You've already forked RekomenciBackend
073c1f75c7
Signed-off-by: ITQ <itq.dev@ya.ru>
376 lines
9.4 KiB
YAML
376 lines
9.4 KiB
YAML
stages:
|
|
- iac
|
|
- build
|
|
- test
|
|
- security
|
|
- tag
|
|
- deploy
|
|
|
|
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
|
|
|
|
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
|
|
|
|
.webhook-template: &webhook-config
|
|
image: curlimages/curl:latest
|
|
script:
|
|
- |
|
|
curl -sf -X POST \
|
|
-H "Content-Type: application/json" \
|
|
-H "Authorization: Bearer $WEBHOOK_SECRET_TOKEN" \
|
|
-H "Webhook-Identifier: $WEBHOOK_BYPASS_TOKEN" \
|
|
"$WEBHOOK_URL"
|
|
rules:
|
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
when: on_success
|
|
|
|
.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
|
|
- update-ca-certificates
|
|
- curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
- export PATH="$HOME/.local/bin:$PATH"
|
|
|
|
ansible-initvm:
|
|
stage: iac
|
|
image: alpine/ansible:2.18.6
|
|
variables:
|
|
ANSIBLE_HOST_KEY_CHECKING: false
|
|
before_script:
|
|
- apk add openssl
|
|
- echo $ENV_PRIVATE_KEY_BASE64 | base64 -d > /id.pem
|
|
- chmod 0600 /id.pem
|
|
- mv "$INVENTORY_ALPHA_VM" ./infrastructure/iac/ansible/inventory/host_vars/alpha.yaml
|
|
- printf "[servers]\nalpha\n" > infrastructure/iac/ansible/inventory/hosts
|
|
script:
|
|
- cd ./infrastructure/iac/ansible
|
|
- ansible-galaxy collection install -r requirements.yaml
|
|
- ansible-galaxy install -r requirements.yaml
|
|
- ansible-playbook -i inventory/hosts site.yaml
|
|
when: manual
|
|
|
|
build-runtime:
|
|
<<: *build-config
|
|
variables:
|
|
IMAGE_NAME: $BASE_IMAGE_NAME/backend
|
|
CONTAINERFILE: Containerfile
|
|
BUILDTARGET: runtime
|
|
|
|
build-tests:
|
|
<<: *build-config
|
|
variables:
|
|
IMAGE_NAME: $BASE_IMAGE_NAME/backend-tests
|
|
CONTAINERFILE: Containerfile
|
|
BUILDTARGET: tests
|
|
|
|
build-migrations:
|
|
<<: *build-config
|
|
variables:
|
|
IMAGE_NAME: $BASE_IMAGE_NAME/backend-migrations
|
|
CONTAINERFILE: Containerfile
|
|
BUILDTARGET: migrations
|
|
|
|
lint:
|
|
<<: *uv-job
|
|
stage: test
|
|
script:
|
|
- source $HOME/.local/bin/env
|
|
- uv sync --group linters --frozen
|
|
- source $UV_PROJECT_ENVIRONMENT/bin/activate
|
|
- just lint
|
|
allow_failure: true
|
|
rules:
|
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
|
- if: $CI_COMMIT_TAG
|
|
|
|
test:
|
|
<<: *buildah-job
|
|
stage: test
|
|
variables:
|
|
COMPOSE_PROFILES: |
|
|
--profile migrations
|
|
--profile tests
|
|
PODMAN_IGNORE_CGROUPSV1_WARNING: True
|
|
script:
|
|
- dnf -y install podman podman-compose
|
|
- export PROFILES="$(printf '%s ' $COMPOSE_PROFILES)"
|
|
- cp "$TEST_STAGE_FIREBASE_CONF" ./infrastructure/configs/backend/firebase.json
|
|
- |
|
|
(
|
|
while true; do
|
|
podman-compose -f compose.yaml $PROFILES logs -f 2>&1
|
|
sleep 1
|
|
done
|
|
) | tee -a compose.log &
|
|
- LOGS_PID=$!
|
|
- |
|
|
REGISTRY_PREFIX=$CI_REGISTRY_IMAGE IMAGE_TAG=$CI_COMMIT_SHA \
|
|
podman-compose -f compose.prod.yaml -f compose.yaml \
|
|
$PROFILES up -d --no-build --pull 2>&1 | tee compose.log
|
|
- |0
|
|
TEST_CONTAINER_ID=$(
|
|
podman-compose ps --all --format json \
|
|
| jq -r '.[] | select(.Labels["io.podman.compose.service"] == "tests") | .Id'
|
|
)
|
|
|
|
if [ -z "$TEST_CONTAINER_ID" ]; then
|
|
echo "Tests container not found."
|
|
exit 1
|
|
fi
|
|
|
|
timeout 600 podman wait "$TEST_CONTAINER_ID"
|
|
TEST_EXIT_CODE=$(podman inspect --format "{{.State.ExitCode}}" "$TEST_CONTAINER_ID")
|
|
|
|
if [ "$TEST_EXIT_CODE" -eq 0 ]; then
|
|
echo "Tests passed."
|
|
else
|
|
echo "Tests failed with exit code $TEST_EXIT_CODE."
|
|
exit 1
|
|
fi
|
|
- |
|
|
podman-compose -f compose.yaml $PROFILES down
|
|
- cat .cov/coverage.txt
|
|
artifacts:
|
|
paths:
|
|
- ./.cov
|
|
- ./compose.log
|
|
reports:
|
|
coverage_report:
|
|
coverage_format: cobertura
|
|
path: .cov/coverage.xml
|
|
expire_in: 1 week
|
|
when: always
|
|
coverage: /TOTAL.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/
|
|
rules:
|
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
|
dependencies:
|
|
- build-runtime
|
|
- build-tests
|
|
- build-migrations
|
|
|
|
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-tests:
|
|
<<: *trivy-image-scan
|
|
variables:
|
|
IMAGE_NAME: $BASE_IMAGE_NAME/backend-tests
|
|
IMAGE_TYPE: tests
|
|
dependencies:
|
|
- build-tests
|
|
|
|
sast-image-migrations:
|
|
<<: *trivy-image-scan
|
|
variables:
|
|
IMAGE_NAME: $BASE_IMAGE_NAME/backend-migrations
|
|
IMAGE_TYPE: migrations
|
|
dependencies:
|
|
- build-migrations
|
|
|
|
tag-runtime:
|
|
<<: *tag-config
|
|
variables:
|
|
IMAGE_NAME: $BASE_IMAGE_NAME/backend
|
|
|
|
tag-tests:
|
|
<<: *tag-config
|
|
variables:
|
|
IMAGE_NAME: $BASE_IMAGE_NAME/backend-tests
|
|
|
|
tag-migrations:
|
|
<<: *tag-config
|
|
variables:
|
|
IMAGE_NAME: $BASE_IMAGE_NAME/backend-migrations
|
|
|
|
webhook-migrations-deploy:
|
|
<<: *webhook-config
|
|
stage: deploy
|
|
variables:
|
|
WEBHOOK_URL: $WEBHOOK_URL_MIGRATIONS
|
|
resource_group: staging
|
|
dependencies:
|
|
- build-migrations
|
|
- sast-image-migrations
|
|
|
|
webhook-backend-deploy:
|
|
<<: *webhook-config
|
|
stage: deploy
|
|
variables:
|
|
WEBHOOK_URL: $WEBHOOK_URL_BACKEND
|
|
environment:
|
|
name: staging
|
|
url: https://hackaton.paas.itqdev.xyz
|
|
resource_group: staging
|
|
dependencies:
|
|
- build-runtime
|
|
- sast-image-runtime
|
|
|
|
workflow:
|
|
rules:
|
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
- if: $CI_COMMIT_TAG
|