Trigger and wait in gitlab pipeline

Viewed 782

I have 3 projects in Gitlab.

  1. Frontend
  2. Backend
  3. Deployment Each project has separate pipeline definition which has CI pipeline and using Multi-project pipeline concept, it will invoke the deployment project pipeline for deploying each module.

Frontend

image: frontend:runner1.1

# Cache modules in between jobs
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .npm/

variables:
  GIT_SUBMODULE_STRATEGY: recursive
  JAVA_OPTS: "Dlog4j.formatMsgNoLookups=true"
  LOG4J_FORMAT_MSG_NO_LOOKUPS: "true"

stages:
  - VersionCheck
  - Static Analysis
  - Test
  - SonarQube
  - Tag
  - Version 
  - Build
  - Deploy

.build:
  stage: Build
  image: google/cloud-sdk
  services:
    - docker:dind
  before_script:
    - mkdir -p $HOME/.docker && echo $DOCKER_AUTH_CONFIG > $HOME/.docker/config.json
  script:
    - echo $CI_REGISTRY_USER
    - echo $CI_REGISTRY
    - echo ${IMAGE_TAG}
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $IMAGE_TAG . --build-arg REACT_APP_ENV=${CI_COMMIT_BRANCH} --build-arg REACT_APP_BACKEND_API=${REACT_APP_BACKEND_API} --build-arg REACT_APP_GOOGLE_CLIENT_ID=${REACT_APP_GOOGLE_CLIENT_ID}
    - docker push $IMAGE_TAG

VersionCheck:
  stage: VersionCheck
  allow_failure: false
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "sandbox"'
  before_script:
    - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME:$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
    - git fetch origin $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME:$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
  script:
    - deployed_version=`git show $CI_MERGE_REQUEST_TARGET_BRANCH_NAME:package.json | sed -nE 's/^\\s*\"version\"\:\ \"(.*?)\",$/\\1/p'`
    - new_version=`git show $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME:package.json | sed -nE 's/^\\s*\"version\"\:\ \"(.*?)\",$/\\1/p'`
    - >
      echo "sandbox version: $deployed_version"
      echo "feature version: $new_version"

      if [ "$(printf '%s\n' "$deployed_version" "$new_version" | sort -V | head -n1)" = "$deployed_version" ]; then
        echo "version is incremented"
      else
        echo "Version need to be incremented on the feature branch. See the README.md file"
        exit 1  
      fi

eslint:
  stage: Static Analysis
  allow_failure: false
  before_script:
    - npm ci --cache .npm --prefer-offline
  script:
    - echo "Start building App"
    - npm install
    - npm run eslint-report
    - echo "Build successfully!"
  artifacts:
    reports:
      junit: coverage/eslint-report.xml
    paths:
      - coverage/eslint-report.json

test:
  stage: Test
  allow_failure: false
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: always
    - when: always
  before_script:
    - npm ci --cache .npm --prefer-offline
  script:
    - echo "Testing App"
    - npm install
    - npm run generate-tests-report
    - echo "Test successfully!"
  artifacts:
    reports:
      junit: junit.xml
    paths:
      - test-report.xml
      - coverage/lcov.info    

sonarqube-check:
  stage: SonarQube
  allow_failure: true
  image:
    name: sonarsource/sonar-scanner-cli:4.6
    entrypoint: [""]
  variables:
    SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
    GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task
  cache:
    key: "${CI_JOB_NAME}"
    paths:
      - .sonar/cache
  script:
    # wait for the quality results, true/false
    - sonar-scanner -X -Dsonar.qualitygate.wait=false -Dsonar.branch.name=$CI_COMMIT_BRANCH -Dsonar.login=$SONAR_TOKEN  -Dsonar.projectVersion=$(npm run print-version --silent)
  only:
    - merge_requests
    - release
    - master
    - develop
    - sandbox

Version:
  stage: Version
  allow_failure: false
  only:
    - sandbox
    - develop
    - release
    - master
  script:
    - VERSION=`sed -nE 's/^\\s*\"version\"\:\ \"(.*?)\",$/\\1/p' package.json`
    - echo "VERSION=$CI_COMMIT_REF_SLUG$VERSION" >> build.env
  artifacts:
    reports:
      dotenv: build.env


