melekes
melekes

Reputation: 1888

Github Actions: set-output does not seem to work

I have a workflow that executes a bunch of fuzz tests and, at the end, calculates the total number of files in all crashers sub-directories. Later, in another job, I use that number to send a notification to Slack. But, for some reason, ::set-output produces no output and, most importantly, the next job does not get run even though the number of crashers is not zero!

jobs:
  fuzz-nightly-test:
    runs-on: ubuntu-latest
    steps:
      ...
      - name: Set crashers count
        working-directory: test/fuzz
        run: echo "::set-output name=crashers-count::$(find . -type d -name 'crashers' | xargs -I % sh -c 'ls % | wc -l' | awk '{total += $1} END {print total}')"
        id: set-crashers-count

   outputs:
     crashers-count: ${{ steps.set-crashers-count.outputs.crashers-count }}

  fuzz-nightly-fail:
    needs: fuzz-nightly-test
    if: ${{ needs.set-crashers-count.outputs.crashers-count != 0 }}
    runs-on: ubuntu-latest
    steps:
      ...

Does anybody know what I am doing wrong? Thank you!

Upvotes: 6

Views: 11292

Answers (1)

jidicula
jidicula

Reputation: 3929

I did a bunch of tests with a similar minimal example and I think I figured out the issue. Most immediately, in your if directive in your fuzz-nightly-fail job, you need to be accessing needs.<job_id>.outputs.<job_output_id> rather than needs.<step_id>.outputs.<job_output_id>. Therefore, the if directive would become if: ${{ needs.fuzz-nightly-test.outputs.crashers-count != 0 }}.

Additionally, you should probably make a step output ID that's distinct from the job output ID to save yourself from some confusion about what context object is being referenced where. So, the run statement in your first job could be something like run: echo "::set-output name=count::$(find . -type d -name 'crashers' | xargs -I % sh -c 'ls % | wc -l' | awk '{total += $1} END {print total}')" and the job output would also be changed to crashers-count: ${{ steps.set-crashers-count.outputs.count }}. Putting this all together, we get

jobs:
  fuzz-nightly-test:
    runs-on: ubuntu-latest
    steps:
      ...
      - name: Set crashers count
        working-directory: test/fuzz
        run: echo "::set-output name=count::$(find . -type d -name 'crashers' | xargs -I % sh -c 'ls % | wc -l' | awk '{total += $1} END {print total}')"
        id: set-crashers-count

   outputs:
     crashers-count: ${{ steps.set-crashers-count.outputs.count }}

  fuzz-nightly-fail:
    needs: fuzz-nightly-test
    if: ${{ needs.fuzz-nightly-test.outputs.crashers-count != 0 }}
    runs-on: ubuntu-latest
    steps:
      ...

The reason for this isn't immediately obvious from the documentation alone, but the example here implies that <step_id>.outputs.foo is different from <job_id>.outputs.foo - jobs.job1.outputs.output1 is defined as that job's steps.step1.outputs.test.

You can see a (very) minimal example of this here, with its corresponding workflow run here.

Upvotes: 16

Related Questions