4

(GH newb attempting to cargo cult my way through some configuration ...)

I am using the GitHub actions YAML file here to test an R package. By default this workflow tests on four separate platforms, but this is overkill for my day-to-day needs. (This action does more limited testing, but I think? it also misses some stuff I wanted from the fuller workflow ...)

I would like to have the tests done on all four platforms only if the commit message includes the string "full check", otherwise testing just one platform. I know I can in principle achieve something like this if I include a conditional:

if: "contains(github.event.head_commit.message, '[full ci]')"

but I'm not sure of the precise syntax for including it in the workflow (and I'm afraid of spending many hours on trial-and-error attempts)

The chunk of the workflow that defines the set of platforms current looks like this, with three of the platforms commented out:

    strategy:
      fail-fast: false
      matrix:
        config:
          - {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
##          - {os: ubuntu-20.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
##          - {os: windows-latest, r: 'release'}
##          - {os: macOS-latest, r: 'release'}

I'm assuming that just sticking the if: clause below the first row won't work (because it would break up the list). I suppose something like this might work?

    matrix:
      config:
        if: "! contains(github.event.head_commit.message, '[full ci]')"]
        config:
           - {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
        if: "contains(...)"
        config: 
            [list with all four configs]

(Does this syntax have an if/else construct?)

I'm looking for answers that help me achieve the narrow goal, and hopefully understand the YAML syntax a little better (I have tried to read the FM ...)

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • This is pretty similar: https://stackoverflow.com/questions/65384420/how-to-make-a-github-action-matrix-element-conditional. Does it answer your question? – riQQ Jan 02 '21 at 23:56
  • Looks like it might be, thanks. I will have to read and digest it (more complex/harder to adapt than I had hoped, but it looks like the right direction ...) I would happily accept an answer that adapts [this answer](https://stackoverflow.com/a/65513159/190277) to my situation ('cause it will take me from tens of minutes to hours to grok the answer sufficiently to adapt it ...) – Ben Bolker Jan 03 '21 at 00:15
  • Does this answer your question? [how to make a github action matrix element conditional](https://stackoverflow.com/questions/65384420/how-to-make-a-github-action-matrix-element-conditional) – JoshuaTheMiller Aug 12 '21 at 13:26

1 Answers1

4

I believe it is not possible to add conditions to the matrix construct itself. You could generate the matrix data beforehand in another job and then use it in your job.

There is a simpler solution: Use two jobs, because if can be used at the job level. Copy the current job that you have and then add if-conditions to each job. Keep one job as it is for the full CI and in the other job hardcode your environment for the ordinary commits.

Something like this:

jobs:
  R-CMD-check-ordinary:
    if: ${{ ! contains(github.event.head_commit.message, '[full ci]') }}
    # Hardcode os
    runs-on: ubuntu-20.04
    # Hardcode name
    name: Test only on Ubuntu

    env:
      R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
      RSPM: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}

    steps:
      # replace any occurences of matrix.config. with hardcoded values
      ...
      
  # And the original job
  R-CMD-check-full:
    if: ${{ contains(github.event.head_commit.message, '[full ci]') }}
    runs-on: ${{ matrix.config.os }}

    name: ${{ matrix.config.os }} (${{ matrix.config.r }})

    strategy:
      fail-fast: false
      matrix:
        config:
          - {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
          - {os: ubuntu-20.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
          - {os: windows-latest, r: 'release'}
          - {os: macOS-latest, r: 'release'}

    env:
      R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
      RSPM: ${{ matrix.config.rspm }}
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}

    steps:
      ...

Regarding YAML syntax:

YAML is a data format. Don't think of YAML as a script or program. A YAML file is similar to a list of command line arguments for a program. It only defines input data for another program.

So there is no if in YAML. For YAML if: condition is like as any other key: value pair, there is no logic attached.

cuzi
  • 978
  • 10
  • 21
  • 1
    this is a nice, simple answer. It violates [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) but may be worth it in this case. – Ben Bolker Jan 03 '21 at 00:38
  • I take your point as YAML being a data format. My comments about understanding the syntax were driven by frustration at my ignorance about the syntax and the importance of whitespace, meaning of elements with and without dashes, etc. – Ben Bolker Jan 03 '21 at 00:40
  • 1
    It think it helps to always keep in mind that although there are several ways to write them, there are just two data types, lists (a.k.a. arrays) and key-value-pairs (a.k.a. dictionaries/hash maps) – cuzi Jan 03 '21 at 01:12