runner icon indicating copy to clipboard operation
runner copied to clipboard

Unrecognized named-value: 'matrix' in job if conditional

Open Joe-Kollin opened this issue 3 years ago • 16 comments

Describe the bug A job generates a matrix as an output and I have a subsequent job that depends on the generation of that matrix. The first job does an API call to get all customers which each have a unique schema association. I only want to run this second job in the event that my input SCHEMA array contains the schema of a given return record. However, when I execute the build I get the following error: Unrecognized named-value: 'matrix'. Located at position 26 within expression: contains(inputs.SCHEMAS, matrix.customer.schema). The pattern works without the conditional, but does not fit my use case.

This is a rough idea of what the job looks like.

job-name:
  runs-on: ubuntu-latest
  needs: get-customers
  if: contains(inputs.SCHEMAS, matrix.customer.schema)
  strategy:
    matrix:
      customer: ${{fromJson(needs.get-customers.outputs.customers)}}
  steps:
     ....

Expected behavior The job should only run when the matrix schema is contained within the input SCHEMA

Runner Version and Platform

ubuntu-latest

What's not working?

The use of matrix in a job level conditional

Joe-Kollin avatar Jul 07 '22 14:07 Joe-Kollin

I had the same issue, it seems that if statement is evaluated before running a matrix of jobs. I found this topic on GitHub forum about this problem.

alexandrebrg avatar Jul 20 '22 11:07 alexandrebrg

I do have the same issue, and not using any if statement. And the matrix value does not contain any spaces.

  list-dev-configs:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - uses: actions/checkout@v3
      - id: set-matrix
        run: echo "::set-output name=matrix::[\"A\",\"B\"]"
  check:
    needs: list-dev-configs
    runs-on: ubuntu-latest
    strategy:
        matrix:
            dev_config: ${{ fromJSON(needs.list-dev-configs.outputs.matrix) }}
    steps:
      - uses: actions/checkout@v3   
      - run: |
          echo "${{ needs.list-dev-configs.outputs.matrix }}"
          echo "${{ fromJSON(needs.list-dev-configs.outputs.matrix) }}"
          echo "${{ martix.dev_config }}"

funes79 avatar Sep 29 '22 08:09 funes79

My bad, that was a typo in the script last line martix instead of matrix.

funes79 avatar Sep 30 '22 10:09 funes79

Also having this issue. the workflow works fine if there was no if statement.

  build:
    needs: manifest
    strategy:
      matrix: ${{ fromJson(needs.manifest.outputs.build_matrix) }}

    uses: andaman-common-pkgs/github-actions/.github/workflows/anda-rpm.yml@main
    if: ${{ matrix.changed_folders != '' }}
    with:
      name: "rust/${{ matrix.changed_folders }}/pkg"
      subatomicServer: "https://subatomic.fyralabs.com"
      subatomicRepo: ad37
      mockConfig: anda-37-x86_64
      mockConfigPackage: anda-mock-configs
      upload: true
    secrets:
      subatomicToken: ${{ secrets.SUBATOMIC_TOKEN }}

korewaChino avatar Oct 07 '22 02:10 korewaChino

I also have this problem in https://github.com/Lightning-AI/lightning/pull/15043

carmocca avatar Oct 08 '22 16:10 carmocca

You can probably work around this by having additional jobs that generate outputs and relying on needs and the outputs from those jobs.

You might need to demote your ifs from job level to step level.

jsoref avatar Oct 12 '22 08:10 jsoref

Same problem here. Are there any plans to add the matrix context to the jobs.<job_id>.if condition?

garciasdos avatar Nov 25 '22 12:11 garciasdos

I'm also encountering this issue.

Sadly my workflow had to be changed from this:

jobs:
  remediate:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        env: ["dev", "test", "prod"]
    if: ${{ github.event.schedule || matrix.env == github.event.inputs.env }}
    environment: ${{ matrix.env }}
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - uses: cue-lang/[email protected]
        with:
      [ etc... ]

to this:

jobs:
  remediate:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        env: ["dev", "test", "prod"]
    environment: ${{ matrix.env }}
    steps:
      - name: Checkout
        if: ${{ github.event.schedule || matrix.env == github.event.inputs.env }}
        uses: actions/checkout@v2
      - uses: cue-lang/[email protected]
        if: ${{ github.event.schedule || matrix.env == github.event.inputs.env }}
        with:
      [ etc... ]

Obviously with a few more steps than in the above truncated example.

It makes the whole workflow feel a bit messy, especially since the jobs are being marked as successfully run when in reality all the steps within it have been skipped.

