From 887af785f66c8e3c2a7ec5ac87bc63cc3941b4f5 Mon Sep 17 00:00:00 2001 From: ITQ Date: Mon, 23 Feb 2026 23:30:47 +0300 Subject: [PATCH] ci: added CI/CD --- .gitlab-ci.yml | 265 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..b834b39 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,265 @@ +stages: + - build + - style + - test + - security + - tag + +default: + retry: 2 + +variables: + BASE_IMAGE_NAME: $CI_REGISTRY_IMAGE + TRIVY_CACHE_DIR: .cache/trivy + TRIVY_NO_PROGRESS: "true" + TRIVY_TIMEOUT: "10m0s" + TRIVY_USERNAME: $CI_REGISTRY_USER + TRIVY_PASSWORD: $CI_REGISTRY_PASSWORD + TRIVY_REGISTRY: $CI_REGISTRY + UV_PROJECT_ENVIRONMENT: .venv + UV_CACHE_DIR: .cache/uv + BUILDAH_ISOLATION: oci + STORAGE_DRIVER: vfs + DOCKER_HOST: "tcp://docker:2375" + DOCKER_TLS_CERTDIR: "" + +cache: + key: "${CI_COMMIT_REF_SLUG}" + paths: + - $TRIVY_CACHE_DIR + - $UV_CACHE_DIR + - $UV_PROJECT_ENVIRONMENT + policy: pull-push + +.buildah-job: &buildah-job + image: quay.io/containers/buildah:latest + variables: + STORAGE_DRIVER: vfs + before_script: + - buildah login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + +.trivy-fs-template: &trivy-fs-scan + stage: security + image: + name: aquasec/trivy:latest + entrypoint: [""] + cache: + paths: + - $TRIVY_CACHE_DIR + policy: pull-push + before_script: + - mkdir -p $TRIVY_CACHE_DIR + script: + - trivy filesystem --skip-files $TRIVY_CACHE_DIR --format cyclonedx --output fs-sbom.json . + - trivy filesystem --skip-files $TRIVY_CACHE_DIR --format sarif --output gl-sast-fs-report.json . + allow_failure: true + artifacts: + reports: + sast: gl-sast-fs-report.json + paths: + - fs-sbom.json + - gl-sast-fs-report.json + expire_in: 1 week + when: always + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + - if: $CI_COMMIT_TAG + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + - if: $SAST_DISABLED + when: never + +.trivy-image-template: &trivy-image-scan + stage: security + image: + name: aquasec/trivy:latest + entrypoint: [""] + cache: + paths: + - $TRIVY_CACHE_DIR + policy: pull-push + before_script: + - mkdir -p $TRIVY_CACHE_DIR + script: + - | + trivy image \ + --scanners vuln \ + --format cyclonedx \ + --output image-sbom-${IMAGE_TYPE}.json \ + $IMAGE_NAME:$CI_COMMIT_SHA + - | + trivy image \ + --format sarif \ + --output gl-sast-image-${IMAGE_TYPE}-report.json \ + $IMAGE_NAME:$CI_COMMIT_SHA + allow_failure: true + artifacts: + reports: + sast: gl-sast-image-${IMAGE_TYPE}-report.json + paths: + - image-sbom-${IMAGE_TYPE}.json + - gl-sast-image-${IMAGE_TYPE}-report.json + expire_in: 1 week + when: always + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + - if: $CI_COMMIT_TAG + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + - if: $SAST_DISABLED + when: never + +.build-template: &build-config + <<: *buildah-job + stage: build + script: + - | + buildah bud \ + --tag $IMAGE_NAME:$CI_COMMIT_SHA \ + --file $CONTAINERFILE \ + --target $BUILDTARGET \ + --layers \ + --cache-from $IMAGE_NAME-cache \ + --cache-to $IMAGE_NAME-cache \ + . + - buildah push $IMAGE_NAME:$CI_COMMIT_SHA + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + when: always + - if: $CI_COMMIT_TAG + when: always + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + when: manual + allow_failure: true + +.tag-template: &tag-config + <<: *buildah-job + stage: tag + script: + - | + set -euo pipefail + + buildah pull $IMAGE_NAME:$CI_COMMIT_SHA + + if [ -n "${CI_COMMIT_TAG:-}" ]; then + buildah tag $IMAGE_NAME:$CI_COMMIT_SHA $IMAGE_NAME:$CI_COMMIT_TAG + buildah push $IMAGE_NAME:$CI_COMMIT_TAG + fi + + if [ -n "${CI_COMMIT_BRANCH:-}" ]; then + buildah tag $IMAGE_NAME:$CI_COMMIT_SHA $IMAGE_NAME:$CI_COMMIT_REF_SLUG + buildah push $IMAGE_NAME:$CI_COMMIT_REF_SLUG + + if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ]; then + buildah tag $IMAGE_NAME:$CI_COMMIT_SHA $IMAGE_NAME:latest + buildah push $IMAGE_NAME:latest + fi + fi + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + - if: $CI_COMMIT_TAG + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + when: manual + allow_failure: true + +.uv-job: &uv-job + image: debian:trixie-slim + cache: + key: "${CI_JOB_NAME}-${CI_COMMIT_REF_SLUG}" + paths: + - $UV_PROJECT_ENVIRONMENT + - $UV_CACHE_DIR + policy: pull-push + before_script: + - apt-get update + - apt-get install -y --no-install-recommends ca-certificates curl just git + - update-ca-certificates + - curl -LsSf https://astral.sh/uv/install.sh | sh + - export PATH="$HOME/.local/bin:$PATH" + +build-runtime: + <<: *build-config + variables: + IMAGE_NAME: $BASE_IMAGE_NAME/backend + CONTAINERFILE: Containerfile + BUILDTARGET: runtime + +build-staticfiles: + <<: *build-config + variables: + IMAGE_NAME: $BASE_IMAGE_NAME/backend-staticfiles + CONTAINERFILE: Containerfile + BUILDTARGET: staticfiles + +lint: + <<: *uv-job + stage: style + script: + - uv sync --frozen + - just lint + allow_failure: true + +format: + <<: *uv-job + stage: style + script: + - uv sync --frozen + - just format + allow_failure: true + +test: + <<: *uv-job + stage: test + script: + - just ci-test + artifacts: + paths: + - reports/ + - .cov/ + reports: + junit: reports/junit.xml + coverage_report: + coverage_format: cobertura + path: .cov/coverage.xml + expire_in: 1 week + when: always + coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/' + dependencies: + - build-runtime + +sast-filesystem: + <<: *trivy-fs-scan + +sast-image-runtime: + <<: *trivy-image-scan + variables: + IMAGE_NAME: $BASE_IMAGE_NAME/backend + IMAGE_TYPE: runtime + dependencies: + - build-runtime + +sast-image-staticfiles: + <<: *trivy-image-scan + variables: + IMAGE_NAME: $BASE_IMAGE_NAME/backend-staticfiles + IMAGE_TYPE: staticfiles + dependencies: + - build-staticfiles + +tag-runtime: + <<: *tag-config + variables: + IMAGE_NAME: $BASE_IMAGE_NAME/backend + dependencies: + - build-runtime + +tag-staticfiles: + <<: *tag-config + variables: + IMAGE_NAME: $BASE_IMAGE_NAME/backend-staticfiles + dependencies: + - build-staticfiles + +workflow: + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + - if: $CI_COMMIT_TAG