Is there a way to use the GitLab "Merge when pipeline succeeds" together with Review apps (that need an auto-stop job)?

Viewed 1529

I have a pipeline with review apps. So when the pipeline runs in the context of a Merge Request / Pull Request then I run:

  • build and upload a docker image to ECR tagged with $CI_PROJECT_NAME.$CI_MERGE_REQUEST_ID
  • deploy a helm chart that configures the app to be visible at $CI_PROJECT_NAME-$CI_MERGE_REQUEST_ID.reviewapps.example.com

I want to delete that docker image tag and kubernetes deployment after the merge request is merged/closed, so I added the following stop review app job:

deploy review app:
  stage: deploy
  image: alpine/helm:3.5.0
  dependencies: []
  script:
    - helm -n "$KUBE_NAMESPACE" upgrade
      --install --wait "$CI_PROJECT_NAME-$CI_MERGE_REQUEST_ID" chart
      -f helm-reviewapp-values.yaml
      --set-string "ingress.annotations.external-dns\.alpha\.kubernetes\.io/hostname=$CI_PROJECT_NAME-$CI_MERGE_REQUEST_ID.reviewapps.example.com."
      --set-string "ingress.host=$CI_PROJECT_NAME-$CI_MERGE_REQUEST_ID.reviewapps.example.com"
      --set-string "image=$AWS_REPOSITORY:$CI_PROJECT_NAME.$CI_MERGE_REQUEST_ID"
      --set "deploymentAnnotations.app\.gitlab\.com/app=${CI_PROJECT_PATH_SLUG}"
      --set "deploymentAnnotations.app\.gitlab\.com/env=${CI_ENVIRONMENT_SLUG}"
      --set "podAnnotations.app\.gitlab\.com/app=${CI_PROJECT_PATH_SLUG}"
      --set "podAnnotations.app\.gitlab\.com/env=${CI_ENVIRONMENT_SLUG}"

  environment:
    name: review/$CI_PROJECT_NAME-$CI_MERGE_REQUEST_ID
    url: https://$CI_PROJECT_NAME-$CI_MERGE_REQUEST_ID.reviewapps.example.com
    on_stop: stop review app
    auto_stop_in: 1 day
  needs:
    - build docker image review app
  rules:
    - if: $CI_MERGE_REQUEST_ID

stop review app:
  stage: cleanup approval
  script: echo approved
  dependencies: []
  environment:
    name: review/$CI_PROJECT_NAME-$CI_MERGE_REQUEST_ID
    action: stop
  needs:
    - deploy review app
  rules:
    - if: $CI_MERGE_REQUEST_ID
      when: manual
      allow_failure: true

uninstall helm chart:
  stage: cleanup
  image: alpine/helm:3.5.0
  dependencies: []
  environment:
    name: review/$CI_PROJECT_NAME-$CI_MERGE_REQUEST_ID
    action: stop
  script:
    - helm -n "$KUBE_NAMESPACE" uninstall "$CI_PROJECT_NAME-$CI_MERGE_REQUEST_ID"
  needs:
    - stop review app
  rules:
    - if: $CI_MERGE_REQUEST_ID
      allow_failure: true

delete ecr image:
  stage: cleanup
  image: amazon/aws-cli:2.1.19
  dependencies: []
  script:
    - aws ecr batch-delete-image --repository-name XXXX --image-ids "imageTag=$CI_PROJECT_NAME.$CI_MERGE_REQUEST_ID"
  needs:
    - stop review app
  rules:
    - if: $CI_MERGE_REQUEST_ID
      allow_failure: true

As you can see the stop review job is

  • referred in the "deploy review app" in the environment:on_stop, making use of the environment auto-stop feature
  • marked as when:manual
  • made optional with allow_failure: true

Then the pipeline looks like this

the stop review app still "blocks" the pipeline, it shows as running until the stop job runs:

gitlab pipeline

This is bothering me because when people click on the Merge when pipeline succeeds nothing will really happen until the environment is manually stopped (by clicking the play button on the stop review app job).

I also tried removing the allow_failure from the stop job but the only difference is that the pipeline will be stuck in state blocked instead of running.

Is there a way to use the Merge when pipeline succeeds together with Review apps (that need a stop job)?

1 Answers

This caused by the needs: stop review app in the downstream jobs.

As a workaround you can create a single job that performs all the cleanup instead of having uninstall helm chart and delete ecr image depending on stop review app via needs:.

You will need to use a docker image for the job that has all the tools required (helm and aws-cli in your case).

The following pipeline .gitlab-ci.yml will turn to passed after deploy review app passed. The single optional stop job stop review app does not force the pipeline to remain in running or blocked and the pipeline succeeds without having to run that particular job:

stages:
  - test
  - package
  - deploy
  - cleanup approval
  - cleanup


build docker image review app:
  stage: package
  script:
    - echo hello
  rules:
    - if: $CI_MERGE_REQUEST_ID

deploy review app:
  stage: deploy
  image: alpine/helm:3.5.0
  dependencies: []
  script:
    - echo hello
  environment:
    name: review/$CI_PROJECT_NAME-$CI_MERGE_REQUEST_ID
    url: https://$CI_PROJECT_NAME-$CI_MERGE_REQUEST_ID.reviewapps.tdhb2bdev.com
    on_stop: stop review app
    auto_stop_in: 1 day
  needs:
    - build docker image review app
  rules:
    - if: $CI_MERGE_REQUEST_ID

stop review app:
  stage: cleanup approval
  script: 
    - echo helm uninstall xxxx
    - echo aws ecr batch-delete-image xxxx
  dependencies: []
  environment:
    name: review/$CI_PROJECT_NAME-$CI_MERGE_REQUEST_ID
    action: stop
  needs:
    - deploy review app
  rules:
    - if: $CI_MERGE_REQUEST_ID
      when: manual
      allow_failure: true
Related