(never mind my failed job, it's still in development😅) image

mrkesu avatar Nov 29 '22 08:11 mrkesu

@mrkesu: if you're up for it, you should really try having a job that creates your matrix and then have it create an empty array when you don't want it to do work. https://github.com/actions/runner/issues/1985#issuecomment-1275812256

Here's a workflow which does something similar: https://github.com/commercialhaskell/stack/blob/71a85a488ef458d5c7d315b647411056aafd3d0a/.github/workflows/integration-tests.yml#L104-L127

jsoref avatar Nov 29 '22 15:11 jsoref

I ran into this issue today as well. Can the matrix context indeed be added to jobs.<job_id>.if ? I would imagine that if it is available for runs-on, it should be possible to make it available for jobs.<job_id>.if too, as I would expect both are evaluated before starting the job.

My use case is in reusable workflows, where I also want to reuse my matrix for several projects, However, there are projects who don't need all configurations. So I want to allow the calling workflow to use input parameters to skip certain matrix entries. For example, I would very much like something like this to work, which would allow the calling workflow to control whether to build for win32:

on:
  workflow_call:
    inputs:
      build-win32:
        required: true
        type: boolean
      
jobs:
  build:
    strategy:
      matrix:
        include:
          - os: windows-latest
            arch: "win64"
            build: true
          - os: windows-latest
            arch: "win32"
            build: ${{ inputs.build-win32 }}
          - os: ubuntu-latest
            build: true
        
    if: ${{ matrix.build }}
    runs-on: ${{ matrix.os }}

I've seen workarounds that use a separate job to set up a matrix, but that solution is (1) much harder to understand than this one, and (2) will introduce an extra job in your output that is just noise.

markstijnman-shell avatar Mar 03 '23 19:03 markstijnman-shell

It's indeed a bit surprising to get this error when seeing that runs-on works just fine with it:

    runs-on: ${{ matrix.os }}  # ok
    if: ${{ matrix.os == 'ubuntu-latest' }}  # not ok

pawamoy avatar May 15 '23 10:05 pawamoy

Here is the most elegant solution I found to this issue:

jobs:
  exclude-jobs:
    runs-on: ubuntu-latest
    outputs:
      jobs: ${{ steps.exclude-jobs.outputs.jobs }}
    steps:
    - id: exclude-jobs
      # 1. use any other condition(s) that fits your requirements
      # 2. each item in the JSON array will be matched against your matrix later
      # 3. here I exclude everything except ubuntu-latest + python3.7 (see matrix below)
      # 4. make sure to output as single line
      # 5. the default case is: exclude nothing
      run: |
        if ${{ github.repository_owner == 'pawamoy-insiders' }}; then  # 1
          # 2, 3
          echo 'jobs=[
            {"os": "macos-latest"},
            {"os": "windows-latest"},
            {"python-version": "3.8"},
            {"python-version": "3.9"},
            {"python-version": "3.10"},
            {"python-version": "3.11"}
          ]' | tr -d '[:space:]' >> $GITHUB_OUTPUT  # 4
        else
          echo 'jobs=[]' >> $GITHUB_OUTPUT  # 5
        fi

  tests:
    needs: exclude-jobs
    strategy:
      matrix:
        os:
        - ubuntu-latest
        - macos-latest
        - windows-latest
        python-version:
        - "3.7"
        - "3.8"
        - "3.9"
        - "3.10"
        - "3.11"
        # simply use the previous JSON data you echoed to exclude jobs
        exclude: ${{ fromJSON(needs.exclude-jobs.outputs.jobs) }}

pawamoy avatar Jun 02 '23 10:06 pawamoy

Thanks @pawamoy that worked for me, in order to use a one dimensional set of inputs and rather use include:

jobs:
  include-jobs:
    runs-on: ubuntu-latest
    outputs:
      jobs: ${{ steps.include-jobs.outputs.jobs }}
    steps:
      - id: include-jobs
        run: |
          includeJobs='
            ${{ inputs.enable_web && '{"platform": "web", "os": "ubuntu-latest", "build-type": "web"},' || '' }}
            ${{ inputs.enable_android && '{"platform": "android", "os": "ubuntu-latest", "build-type": "apk"},' || '' }}
            ${{ inputs.enable_ios && '{"platform": "ios", "os": "macos-latest", "build-type": "ipa"},' || '' }}
          '
          # Remove last ',' with ::-1
          echo "jobs=[${includeJobs::-1}]" | tr -d '[:space:]' >> $GITHUB_OUTPUT

  build-client:
    needs: include-jobs
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include: ${{ fromJSON(needs.include-jobs.outputs.jobs) }}

Gustl22 avatar Apr 06 '24 12:04 Gustl22

@pawamoy @Gustl22 You can also do it this way:

jobs:
  ReuseableMatrixJobForDeployment:
    strategy:
      matrix:
        target: [dev, stage, prod]
    uses: ./.github/workflows/base.yml
    with:
      target: ${{ matrix.target }}

Inside nested job if will work again.

https://docs.github.com/en/actions/using-workflows/reusing-workflows#using-a-matrix-strategy-with-a-reusable-workflow

excitoon avatar Apr 27 '24 17:04 excitoon

I just ran into this issue. As others pointed out, it seems unintuitive that runs-on can access the matrix but if can't. Both proposed workarounds (moving ifs to steps or creating a new job to make the matrix) add a lot of unneeded complexity.

Any chance we could see this be added?

deannagarcia avatar Jun 14 '24 18:06 deannagarcia

The 3rd example in the Repo should be useful in conditionally build the matrix in the GitHub Actions. https://github.com/dorny/paths-filter?tab=readme-ov-file#examples

Sivakajan-tech avatar Aug 06 '24 06:08 Sivakajan-tech