Skip to content

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

Open

Description

@Joe-Kollin

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

Activity

  1. alexandrebrg commented on Jul 20, 2022

    @alexandrebrg

    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.

  2. funes79 commented on Sep 29, 2022

    @funes79

    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 }}"
    
  3. funes79 commented on Sep 30, 2022

    @funes79

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

  4. korewaChino commented on Oct 7, 2022

    @korewaChino

    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 }}
  5. carmocca commented on Oct 8, 2022

    @carmocca

    I also have this problem in Lightning-AI/pytorch-lightning#15043

  6. jsoref commented on Oct 12, 2022

    @jsoref
    Contributor

    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.

  7. garciasdos commented on Nov 25, 2022

    @garciasdos

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

  8. mrkesu commented on Nov 29, 2022

    @mrkesu

    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

  9. jsoref commented on Nov 29, 2022

    @jsoref
    Contributor

    @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. #1985 (comment)

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

  10. added a commit that references this issue on Jan 3, 2023
  11. markstijnman-shell commented on Mar 3, 2023

    @markstijnman-shell

    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.

  12. added a commit that references this issue on May 12, 2023
  13. pawamoy commented on May 15, 2023

    @pawamoy

    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
  14. pawamoy commented on Jun 2, 2023

    @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) }}
  15. Gustl22 commented on Apr 6, 2024

    @Gustl22

    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) }}
  16. excitoon commented on Apr 27, 2024

    @excitoon

    @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

  17. deannagarcia commented on Jun 14, 2024

    @deannagarcia

    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?

  18. Sivakajan-tech commented on Aug 6, 2024

    @Sivakajan-tech

    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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions