Which job properties get merged vs overwritten when using `extends` in GitLab CI?

468 Views Asked by At

In GitLab CI, you can use the extends keyword in order to inherit properties from another job or template.

One example is:

.tests:
  script: rake test
  stage: test
  only:
    refs:
      - branches

rspec:
  extends: .tests
  script: rake rspec
  only:
    variables:
      - $RSPEC

Which results in:

rspec:
  script: rake rspec
  stage: test
  only:
    refs:
      - branches
    variables:
      - $RSPEC

But as you can see, it is not obvious how each property gets merged. Properties like "only" appear to get merged and other properties like script appear to get overwritten instead.

I'm trying to understand exactly which properties get overwritten and which properties get merged (and how). Is there a complete list?

Something like this maybe?

Property Behavior when used with extends
script Overwritten
only Merged
except Merged
variables Merged
before_script Overwritten
after_script Overwritten
needs Merged
cache Merged (gets converted from map to list of maps)
artifacts Merged (deep)
services ?
when ?
rules ?
... ...
1

There are 1 best solutions below

0
sytech On BEST ANSWER

As documented in merge details, hashes (key, value pairs) get merged, but any other value like arrays are overwritten by the extending job. It works simply by using the deep_merge method which is part of the Ruby on Rails framework.

The actual logic, looks like this:

# File activesupport/lib/active_support/core_ext/hash/deep_merge.rb, line 23
  def deep_merge!(other_hash, &block)
    merge!(other_hash) do |key, this_val, other_val|
      if this_val.is_a?(Hash) && other_val.is_a?(Hash)
        this_val.deep_merge(other_val, &block)
      elsif block_given?
        block.call(key, this_val, other_val)
      else
        other_val
      end
    end
  end

This means it can be important how you write your YAML, as some configurations accept multiple types. For example variables: may be a hash of keys and values (or hash of keys and hash of configuration options). It can also be an array of hashes. These different options for writing variables: will merge differently when used with extends:. The same goes for many other keys, like only: and except:.