Skip to content

Conditional execution of steps with `if:`

Erik Seliger requested to merge mrn/conditional-exec into main

Created by: mrnugget

This extends the schema of the batch spec steps to add a new field:

  • if: <string that can use templating to evaluate to "true" or "false">

(the corresponding schema changes sourcegraph/sourcegraph are here: https://github.com/sourcegraph/sourcegraph/pull/20399)

if: is evaluated in a best-effort partial-evaluation manner before the execution of the steps. If we can statically evaluate it, we use the result of that evaluation to build a per-repository/per-workspace list of tasks, which increases cache utilisation.

See the comments in partial_eval.go for more details.

It also extends the StepContext in the templates to have the steps.{added,modified,deleted}_files and steps.path fields.

Example batch spec

name: conditional-exec
description: Testing conditional execution of steps

on:
  - repository: github.com/sourcegraph-testing/mkcert
  - repository: github.com/sourcegraph-testing/zap
  - repository: github.com/sourcegraph/automation-testing

steps:
  #
  # Step 1.
  # No `if:`, runs in every repository/workspace
  #
  - run: echo "This is ${{ repository.name }}" >> message.txt
    container: alpine:3
  #
  # Step 2.
  # `if:` checks for repository name. Only runs in github.com/sourcegraph/automation-testing
  #
  - run: echo "hello viewers! is the background noise from the landscapers too loud? leave a message after the beep" >> message.txt
    if: "${{ eq repository.name \"github.com/sourcegraph/automation-testing\" }}"
    container: alpine:3
  #
  # Step 3.
  # `if:` checks repository name. Only runs in repos
  #
  - run: echo "repo name contains sourcegrap-testing" >> message.txt
    # The new builtin function `matches` makes it easy to check for repository names:
    if: "${{ matches repository.name \"*sourcegraph-testing*\" }}"
    container: alpine:3
  #
  # Step 4.
  # Checks for go.mod existance and saves to outputs
  #
  - run:  if [[ -f "go.mod" ]]; then echo "true"; else echo "false"; fi
    container: alpine:3
    outputs:
      goModExists:
        value: ${{ step.stdout }}
  #
  # Step 5.
  # `if:` checks whether the value just saved to outputs is true
  #
  - run: go fmt ./...
    container: golang
    # `if:` supports templating and has access to the full step context, including `previous_step.stdout`, `repository.name`, etc.
    if: ${{ outputs.goModExists }}

  #
  # Step 6.
  # `if:` checks whether the steps are executed in a workspace.
  #
  - run: echo "hello workspace" >> workspace.txt
    container: golang
    if: ${{ eq steps.path "sub/directory/in/repo" }}

changesetTemplate:
  title: Testing conditional execution of steps
  body:  Testing conditional execution of steps
  branch: thorsten/conditional-exec
  published: false
  commit:
    message: Conditional exec of steps

Demo video

Click here

Merge request reports

Loading