Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I centralize (DRY) a string in GitHub Actions config yaml?

I'm creating a GitHub Actions workflow for my CI and I realize that I'm repeating some piece of information. For example, the runs-on of a job is defined as ubuntu-18.04 and mac-10.14, or a specific compiler/toolchain version in a strategy/matrix.

I'd like to centralize those version information somewhere in the YAML file and be able to refer to these instead of duplicating the value many times. That way I don't repeat myself (DRY) and I can easily change the version value at a single location and prevent inconsistencies.

Unfortunately I have trouble doing so. The way I though could be used for this is to use a global env environment variable at the top of the YAML and refer to it elsewhere. For example, I would like to replace something like the following:

on: [push, pull_request]
name: CI
jobs:
  build:
    name: Build
    runs-on: ubuntu-18.04
    strategy:
      matrix:
        toolchain:
          - 1.2.3
    steps:
      - run: ./build.sh 1.2.3
  package:
    name: Package
    runs-on: ubuntu-18.04
    steps:
      - run: ./package.sh 1.2.3
[...]

with:

on: [push, pull_request]
name: CI
env:
  UBUNTU_VERSION: 18.04
  TOOLCHAIN_VERSION: 1.2.3
jobs:
  build:
    name: Build
    runs-on: ubuntu-${{ env.UBUNTU_VERSION }}
    strategy:
      matrix:
        toolchain:
          - ${{ env.TOOLCHAIN_VERSION }}
    steps:
      - run: ./build.sh ${{ matrix.toolchain }}
  package:
    name: Package
    runs-on: ubuntu-${{ env.UBUNTU_VERSION }}
    steps:
      - run: ./package.sh ${{ env.TOOLCHAIN_VERSION }}
[...]

i.e. use the env context in an expression (see Contexts and expression syntax for GitHub Actions - Contexts).

This fails with:

### ERRORED 18:08:15Z

- Your workflow file was invalid: The pipeline is not valid. .github/workflows/ci.yml (Line: 20, Col: 14): Unrecognized named-value: 'env'. Located at position 1 within expression: env.UBUNTU_VERSION,.github/workflows/ci.yml (Line: 125, Col: 14): Unrecognized named-value: 'env'. Located at position 1 within expression: env.UBUNTU_VERSION

I could only find this question on the env context and this page saying the env now works on the workflow level.

How can I centralize repeating strings/versions/etc. into a single location as to DRY?

Thanks!

like image 701
big_gie Avatar asked Nov 21 '19 18:11

big_gie


1 Answers

You can do this at the workflow level using env, you just can't use those values inside the runs-on - which is why you've only got errors for UBUNTU_VERSION and not TOOLCHAIN_VERSION.

Why? Because env is an environment variable which is set on the machine but it needs to provision the machine before it can set an environment variable on the machine, but it doesn't know which machine to provision because you have an env var in the machine type.. :)

I'm sure GitHub COULD fix this but it doesn't work right now.

Side note: jobs are designed to be run independently, in parallel and on different machines. If you have a sequential workflow it's better to have a single job and multiple steps. That would also get rid of your repeating ubuntu-18.04 definitions and shrink your workflow file.

like image 92
Michael Parker Avatar answered Sep 21 '22 14:09

Michael Parker