This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the sole discretion of GitLab Inc.
Status Authors Coach DRIs Owning Stage Created
proposed devops verify -

Usage of the GitLab Steps with .gitlab-ci.yml

This document describes how GitLab Steps are integrated into the .gitlab-ci.yml.

GitLab Steps will be integrated using a three-stage execution cycle and replace before_script:, script: and after_script:.

  • setup:: Execution stage responsible for provisioning the environment, including cloning the repository, restoring artifacts, or installing all dependencies. This stage will replace implicitly cloning, restoring artifacts, and cache download.
  • run:: Execution stage responsible for running a test, build, or any other main command required by that job.
  • teardown:: Execution stage responsible for cleaning the environment, uploading artifacts, or storing cache. This stage will replace implicit artifacts and cache uploads.

Before we can achieve three-stage execution we will ship minimal initial support that does not require any prior GitLab integration.

Phase 1: Initial support

Initially the Step Runner will be used externally, without any prior dependencies to GitLab:

  • The step-runner will be provided as part of a container image.
  • The step-runner will be explicitly run in the script: section.
  • The $STEPS environment variable will be executed as type: steps.
hello-world:
  image: registry.gitlab.com/gitlab-org/step-runner
  variables:
    STEPS: |
      - step: gitlab.com/josephburnett/component-hello-steppy@master
        inputs:
          greeting: "hello world"
  script:
    - /step-runner ci

Phase 2: The addition of run: to .gitlab-ci.yml

In Phase 2 we will add run: as a first class way to use GitLab Steps:

  • run: will use a type: steps syntax.
  • run: will replace usage of before_script, script and after_script.
  • All existing functions to support Git cloning, artifacts, and cache would continue to be supported.
  • It is yet to be defined how we would support after_script, which is executed unconditionally or when the job is canceled.
  • run: will not be allowed to be combined with before_script:, script: or after_script:.
  • GitLab Rails would not parse run:, instead it would only perform static validation with a JSON schema provided by the Step Runner.
hello-world:
  image: registry.gitlab.com/gitlab-org/step-runner
  run:
    - step: gitlab.com/josephburnett/component-hello-steppy@master
      inputs:
        greeting: "hello world"

The following example would fail syntax validation:

hello-world:
  image: registry.gitlab.com/gitlab-org/step-runner
  run:
    - step: gitlab.com/josephburnett/component-hello-steppy@master
      inputs:
        greeting: "hello world"
  script: echo "This is ambiguous and invalid example"

Transitioning from before_script:, script: and after_script:

GitLab Rails would automatically convert the *script: syntax into relevant run: specification:

  • Today before_script: and script: are joined together as a single script for execution.
  • The after_script: section is always executed in a separate context, representing a separate step to be executed.
  • It is yet to be defined how we would retain the existing behavior of after_script, which is always executed regardless of the job status or timeout, and uses a separate timeout.
  • We would retain all implicit behavior which defines all environment variables when translating script: into step-based execution.

For example, this CI/CD configuration:

hello-world:
  before_script:
    - echo "Run before_script"
  script:
    - echo "Run script"
  after_script:
    - echo "Run after_script"

Could be translated into this equivalent specification:

hello-world:
  run:
    - step: gitlab.com/gitlab-org/components/steps/legacy/script@v1.0
      inputs:
        script:
          - echo "Run before_script"
          - echo "Run script"
    - step: gitlab.com/gitlab-org/components/steps/legacy/script@v1.0
      inputs:
        script:
          - echo "Run after_script"
      when: always

Phase 3: The addition of setup: and teardown: to .gitlab-ci.yml

The addition of setup: and teardown: will replace the implicit functions provided by GitLab Runner: Git clone, artifacts and cache handling:

  • The usage of setup: would stop GitLab Runner from implicitly cloning the repository.
  • artifacts: and cache:, when specified, would be translated and appended to setup: and teardown: to provide backward compatibility for the old syntax.
  • release:, when specified, would be translated and appended to teardown: to provide backward compatibility for the old syntax.
  • setup: and teardown: could be used in default: to simplify support of common workflows like where the repository is cloned, or how the artifacts are handled.
  • The split into 3-stage execution additionally improves composability of steps with extends:.
  • The hooks:pre_get_sources_script would be implemented similar to script: and be prepended to setup:.

For example, this CI/CD configuration:

rspec:
  script:
    - echo "This job uses a cache."
  artifacts:
    paths: [binaries/, .config]
  cache:
    key: binaries-cache
    paths: [binaries/*.apk, .config]

Could be translated into this equivalent specification executed by a step runner:

rspec:
  setup:
    - step: gitlab.com/gitlab-org/components/git/clone@v1.0
    - step: gitlab.com/gitlab-org/components/artifacts/download@v1.0
    - step: gitlab.com/gitlab-org/components/cache/restore@v1.0
      inputs:
        key: binaries-cache
  run:
    - step: gitlab.com/gitlab-org/components/steps/legacy/script@v1.0
      inputs:
        script:
          - echo "This job uses a cache."
  teardown:
    - step: gitlab.com/gitlab-org/components/artifacts/upload@v1.0
      inputs:
        paths: [binaries/, .config]
    - step: gitlab.com/gitlab-org/components/cache/restore@v1.0
      inputs:
        key: binaries-cache
        paths: [binaries/*.apk, .config]

Inheriting common operations with default:

setup: and teardown: are likely to become very verbose over time. One way to simplify them is to allow inheriting the common setup: and teardown: operations with default:.

The previous example could be simplified to:

default:
  setup:
    - step: gitlab.com/gitlab-org/components/git/clone@v1.0
    - step: gitlab.com/gitlab-org/components/artifacts/download@v1.0
    - step: gitlab.com/gitlab-org/components/cache/restore@v1.0
      inputs:
        key: binaries-cache
  teardown:
    - step: gitlab.com/gitlab-org/components/artifacts/upload@v1.0
      inputs:
        paths: [binaries/, .config]
    - step: gitlab.com/gitlab-org/components/cache/restore@v1.0
      inputs:
        key: binaries-cache
        paths: [binaries/*.apk, .config]

rspec:
  run:
    - step: gitlab.com/gitlab-org/components/steps/legacy/script@v1.0
      inputs:
        script:
          - echo "This job uses a cache."

linter:
  run:
    - step: gitlab.com/gitlab-org/components/steps/legacy/script@v1.0
      inputs:
        script:
          - echo "Run linting"

Parallel jobs and setup:

With the introduction of setup: at some point in the future we will introduce an efficient way to parallelize the jobs:

  • setup: would define all steps required to provision the environment.
  • The result of setup: would be snapshot and distributed as the base for all parallel jobs, if parallel: N is used.
  • The run: and teardown: would be run on top of cloned job, and all its services.
  • The runner would control and intelligently distribute all parallel jobs, significantly cutting the resource requirements for fixed parts of the job (Git clone, artifacts, installing dependencies.)
rspec-parallel:
  image: ruby:3.2
  services: [postgres, redis]
  parallel: 10
  setup:
    - step: gitlab.com/gitlab-org/components/git/clone@v1.0
    - step: gitlab.com/gitlab-org/components/artifacts/download@v1.0
      inputs:
        jobs: [setup-all]
    - script: bundle install --without production
  run:
    - script: bundle exec knapsack

Potential GitLab Runner flow:

  1. Runner receives the rspec-parallel job with setup: and parallel: configured.
  2. Runner executes a job on top of Kubernetes cluster using block volumes up to the setup.
  3. Runner then runs 10 parallel jobs in Kubernetes, overlaying the block volume from 2 and continue execution of run: and teardown:.