variables: YARN_CACHE_FOLDER: '$CI_PROJECT_DIR/.yarn/cache' YARN_ENABLE_GLOBAL_CACHE: 'false' # This variable needs to be named differently than in triggering projects # because if not, it gets set to '/api_domain', which breaks the e2e stage # due to the file not being in the artifacts. API_DOMAIN_FILE: '$CI_PROJECT_DIR/api_domain' .yarn-cache-rw: key: files: - yarn.lock paths: - .yarn/ policy: pull-push .yarn-cache-readonly: key: files: - yarn.lock paths: - .yarn/ policy: pull default: before_script: - set -e # env -0 | sort -z | tr '\0' '\n': Sort env output alphabetically, keeping multiline variables intact # egrep: Remove sensitive information from the output of env #- env -0 | sort -z | tr '\0' '\n' | egrep -ve '^(DOCKER_AUTH_CONFIG|GOOGLE_APPLICATION_CREDENTIALS)=.*' interruptible: true tags: - 1cpu-4gb # build on smaller machine stages: - prepare - build - deploy - smoketest - destroy # job templates .deploy: image: name: 'europe-north1-docker.pkg.dev/holi-shared/docker-hub-remote/hashicorp/terraform:1.11.1' # default entrypoint is terraform command, but we want to run shell scripts entrypoint: ['/bin/sh', '-c'] variables: ENVIRONMENT_ID: $CI_ENVIRONMENT_SLUG artifacts: paths: - 'terraform/environments/crash.log' # optional, only available in case of a crash/panic - 'terraform/environments/terraform-*.log' # separate log for every step/command - $API_DOMAIN_FILE name: '${CI_JOB_NAME}_${CI_JOB_ID}' #when: on_failure expire_in: 1 week script: - terraform/environments/scripts/create-or-update-env.sh "$ENVIRONMENT_ID" "${CI_COMMIT_SHA}_${CI_PIPELINE_IID}" - echo "$(terraform/environments/scripts/get-output.sh api_domain)" > "$API_DOMAIN_FILE" resource_group: $ENVIRONMENT_ID # never execute terraform in parallel on the same environment interruptible: false .smoketest: stage: 'smoketest' image: 'europe-north1-docker.pkg.dev/holi-shared/docker/holi-docker/holi-k6-builder' script: - API_DOMAIN=$(cat "$API_DOMAIN_FILE") - terraform/environments/scripts/wait-for-ssl.sh "https://${API_DOMAIN}" - BASE_URL="https://${API_DOMAIN}/graphql" k6 run smoketest/main.js # TODO should/could we roll back the service to the last working revision on test failure? resource_group: $CI_COMMIT_REF_NAME # only 1 job per branch # end job templates # pipeline in chronological order ## common steps install_deps: stage: prepare image: 'europe-north1-docker.pkg.dev/holi-shared/docker-hub-remote/node:22-slim' cache: !reference [.yarn-cache-rw] script: - corepack enable - yarn install --immutable rules: - if: $CI_COMMIT_BRANCH changes: - yarn.lock - .gitlab-ci.yml resource_group: $ENVIRONMENT_ID # only 1 job per branch install_lint_test: stage: build needs: - job: install_deps optional: true image: 'europe-north1-docker.pkg.dev/holi-shared/docker-hub-remote/node:22-slim' cache: !reference [.yarn-cache-rw] script: - corepack enable # If CI Cache is empty because install_deps did not run, install filling the cache, otherwise install from the immutable cache # install_deps does not run on long living branches, and it might not run on pipeline failures on the first build of a branch - '[ ! -d ".yarn/cache" ] && yarn install --immutable || yarn install --immutable --immutable-cache' - yarn lint - yarn test tags: - 4cpu-4gb resource_group: $CI_COMMIT_REF_NAME # only 1 job per branch # You can override the included template(s) by including variable overrides # SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings # Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings # Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings # Note that environment variables can be set in several places # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence sast: needs: ['install_lint_test'] stage: build resource_group: $CI_COMMIT_REF_NAME # only 1 job per branch include: - template: Security/SAST.gitlab-ci.yml .build_mesh: needs: ['install_lint_test'] image: 'europe-north1-docker.pkg.dev/holi-shared/docker-hub-remote/node:22-slim' cache: !reference [.yarn-cache-readonly] script: - corepack enable - yarn install --immutable --immutable-cache - yarn run mesh build - yarn run mesh validate tags: - 4cpu-4gb artifacts: paths: - '.mesh/' resource_group: $CI_COMMIT_REF_NAME # only 1 job per branch .build_docker: needs: ['install_lint_test'] image: 'europe-north1-docker.pkg.dev/holi-shared/docker-hub-remote/docker:28' services: - name: 'europe-north1-docker.pkg.dev/holi-shared/docker-hub-remote/docker:28-dind' alias: 'docker' variables: # this could be fetched via terraform output ("gcr_location" in infra project), but then we would need an extra job for terraform GCR_IMAGE: europe-north1-docker.pkg.dev/holi-shared/docker/holi-unified-api script: - docker pull "$GCR_IMAGE" || true # Allows us to use --cache-from, we need to tag with latest in the next command for this to work - docker build --cache-from "$GCR_IMAGE" -t "$GCR_IMAGE":latest -t "$GCR_IMAGE":"${CI_COMMIT_SHA}_${CI_PIPELINE_IID}" -t "$GCR_IMAGE":"$CI_COMMIT_REF_SLUG" . - docker push "$GCR_IMAGE":"${CI_COMMIT_SHA}_${CI_PIPELINE_IID}" # this is the tag that is used for deployment - docker push "$GCR_IMAGE":"$CI_COMMIT_REF_SLUG" # just for easyly knowing which is the last image for a branch - docker push "$GCR_IMAGE":latest # for caching the build resource_group: $CI_COMMIT_REF_NAME # only 1 job per branch development_build_mesh: stage: build extends: .build_mesh variables: # these could be fetched via terraform output ("gcr_location" in infra project), but then we would need an extra job for terraform DONATIONS_API_URL: https://staging.donations.apis.holi.social/graphql GEO_API_URL: https://staging.geo.apis.holi.social/graphql GOODNEWS_API_URL: https://staging.goodnews.apis.holi.social/graphql OKUNA_URL: https://staging.social.apis.holi.social/graphql VOLUNTEERING_API_URL: https://staging.volunteering.apis.holi.social/graphql NOTIFICATIONS_API_URL: https://staging.notifications.apis.holi.social/graphql TRANSLATION_API_URL: https://staging.translation.apis.holi.social/graphql MODERATION_BACKEND_URL: https://staging.moderation.apis.holi.social/graphql REDIS_HOST: 10.104.0.3 REDIS_PORT: 6379 REDIS_DB: 5 rules: - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "production" when: on_success development_build_docker: stage: build extends: .build_docker needs: ['development_build_mesh'] variables: ENVIRONMENT_ID: staging rules: - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "production" when: on_success ## review environments review_deploy: stage: deploy extends: .deploy needs: ['development_build_docker'] environment: name: review/$CI_COMMIT_REF_SLUG url: https://$CI_ENVIRONMENT_SLUG.unified.apis.holi.social on_stop: review_destroy auto_stop_in: 1 week rules: - if: $CI_COMMIT_BRANCH =~ /^main$|^production$|^noenv\/.*/ when: never - if: $CI_COMMIT_BRANCH when: on_success review_smoketest: extends: .smoketest needs: ['review_deploy'] rules: - if: $CI_COMMIT_BRANCH =~ /^main$|^production$|^noenv\/.*/ when: never - if: $CI_COMMIT_BRANCH when: on_success review_destroy: stage: destroy needs: ['review_deploy'] image: name: 'europe-north1-docker.pkg.dev/holi-shared/docker-hub-remote/hashicorp/terraform:1.11.1' # default entrypoint is terraform command, but we want to run shell scripts entrypoint: ['/bin/sh', '-c'] variables: # has to be set to none for auto stop GIT_STRATEGY: none ENVIRONMENT_ID: $CI_ENVIRONMENT_SLUG environment: name: review/$CI_COMMIT_REF_SLUG action: stop dependencies: [] # explicitly disable artifact usage script: # branch may have been deleted, so we clone and checkout main - git clone "$CI_REPOSITORY_URL" main-clone - cd main-clone - terraform/environments/scripts/destroy-env.sh "$CI_ENVIRONMENT_SLUG" # can't use rules here: https://gitlab.com/gitlab-org/gitlab/-/issues/34077 allow_failure: true rules: - if: $CI_COMMIT_BRANCH =~ /^main$|^production$|^noenv\/.*/ when: never - if: $CI_COMMIT_BRANCH when: manual resource_group: $ENVIRONMENT_ID # never execute terraform in parallel on the same environment interruptible: false ## staging environment staging_deploy: stage: deploy extends: .deploy needs: ['development_build_docker'] environment: name: staging deployment_tier: staging url: https://staging.unified.apis.holi.social variables: ENVIRONMENT_ID: staging rules: - if: $CI_COMMIT_BRANCH == "main" when: on_success staging_smoketest: extends: .smoketest needs: ['staging_deploy'] rules: - if: $CI_COMMIT_BRANCH == "main" when: on_success ## production environment production_build_mesh: stage: build extends: .build_mesh variables: # these could be fetched via terraform output ("gcr_location" in infra project), but then we would need an extra job for terraform DONATIONS_API_URL: https://production.donations.apis.holi.social/graphql GEO_API_URL: https://production.geo.apis.holi.social/graphql GOODNEWS_API_URL: https://production.goodnews.apis.holi.social/graphql OKUNA_URL: https://production.social.apis.holi.social/graphql VOLUNTEERING_API_URL: https://production.volunteering.apis.holi.social/graphql NOTIFICATIONS_API_URL: https://production.notifications.apis.holi.social/graphql TRANSLATION_API_URL: https://production.translation.apis.holi.social/graphql MODERATION_BACKEND_URL: https://moderation.apis.holi.social/graphql REDIS_HOST: 10.104.0.3 REDIS_PORT: 6379 REDIS_DB: 13 rules: - if: $CI_COMMIT_BRANCH == "production" when: on_success production_build_docker: stage: build extends: .build_docker needs: ['production_build_mesh'] variables: ENVIRONMENT_ID: production rules: - if: $CI_COMMIT_BRANCH == "production" when: on_success production_deploy: stage: deploy extends: .deploy needs: ['production_build_docker'] allow_failure: false environment: name: production deployment_tier: production url: https://production.unified.apis.holi.social variables: ENVIRONMENT_ID: production rules: - if: $CI_COMMIT_BRANCH == "production" when: on_success production_smoketest: extends: .smoketest needs: ['production_deploy'] rules: - if: $CI_COMMIT_BRANCH == "production" when: on_success trigger_docs_generation: stage: deploy needs: ['production_deploy'] trigger: project: app/app.gitlab-pages.holi.team branch: main strategy: depend forward: yaml_variables: false pipeline_variables: false rules: - if: $CI_COMMIT_BRANCH == "production" when: on_success resource_group: docs-deploy