Steven Lu
Steven Lu

Reputation: 43427

How to use an anchor to prevent repetition of code sections?

Say I have a number of jobs that all do similar series of scripts, but need a few variables that change between them:

test a:
  stage: test
  tags:
    - a
  interruptible: true
  rules: 
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
  script:
    - echo "env is $(env)"
    - echo etcetera
    - echo and so on
    - docker build -t a -f Dockerfile.a .
test b:
  stage: test
  tags:
    - b
  interruptible: true
  rules: 
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
  script:
    - echo "env is $(env)"
    - echo etcetera
    - echo and so on
    - docker build -t b -f Dockerfile.b .

All I need is to be able to define e.g.

- docker build -t ${WHICH} -f Dockerfile.${which} .

If only I could make an anchor like:

.x: &which_ref
  - echo "env is $(env)"
  - echo etcetera
  - echo and so on
  - docker build -t $WHICH -f Dockerfile.$WHICH .

And include it there:

test a:
  script:
    - export WHICH=a
    <<: *which_ref

This doesn't work and in a yaml validator I get errors like

Error: YAMLException: cannot merge mappings; the provided source object is unacceptable

I also tried making an anchor that contains some entries under script inside of it:

.x: &which_ref
  script:
    - echo "env is $(env)"
    - echo etcetera
    - echo and so on
    - docker build -t $WHICH -f Dockerfile.$WHICH .

This means I have to include it from one step higher up. So this does not error, but all this accomplishes is cause the later declared script section to override the first one.

So I'm losing hope. It seems like I will just need to abstract the sections away into their own shell scripts and call them with arguments or whatever.

Upvotes: 0

Views: 93

Answers (1)

flyx
flyx

Reputation: 39688

The YAML merge key << is a non-standard extension for YAML 1.1, which has been superseded by YAML 1.2 about 14 years ago. Usage is discouraged.

The merge key works on mappings, not on sequences. It cannot deep-merge. Thus what you want to do is not possible to implement with it.

Generally, YAML isn't designed to process data, it just loads it. The merge key is an outlier and didn't find its way into the standard for good reasons. You need a pre- or postprocessor to do complex processing, and Gitlab CI doesn't offer anything besides simple variable expension, so you're out of luck.

Upvotes: 2

Related Questions