How to set a dynamic gitlab job tag with a variable?

Viewed 5628

I am trying to create a dynamic job that can switch between two gitlab runners depending on which tag it is given. I would like to do this with an environmental variable, but it seems this cannot be used. The following job:

runner_test:
  image: alpine
  tags:
    - $MY_RUNNER
  stage: deploy_main
  script:
    - echo foobar
  retry: 2

Results in a paused pipeline with the error: This job is stuck because you don't have any active runners online or available with any of these tags assigned to them: $MY_RUNNER

4 Answers

This is currently not available. There is currently an open issue which is in the backlog requesting this feature: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/1809.


A work around perhaps, using rules and extends:

.template:
  stage: deploy_main
  script:
    - echo foobar

runner_test_1:
  extends: .template
  tags:
    - runner_1
  rules:
    - if: $RUNNER_TAG == runner_1
    
runner_test_2:
  extends: .template
  tags:
    - runner_2
  rules:
    - if: $RUNNER_TAG == runner_2

or something to that effect.

Dynamic job tags is achievable now (tested on 14.10). Variable interpolation works for job tags, and one way you can dynamically modify CI Variables is with the rules:variables key.

The following example would result in a default job tag of "staging" for most branches, and an override value of "production" for pipelines running against the project's default branch.

job:
  variables:
    RUNNER_TAG: staging           # default CI variable value
  rules:
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
      variables:
        RUNNER_TAG: production    # override CI variable value when the if: check is true
  tags:
    - $RUNNER_TAG                 # use the dynamic CI variable as a job tag
  script:
    - hello world from runner matching $RUNNER_TAG

Since this is not possible on older versions of Gitlab, as a work around for those on older verisons of Gitlab, to extend on the answer given by Rekovni, if you're looking to run environment specific runners:

.Deploy_template:
  stage: Deploy
  image:
    name: busybox/busybox:latest
    entrypoint: [""]
  rules:
    - when: manual
  before_script:
    - echo "Preflight tests"
  script:
    - echo "Start Deployment"
  after_script:
    - echo "Postflight tests"
  allow_failure: false


Deploy_feature:
  extends: .Deploy_template
  tags:
    - docker
    - feature
  rules:
    - if: $BRANCH =~ /feature/

Deploy_develop:
  extends: .Deploy_template
  tags:
    - docker
    - develop
  rules:
    - if: $BRANCH =~ /develop/

Deploy_stable:
  extends: .Deploy_template
  tags:
    - docker
    - stable
  rules:
    - if: $BRANCH =~ /stable/

Then you just repeat this for every job you have.

So if I have control of the repo branching structure, I make the CI branch names match the tags (e.g. dev, test, preprod, prod, etc). Then I can do something like this. However, this solution is not very portable for cases where you need to map the branch name to some other tag.

tags:
  - ${CI_COMMIT_BRANCH}

I really don't like the template, extends paradigm. It makes so much extra code. There must be a better way. There is this feature which is almost there. However, I cannot figure out how to make the source variable dynamically derived from another variable. Maybe it meets some people's use cases.

Related