Skip to content

Commit fb57e39

Browse files
authored
👷 qontract-api-client and qontract-utils CI/CD (#5412)
* 👷 qontract-api-client and qontract-utils CI/CD * default non-set secret settings * add app-sre-pypi-credentials * fix qontract-api openapi.json diff test
1 parent e4b9476 commit fb57e39

27 files changed

+1595
-155
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
apiVersion: tekton.dev/v1
3+
kind: PipelineRun
4+
metadata:
5+
annotations:
6+
build.appstudio.openshift.io/repo: https://github.com/app-sre/qontract-reconcile?rev={{revision}}
7+
build.appstudio.redhat.com/commit_sha: '{{revision}}'
8+
build.appstudio.redhat.com/pull_request_number: '{{pull_request_number}}'
9+
build.appstudio.redhat.com/target_branch: '{{target_branch}}'
10+
pipelinesascode.tekton.dev/max-keep-runs: "3"
11+
pipelinesascode.tekton.dev/on-cel-expression: (event == "pull_request" && target_branch == "master") || (event == "push" && target_branch.startsWith("gh-readonly-queue/master/"))
12+
labels:
13+
appstudio.openshift.io/application: qontract-reconcile-master
14+
appstudio.openshift.io/component: qontract-api-client-master
15+
pipelines.appstudio.openshift.io/type: build
16+
name: qontract-api-client-master-on-pull-request
17+
namespace: app-sre-tenant
18+
spec:
19+
params:
20+
- name: git-url
21+
value: '{{source_url}}'
22+
- name: revision
23+
value: '{{revision}}'
24+
- name: output-image
25+
value: quay.io/redhat-user-workloads/app-sre-tenant/qontract-reconcile-master/qontract-api-client-master:on-pr-{{revision}}
26+
- name: image-expires-after
27+
value: 5d
28+
- name: dockerfile
29+
value: qontract_api_client/Dockerfile
30+
- name: path-context
31+
value: .
32+
- name: target-stage
33+
value: test
34+
pipelineRef:
35+
params:
36+
- name: url
37+
value: https://github.com/app-sre/shared-pipelines
38+
- name: revision
39+
value: main
40+
- name: pathInRepo
41+
value: pipelines/multi-arch-build-pipeline.yaml
42+
resolver: git
43+
taskRunTemplate:
44+
serviceAccountName: build-pipeline-qontract-api-client-master
45+
workspaces:
46+
- name: workspace
47+
volumeClaimTemplate:
48+
metadata:
49+
creationTimestamp: null
50+
spec:
51+
accessModes:
52+
- ReadWriteOnce
53+
resources:
54+
requests:
55+
storage: 1Gi
56+
status: {}
57+
- name: git-auth
58+
secret:
59+
secretName: '{{ git_auth_secret }}'
60+
status: {}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
apiVersion: tekton.dev/v1
3+
kind: PipelineRun
4+
metadata:
5+
annotations:
6+
build.appstudio.openshift.io/repo: https://github.com/app-sre/qontract-reconcile?rev={{revision}}
7+
build.appstudio.redhat.com/commit_sha: '{{revision}}'
8+
build.appstudio.redhat.com/target_branch: '{{target_branch}}'
9+
pipelinesascode.tekton.dev/max-keep-runs: "3"
10+
pipelinesascode.tekton.dev/on-cel-expression: event == "push" && target_branch == "master"
11+
labels:
12+
appstudio.openshift.io/application: qontract-reconcile-master
13+
appstudio.openshift.io/component: qontract-api-client-master
14+
pipelines.appstudio.openshift.io/type: build
15+
name: qontract-api-client-master-on-push
16+
namespace: app-sre-tenant
17+
spec:
18+
params:
19+
- name: git-url
20+
value: '{{source_url}}'
21+
- name: revision
22+
value: '{{revision}}'
23+
- name: output-image
24+
value: quay.io/redhat-user-workloads/app-sre-tenant/qontract-reconcile-master/qontract-api-client-master:{{revision}}
25+
- name: dockerfile
26+
value: qontract_api_client/Dockerfile
27+
- name: path-context
28+
value: .
29+
- name: target-stage
30+
value: pypi
31+
- name: additional_secret
32+
value: app-sre-pypi-credentials
33+
pipelineRef:
34+
params:
35+
- name: url
36+
value: https://github.com/app-sre/shared-pipelines
37+
- name: revision
38+
value: main
39+
- name: pathInRepo
40+
value: pipelines/multi-arch-build-pipeline.yaml
41+
resolver: git
42+
taskRunTemplate:
43+
serviceAccountName: build-pipeline-qontract-api-client-master
44+
workspaces:
45+
- name: workspace
46+
volumeClaimTemplate:
47+
metadata:
48+
creationTimestamp: null
49+
spec:
50+
accessModes:
51+
- ReadWriteOnce
52+
resources:
53+
requests:
54+
storage: 1Gi
55+
status: {}
56+
- name: git-auth
57+
secret:
58+
secretName: '{{ git_auth_secret }}'
59+
status: {}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
apiVersion: tekton.dev/v1
3+
kind: PipelineRun
4+
metadata:
5+
annotations:
6+
build.appstudio.openshift.io/repo: https://github.com/app-sre/qontract-reconcile?rev={{revision}}
7+
build.appstudio.redhat.com/commit_sha: '{{revision}}'
8+
build.appstudio.redhat.com/pull_request_number: '{{pull_request_number}}'
9+
build.appstudio.redhat.com/target_branch: '{{target_branch}}'
10+
pipelinesascode.tekton.dev/max-keep-runs: "3"
11+
pipelinesascode.tekton.dev/on-cel-expression: (event == "pull_request" && target_branch == "master") || (event == "push" && target_branch.startsWith("gh-readonly-queue/master/"))
12+
labels:
13+
appstudio.openshift.io/application: qontract-reconcile-master
14+
appstudio.openshift.io/component: qontract-utils-master
15+
pipelines.appstudio.openshift.io/type: build
16+
name: qontract-utils-master-on-pull-request
17+
namespace: app-sre-tenant
18+
spec:
19+
params:
20+
- name: git-url
21+
value: '{{source_url}}'
22+
- name: revision
23+
value: '{{revision}}'
24+
- name: output-image
25+
value: quay.io/redhat-user-workloads/app-sre-tenant/qontract-reconcile-master/qontract-utils-master:on-pr-{{revision}}
26+
- name: image-expires-after
27+
value: 5d
28+
- name: dockerfile
29+
value: qontract_utils/Dockerfile
30+
- name: path-context
31+
value: .
32+
- name: target-stage
33+
value: test
34+
pipelineRef:
35+
params:
36+
- name: url
37+
value: https://github.com/app-sre/shared-pipelines
38+
- name: revision
39+
value: main
40+
- name: pathInRepo
41+
value: pipelines/multi-arch-build-pipeline.yaml
42+
resolver: git
43+
taskRunTemplate:
44+
serviceAccountName: build-pipeline-qontract-utils-master
45+
workspaces:
46+
- name: workspace
47+
volumeClaimTemplate:
48+
metadata:
49+
creationTimestamp: null
50+
spec:
51+
accessModes:
52+
- ReadWriteOnce
53+
resources:
54+
requests:
55+
storage: 1Gi
56+
status: {}
57+
- name: git-auth
58+
secret:
59+
secretName: '{{ git_auth_secret }}'
60+
status: {}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
apiVersion: tekton.dev/v1
3+
kind: PipelineRun
4+
metadata:
5+
annotations:
6+
build.appstudio.openshift.io/repo: https://github.com/app-sre/qontract-reconcile?rev={{revision}}
7+
build.appstudio.redhat.com/commit_sha: '{{revision}}'
8+
build.appstudio.redhat.com/target_branch: '{{target_branch}}'
9+
pipelinesascode.tekton.dev/max-keep-runs: "3"
10+
pipelinesascode.tekton.dev/on-cel-expression: event == "push" && target_branch == "master"
11+
labels:
12+
appstudio.openshift.io/application: qontract-reconcile-master
13+
appstudio.openshift.io/component: qontract-utils-master
14+
pipelines.appstudio.openshift.io/type: build
15+
name: qontract-utils-master-on-push
16+
namespace: app-sre-tenant
17+
spec:
18+
params:
19+
- name: git-url
20+
value: '{{source_url}}'
21+
- name: revision
22+
value: '{{revision}}'
23+
- name: output-image
24+
value: quay.io/redhat-user-workloads/app-sre-tenant/qontract-reconcile-master/qontract-utils-master:{{revision}}
25+
- name: dockerfile
26+
value: qontract_utils/Dockerfile
27+
- name: path-context
28+
value: .
29+
- name: target-stage
30+
value: pypi
31+
- name: additional_secret
32+
value: app-sre-pypi-credentials
33+
pipelineRef:
34+
params:
35+
- name: url
36+
value: https://github.com/app-sre/shared-pipelines
37+
- name: revision
38+
value: main
39+
- name: pathInRepo
40+
value: pipelines/multi-arch-build-pipeline.yaml
41+
resolver: git
42+
taskRunTemplate:
43+
serviceAccountName: build-pipeline-qontract-utils-master
44+
workspaces:
45+
- name: workspace
46+
volumeClaimTemplate:
47+
metadata:
48+
creationTimestamp: null
49+
spec:
50+
accessModes:
51+
- ReadWriteOnce
52+
resources:
53+
requests:
54+
storage: 1Gi
55+
status: {}
56+
- name: git-auth
57+
secret:
58+
secretName: '{{ git_auth_secret }}'
59+
status: {}

Makefile

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,3 @@ unittest: ## Run unit tests
117117
.PHONY: generate-client
118118
generate-client:
119119
make -C qontract_api_client generate-client
120-
121-
poc-tests:
122-
make -C qontract_api test
123-
# cd qontract_api_client && make test
124-
make -C qontract_utils test

qontract_api/Dockerfile

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#
22
# Base image with defaults for all stages
3-
FROM registry.access.redhat.com/ubi9-minimal@sha256:90bd85dcd061d1ad6dbda70a867c41958c04a86462d05c631f8205e8870f28f8 AS base
3+
FROM registry.access.redhat.com/ubi9-minimal@sha256:ecd4751c45e076b4e1e8d37ac0b1b9c7271930c094d1bcc5e6a4d6954c6b2289 AS base
44

55
COPY LICENSE /licenses/
66

@@ -12,6 +12,7 @@ ENV \
1212
UV_COMPILE_BYTECODE="true" \
1313
# disable uv cache. it doesn't make sense in a container
1414
UV_NO_CACHE=true \
15+
RUFF_CACHE_DIR=/tmp/.ruff_cache \
1516
# bypass dynamic versioning (git not available)
1617
UV_DYNAMIC_VERSIONING_BYPASS="0.1.0" \
1718
PYTHONUNBUFFERED=1 \
@@ -35,7 +36,7 @@ WORKDIR ${APP_ROOT}/src
3536
#
3637
# Builder image
3738
#
38-
FROM registry.access.redhat.com/ubi9/python-312-minimal@sha256:64a3083a25d9f7573bb9b1a167e10be0464859a8e81421853d09947e873fe500 AS builder
39+
FROM registry.access.redhat.com/ubi9/python-312-minimal@sha256:ecacdd63283ed3083ddd33c02ab5112d4dbf1fbf2508317bf4d4f6d7d913d2f1 AS builder
3940
COPY --from=ghcr.io/astral-sh/uv:0.9.26@sha256:9a23023be68b2ed09750ae636228e903a54a05ea56ed03a934d00fe9fbeded4b /uv /bin/uv
4041

4142
ENV APP_ROOT=/opt/app-root
@@ -65,6 +66,11 @@ RUN cd qontract_api && uv sync --frozen --no-group dev
6566
FROM base AS test
6667
COPY --from=ghcr.io/astral-sh/uv:0.9.26@sha256:9a23023be68b2ed09750ae636228e903a54a05ea56ed03a934d00fe9fbeded4b /uv /bin/uv
6768

69+
USER root
70+
# install dependencies
71+
RUN microdnf install -y diffutils && microdnf clean all
72+
USER 1001
73+
6874
COPY --from=builder /opt/app-root /opt/app-root
6975
RUN cd qontract_api && uv sync --frozen
7076
RUN make -C qontract_api test

qontract_api/Makefile

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
1+
OPENAPI := openapi.json
2+
13
.PHONY: help
24
help:
35
@echo "qontract-api Makefile"
46
@echo ""
57
@echo "Development:"
6-
@echo " make run-api Run FastAPI server locally"
7-
@echo " make run-worker Run Celery worker locally"
8-
@echo " make generate-token SUBJECT=<subject> DAYS=<days>"
9-
@echo " Generate JWT token (default: DAYS=30)"
10-
@echo ""
11-
@echo "Docker:"
12-
@echo " make docker-up Start all services"
13-
@echo " make docker-down Stop all services"
14-
@echo " make docker-build Rebuild images"
15-
@echo " make docker-logs View logs"
8+
@echo " make run-api Run FastAPI server locally"
9+
@echo " make run-worker Run Celery worker locally"
10+
@echo " make generate-token SUBJECT=<subject> EXPIRES_DAYS=<days> Generate JWT token"
11+
@echo " make generate-openapi-spec Generate OpenAPI spec file"
1612
@echo ""
1713
@echo "Quality:"
18-
@echo " make test Run all checks (pytest, mypy, ruff)"
19-
@echo " make format Format and fix code with ruff"
14+
@echo " make test Run all checks (pytest, mypy, ruff)"
15+
@echo " make format Format and fix code with ruff"
2016

2117
.PHONY: run-api
2218
run-api:
@@ -30,29 +26,32 @@ run-worker:
3026
generate-token:
3127
@if [ -z "$(SUBJECT)" ]; then \
3228
echo "Error: SUBJECT is required"; \
33-
echo "Usage: make generate-token SUBJECT=admin DAYS=30"; \
29+
echo "Usage: make generate-token SUBJECT=admin EXPIRES_DAYS=365"; \
3430
exit 1; \
3531
fi
36-
@uv run python -m qontract_api.scripts.generate_token --subject "$(SUBJECT)" --expires-days $(or $(DAYS),30)
37-
38-
.PHONY: docker-up
39-
docker-up:
40-
cd .. && docker compose up
41-
42-
.PHONY: docker-down
43-
docker-down:
44-
cd .. && docker compose down
45-
46-
.PHONY: docker-build
47-
docker-build:
48-
cd .. && docker compose build
32+
@if [ -z "$(EXPIRES_DAYS)" ]; then \
33+
echo "Error: SUBJECT is required"; \
34+
echo "Usage: make generate-token SUBJECT=admin EXPIRES_DAYS=365"; \
35+
exit 1; \
36+
fi
37+
@uv run python -m qontract_api.scripts.generate_token --subject "$(SUBJECT)" --expires-days "$(EXPIRES_DAYS)"
4938

50-
.PHONY: docker-logs
51-
docker-logs:
52-
cd .. && docker compose logs -f
39+
.PHONY: generate-openapi-spec
40+
generate-openapi-spec:
41+
@uv run python -m qontract_api.scripts.generate_openapi_spec > $(OPENAPI)
5342

5443
.PHONY: test
5544
test:
45+
@TEMP_DIR=$$(mktemp -d); \
46+
trap "rm -rf $$TEMP_DIR" EXIT; \
47+
$(MAKE) generate-openapi-spec OPENAPI=$$TEMP_DIR/openapi.json; \
48+
if ! diff -q $(OPENAPI) $$TEMP_DIR/openapi.json > /dev/null 2>&1; then \
49+
echo " ✗ openapi.json differs from generated version"; \
50+
echo ""; \
51+
echo "Run 'make generate-openapi-spec' to update."; \
52+
echo ""; \
53+
exit 1; \
54+
fi
5655
uv run ruff check .
5756
uv run ruff format --check .
5857
uv run mypy .

0 commit comments

Comments
 (0)