From e6f49c8e97e4abf3cb715cc2a701b412c106c7e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Bu=C5=88ata?= Date: Mon, 5 Jan 2026 20:54:15 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Modular=20pipeline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pipeline/cloudrun-gitlab/.gitlab-ci.yml | 264 +++++------------- 1 file changed, 69 insertions(+), 195 deletions(-) diff --git a/starter/pipeline/cloudrun-gitlab/.gitlab-ci.yml b/starter/pipeline/cloudrun-gitlab/.gitlab-ci.yml index 96d8ddc..0389d77 100644 --- a/starter/pipeline/cloudrun-gitlab/.gitlab-ci.yml +++ b/starter/pipeline/cloudrun-gitlab/.gitlab-ci.yml @@ -1,208 +1,82 @@ # Define environments in GitLab UI with vars according to the branches for the pipeline -# ENVIRONMENT={{develpoment/stage/production}} -# GCP_PROJECT_ID={{PROJECT_NAME}} +# GCP_PROJECT_ID=node-app # GCP_REGION={{europe-west3}} -# GCP_SECRETS_NAME={{PROJECT_NAME}} +# GCP_SECRETS_NAME=node-app # GCP_SECRETS_VERSION=latest # GCP_SA_KEY={{base64 encoded string with SA key to deploy Cloud Run}} # GCP_CLOUD_RUN_SA_NAME={{name of the service account for Cloud Run}} - -variables: - # Default configuration, check .export_variables job for calculated env variables based on branch config - # Node image for pipeline runner - NODE_BASE_IMAGE: node:24.5.0 - # Where to store json secrets from Cloud provider - SECRETS_PATH: '/config/secrets.json' - - ## GCP configuration ## - # Where to temporary store Google service account - GCP_SA_KEY_JSON_PATH: /tmp/key.json - - ## Docker artifact registry configuration ## - # Project name for docker compose CI job runs - DOCKER_COMPOSE_PROJECT_NAME: $CI_PROJECT_NAME-job-$CI_JOB_ID - # Build docker version tag - DOCKER_IMAGE_TAG: $CI_COMMIT_SHORT_SHA - -default: - image: ackee/gitlab-builder - before_script: - - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}" >> .npmrc - - echo "//${CI_SERVER_HOST}/api/v4/packages/npm/:_authToken=${CI_JOB_TOKEN}" >> .npmrc; - -cache: &docker_cache - key: "$CI_COMMIT_REF_NAME" - paths: - - app_image*.tar - policy: pull +# GCP_CLOUD_RUN_ALLOCATED_MEMORY={{allocated memory for Cloud Run}} +# GCP_SQL_INSTANCE_NAME={{name of the SQL instance for Cloud Run}} stages: - build - test + - push - deploy -## -# HELPERS -## -# Before script extension that exports ci-branch-config environment variables and stores the GCP service -# account on the disk to be used by another jobs in the CI. This should be extended by every job that uses -# any of the branch configuration, docker image or CI SA -.export_variables: - before_script: - - export DOCKER_REGISTRY_URL="$GCP_REGION-docker.pkg.dev" - - export DOCKER_IMAGE_NAME="$DOCKER_REGISTRY_URL/$GCP_PROJECT_ID/${GCP_PROJECT_ID}-docker/$CI_PROJECT_NAME" - - export DOCKER_IMAGE_BUILDER_NAME="$DOCKER_IMAGE_NAME-builder" - - echo "$GCP_SA_KEY" | base64 -d > "$GCP_SA_KEY_JSON_PATH" - - -# Fetches built docker builder image from remote storage or cache -.fetch_build_image: &fetch_build_image - - | - if ! docker inspect --type=image "$DOCKER_IMAGE_BUILDER_NAME:$DOCKER_IMAGE_TAG" >/dev/null; then - docker load -i app_image_builder.tar - fi - -## -# BUILD STAGE -## -# Builds the builder docker image that can be used for running jobs using the CI docker dependencies and -# configuration (tests, lint, audit, ...) -build image: - stage: build - interruptible: true - extends: .export_variables - script: - - | - echo "app_image*" >> .dockerignore - docker build --target builder \ - -t "$DOCKER_IMAGE_BUILDER_NAME:$DOCKER_IMAGE_TAG" . - - docker save "$DOCKER_IMAGE_BUILDER_NAME:$DOCKER_IMAGE_TAG" > app_image_builder.tar - cache: - <<: *docker_cache - policy: push - when: on_success - -## -# TEST STAGE -## -# Performs npm ci-lint script in builder image. -# Make sure the ci-lint outputs json file "output/checkstyle-result.json" that reports the result of the linter -lint: - stage: test - interruptible: true - extends: .export_variables - script: - - if [ "$SKIP_LINT" == "true" ]; then warn "Lint skipped."; exit 0; fi - - *fetch_build_image - - cd "$CI_PROJECT_DIR/docker-compose" - - | - DOCKER_IMAGE_NAME="$DOCKER_IMAGE_BUILDER_NAME" docker-compose -p "$DOCKER_COMPOSE_PROJECT_NAME" \ - -f docker-compose.yml -f docker-compose.ci.yml \ - run --rm --no-deps app npm run ci-lint - needs: - - build image - artifacts: - reports: - codequality: output/checkstyle-result.json - -# Npm audit run inside of builder image -npm audit: - stage: test - interruptible: true - extends: .export_variables - script: - - if [ "$SKIP_AUDIT" == "true" ]; then warn "Audit skipped."; exit 0; fi - - *fetch_build_image - - cd "$CI_PROJECT_DIR/docker-compose" - - | - DOCKER_IMAGE_NAME="$DOCKER_IMAGE_BUILDER_NAME" docker-compose -p "$DOCKER_COMPOSE_PROJECT_NAME" \ - -f docker-compose.yml -f docker-compose.ci.yml \ - run --rm --no-deps app npm audit --production --audit-level=high - needs: - - build image - -# Test job running npm ci-test script. Make sure the ci-test script exports two files on disk: -# output/test.xml - jUnit reporter with test results -# output/cobertura-coverage.xml - Test coverage results -test: - stage: test - interruptible: true - extends: .export_variables - script: - - if [ "$SKIP_TESTS" == "true" ]; then warn "Tests skipped."; exit 0; fi - - *fetch_build_image - - cd "$CI_PROJECT_DIR/docker-compose" - - | - DOCKER_IMAGE_NAME="$DOCKER_IMAGE_BUILDER_NAME" \ - docker-compose -p "$DOCKER_COMPOSE_PROJECT_NAME" \ - -f docker-compose.yml -f docker-compose.ci.yml \ - run --rm -e RUN_DOCKER_COMPOSE_DEPS=true -e DB_HOST=postgres app npm run ci-test - artifacts: - when: always - reports: - junit: output/test.xml - coverage_report: - coverage_format: cobertura - path: output/cobertura-coverage.xml - needs: - - build image +variables: + # Node image for pipeline runner + NODEJS_VERSION: "24.12.0" + # Where to store json secrets from Cloud provider + SECRETS_PATH: '/config/secrets.json' + # Port for Cloud Run + PORT: "3000" + # Docker image name for Cloud Run + IMAGE_NAME: $GCP_REGION-docker.pkg.dev/$GCP_PROJECT_ID/$GCP_PROJECT_ID-docker/$CI_PROJECT_NAME:$CI_COMMIT_SHA -## -# DEPLOY STAGE -## -# Build production image and push to registry -# Signs in with GCP SA key from pipeline, perform build of the image and pushes it to remote registry -# Make sure /ci-branch-config-name/{branch} exists when adding new branches to "only" field -build and push to registry: - stage: deploy - extends: .export_variables - script: - - docker login -u _json_key --password-stdin $DOCKER_REGISTRY_URL < "$GCP_SA_KEY_JSON_PATH" - - set -a && source ci-branch-config/${CI_COMMIT_REF_NAME}.env && set +a - - | - docker build \ - -t "$DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG" \ - $(for var in $(cat ci-branch-config/${CI_COMMIT_REF_NAME}.env | sed 's/=.*//'); do echo "--build-arg $var=${!var} "; done) \ - --build-arg "SECRETS_PATH=$SECRETS_PATH" \ - . - - docker push "$DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG" - needs: - - build image - - npm audit - - test - environment: - name: $CI_COMMIT_REF_NAME - only: - - development - - stage - - master -# Deploy to Google Cloud Run based on image stored on remote registry -deploy cloud run: - stage: deploy - image: google/cloud-sdk:slim - extends: .export_variables - script: - - gcloud auth activate-service-account --key-file "$GCP_SA_KEY_JSON_PATH" - - gcloud config set project $GCP_PROJECT_ID - - gcloud auth configure-docker - - | - gcloud run deploy wake-arena-project-api \ - --image "$DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG" \ - --project "$GCP_PROJECT_ID" \ - --platform managed \ - --port 3000 \ - --region "$GCP_REGION" \ - --allow-unauthenticated \ - --memory "$GCP_CLOUD_RUN_ALLOCATED_MEMORY" \ - --service-account="$GCP_CLOUD_RUN_SA_NAME" \ - --set-secrets=$SECRETS_PATH="$GCP_SECRETS_NAME:$GCP_SECRETS_VERSION" \ - --set-cloudsql-instances="$GCP_PROJECT_ID:$GCP_REGION:$GCP_SQL_INSTANCE_NAME" - only: - - development - - stage - - master - environment: - name: $CI_COMMIT_REF_NAME - needs: - - build and push to registry +include: + # BUILD APP + - component: $CI_SERVER_FQDN/Backend/gitlab-components/build@v1.0.0 + inputs: + job-stage: build + # BUILD DOCKER IMAGE + - component: $CI_SERVER_FQDN/Backend/gitlab-components/docker-build@v1.0.0 + inputs: + job-stage: build + allowed-branches: "master|stage|development" + image-tag: $IMAGE_NAME + # CODE QUALITY + - component: $CI_SERVER_FQDN/Backend/gitlab-components/codequality@v1.0.0 + inputs: + job-stage: test + # CODE STYLE + - component: $CI_SERVER_FQDN/Backend/gitlab-components/codestyle@v1.0.0 + inputs: + job-stage: test + # AUDIT + - component: $CI_SERVER_FQDN/Backend/gitlab-components/audit@v1.0.0 + inputs: + job-stage: test + audit-command: npm audit --production --audit-level=high + # TEST + - component: $CI_SERVER_FQDN/Backend/gitlab-components/test@v1.0.0 + inputs: + job-stage: test + test-command: DB_CONNECTION_STRING="postgres://node-app_docker:node-app_docker@postgres:5432/postgres" npm run ci-test + postgres-user: node-app_docker + postgres-password: node-app_docker + postgres-db: postgres + # PUSH DOCKER IMAGE + - component: $CI_SERVER_FQDN/Backend/gitlab-components/artifact-registry-push@v1.0.0 + inputs: + job-stage: push + allowed-branches: "master|stage|development" + image-name: $IMAGE_NAME + registry: $GCP_REGION-docker.pkg.dev + # DEPLOY TO CLOUD RUN + - component: $CI_SERVER_FQDN/Backend/gitlab-components/cloudrun-deploy@v1.0.0 + inputs: + job-stage: deploy + allowed-branches: "master|stage|development" + deploy-command: >- + gcloud run deploy $CI_PROJECT_NAME + --image $IMAGE_NAME + --project "$GCP_PROJECT_ID" + --platform managed + --port $PORT + --region "$GCP_REGION" + --allow-unauthenticated + --memory "$GCP_CLOUD_RUN_ALLOCATED_MEMORY" + --service-account="$GCP_CLOUD_RUN_SA_NAME" + --set-secrets=$SECRETS_PATH="$GCP_SECRETS_NAME:$GCP_SECRETS_VERSION"