Specifying a pipeline step as "manual" causes its status to always be "blocked"

Hey folks,

I’m trying to create a pipeline where the last step destroys an environment. The entire pipeline looks as follows:

variables:
  TF_IMAGE: python:3.8-slim-buster

stages:
  - "Analysis/Test"
  - "Deploy Branch"
  - Cleanup

.terraform_defaults:
  image:
    name: $TF_IMAGE
  resource_group: $CI_COMMIT_REF_SLUG
  variables:
    WORKSPACE: "tf-${CI_COMMIT_REF_SLUG}"

analyze:
  stage: "Analysis/Test"
  image:
    name: python:3.8-slim-buster
  script:
    - echo "Running tests"

deploy_branch:
  extends: .terraform_defaults
  stage: "Deploy Branch"
  environment:
    name: review/tf-$CI_COMMIT_REF_SLUG
    on_stop: destroy_branch
    auto_stop_in: 1 week
  rules:
    - if: '$CI_COMMIT_BRANCH == "stable"'
      when: never
    - if: '$CI_COMMIT_BRANCH =~ /^noenv\/.*/'
      when: never
    - when: always
  script:
    - echo "Deploying branch"

destroy_branch:
  extends: .terraform_defaults
  stage: Cleanup
  environment:
    name: review/tf-$CI_COMMIT_REF_SLUG
    action: stop
  rules:
    - if: '$CI_COMMIT_BRANCH == "stable"'
      when: never
    - if: '$CI_COMMIT_BRANCH =~ /^noenv\/.*/'
      when: never
    - when: manual
  variables:
    GIT_STRATEGY: none
  script:
    - echo "Deleting branch"

When I run this pipeline, and all pre-cleanup steps succeed, the result is the following:

Instead I’d expect it to look like this:

I can achieve this by removing the rules section in the destroy_branch step, and instead adding:

when: manual
except:
  - stable
  - /^noenv\/.*/

I’m not entirely sure why these two configurations yield different results, but optimally I would want to avoid the use of except, since it is deprecated as far as I can tell from the documentation.

My assumption at the moment is that I’ve misunderstood something about the rules what I wrote, but this could also be a bug, possible related to:

Can someone shed some light on this issue? I want to avoid opening a bug until I’m sure that it’s not a RTFM situation :sweat_smile:

Environment

I’m using Gitlab.com (i.e. not self-hosted) but the runners are self-hosted (v14.2.0)

4 Likes

This seems to be weird behavior and potentially a bug. I have created a small replicatable pipeline that fails due to using rules.

This configuration runs as expected. The test job is skipped and then the deploy job is run.

stages:
  - build
  - test
  - deploy

build:
  stage: build
  script: exit 0

test:
  stage: test
  when: manual
  script: exit 0

deploy:
  stage: deploy
  script: exit 0

The following will block the CI even though it is effectively the same as the above configuration just because it uses a rule. The if in the rules matches with the when: manual and blocks the pipeline.

stages:
  - build
  - test
  - deploy

build:
  stage: build
  script: exit 0

test:
  stage: test
  rules:
    - if: $CI_COMMIT_BRANCH == ""
      when: always
    - when: manual
  script: exit 0

deploy:
  stage: deploy
  script: exit 0
1 Like

I ran into this same problem, and finally found the answer after reading through the issues linked in the OP. It’s also noted in the GitLab docs, under Additional Details inside the when: section.

Apparently, when using job:when:manual, allow_failure will default to true. Hence, the passing pipeline status when the OP switched to using except:.

But when using job:rules:when:manual, allow_failure will default to false, which is why the OP’s original configuration was showing a blocked pipeline status.

No idea why they made the defaults reversed like that.