Introduce `runner_opts` to CI jobs and service definitions

runner_opts

runner_opts would be a set of configuration that is only validated by GitLab-Runner, with GitLab just passing along the data. Therefore, the types supported would be those that can be converted to JSON (the serialization Runner receives a job as).

Background

Today, GitLab-Runner's behaviour can be tuned using variables. Unfortunately, variables have to be string types, and this has several disadvantages.

  • Controlling git behaviour is done via GIT_*_FLAGS variables (such as GIT_FETCH_EXTRA_FLAGS). Unfortunately, these flags can easily be broken with malformed input. This is a limitation in only accepting a string type.

    If runner_opts could support arbitrary data types, this flag could be an array, and flags such as ['-c', 'something', '--arg'] would be supported.

  • Kubernetes executor supports various overrides. For labels, this looks like this:

    variables:
      KUBERNETES_POD_LABELS_1: "Key1=Val1"
      KUBERNETES_POD_LABELS_2: "Key2=Val2"
      KUBERNETES_POD_LABELS_3: "Key3=Val3"

    With runner_opts, this could instead be something like:

    runner_opts:
      kubernetes_pod_labels:
        Key1: Val1
        Key2: Val2
        Key3: Val3
  • We wanted to add tcp, http and exec health probes for Docker and Kubernetes, but to support all of this under services would mean supporting an explosion of configuration options.

    With runner_opts, Runner would define and validate runner_opts, meanwhile, GitLab would pass through the hashmap as-is. This reduces the burden of GitLab having to maintain validations and logic that only Runner needs to know and handle.


The GIT_*_FLAGS problem might be able to be solved with inputs (#377327 (closed)), but what inputs doesn't solve is configuration that isn't for tuning a specific task/action, but is there to control the behaviour of the job environment that Runner provisions.

Proposal

runner_opts would be introduced to default, jobs and services definitions.

  • runner_opts under default would apply to all jobs. This would be used for Runner to configure the job's environment.
  • runner_opts under a specific job would apply only to that one job. This would be used for Runner to configure the job's environment.
  • runner_opts under a specific service definition would apply only to that one service. This would be used for Runner to configure the environment for a service.

Because we're no longer shoehorning these options into variables, runner_opts should be able to have very strict validation rules. What is allowed under a job might not be allowed under a service and vice-versa (I expect very little overlap between fields).

Similar to how we currently handle variables, Runner would decide if validation either fails the job or if it can fallback. As a later iteration, we could have Runner select whether it wants to execute a job by it first validating these fields. This would require changes to how Runner accepts a job though.