build:sb:
  stage: Build
  allow_failure: false
  environment:
    name: sb
  variables:
    IMAGE_TAG: $CI_REGISTRY_IMAGE:$VERSION
    TF_ENV: "sb"
  extends:
    - .build
  only:
    - sandbox
  dependencies:
    - Version  

build:dev:
  stage: Build
  allow_failure: false
  environment:
    name: dev
  variables:
    IMAGE_TAG: $CI_REGISTRY_IMAGE:$VERSION
    TF_ENV: "dev"
  extends:
    - .build
  only:
    - develop
  dependencies:
    - Version  

build:qa:
  stage: Build
  allow_failure: false
  environment:
    name: qa
  variables:
    IMAGE_TAG: $CI_REGISTRY_IMAGE:$VERSION
    TF_ENV: "qa"
  extends:
    - .build
  only:
    - release
  dependencies:
    - Version  

build:prod:
  stage: Build
  allow_failure: false
  environment:
    name: prod
  variables:
    IMAGE_TAG: $CI_REGISTRY_IMAGE:$VERSION
    TF_ENV: "prod"
  extends:
    - .build
  only:
    - master
  dependencies:
    - Version  

deployment:sandbox:
  rules:
    - if: "$CI_COMMIT_BRANCH =~ /^feature/"
      when: never
    - if: $CI_COMMIT_BRANCH == "sandbox"  
  variables:
    TF_ENV: "sb"
    MODULE: "frontend"
    VERSION: $VERSION
  stage: Deploy
  allow_failure: false
  trigger:
    project: in-silico-prediction/isp/isp-deployment
    strategy: depend
  needs:
    - job: Version
      artifacts: true
    - job: build:sb    
      artifacts: false
  
 
deployment:dev:
  rules:
    - if: "$CI_COMMIT_BRANCH =~ /^feature/"
      when: never
    - if: $CI_COMMIT_BRANCH == "develop"  
  variables:
    TF_ENV: "dev"
    MODULE: "frontend"
    VERSION: $VERSION
  stage: Deploy
  allow_failure: false
  trigger:
    project: deployment
    strategy: depend
  needs:
    - job: Version
      artifacts: true
    - job: build:dev
      artifacts: false  

deployment:qa:
  rules:
    - if: "$CI_COMMIT_BRANCH =~ /^feature/"
      when: never
    - if: $CI_COMMIT_BRANCH == "release"  
  variables:
    TF_ENV: "qa"
    MODULE: "frontend"
    VERSION: $VERSION
  stage: Deploy
  allow_failure: false
  trigger:
    project: deployment
    strategy: depend
  needs:
    - job: Version
      artifacts: true
    - job: build:qa  
      artifacts: false    

deployment:prod:
  rules:
    - if: "$CI_COMMIT_BRANCH =~ /^feature/"
      when: never
    - if: $CI_COMMIT_BRANCH == "master"  
  variables:
    TF_ENV: "prod"
    MODULE: "frontend"
    VERSION: $VERSION
  stage: Deploy
  allow_failure: false
  trigger:
    project: deployment
    strategy: depend
  needs:
    - job: Version
      artifacts: true
    - job: build:prod
      artifacts: false

The deployment stage will invoke downstream project. The backend project also have same pipeline definition. Now both Frontend and Backend project will trigger the deployment project independently.

The deployment project should wait for the trigger from both project and run only 1 time which deploys both frontend and backend in single run into the environment.

1 Answers

For Merge train, is it possible to configure 2 different project merge request

As long as those MRs are from the same project, yes, the all idea of merge train is to, as in this example, list multiple MRs and combine them.
However, that would trigger the FE (FrontEnd) deployment, then it would trigger FE and BE deployments, which is not what you want.

I would rather use a scheduled cron job which detects when both FE and BE have been deployed, for instance by query the the date of their respective published images (latest FE and BE in the registry): if that date is more recent than the latest completed deployment, both for FE and BE build, then the deployment cron job would trigger an actual and full deployment.

Related