Step outputs, job outputs and summaries

GitHub Actions · Practical · 10 min

Pipelines constantly need to hand a computed version, tag or path to the next step or job.

Steps communicate by appending to special files whose paths GitHub puts in environment variables:

  • GITHUB_OUTPUT: echo "name=value" >> "$GITHUB_OUTPUT" sets an output of the current step, read later as steps.<id>.outputs.name.
  • GITHUB_ENV: echo "NAME=value" >> "$GITHUB_ENV" makes NAME an environment variable for all following steps of the job (not the current one).
  • GITHUB_PATH: append a directory to put it on PATH for later steps.
  • GITHUB_STEP_SUMMARY: Markdown appended here appears on the run's summary page; great for test reports.

To pass a value to another job, declare it under the job's outputs, mapping it from a step output, then read it in the dependent job as needs.<job>.outputs.<name>. Job outputs are strings, limited to 1 MB per job; use artifacts for files.

Multi-line values need a delimiter syntax:

{ echo "notes<<EOF"; cat notes.txt; echo "EOF"; } >> "$GITHUB_OUTPUT"

The old ::set-output workflow command is deprecated; always use the files above. Outputs that contain secrets are masked and may be dropped when passed between jobs.

Example

jobs:
  version:
    runs-on: ubuntu-latest
    outputs:
      tag: ${{ steps.v.outputs.tag }}      # expose step output as job output
    steps:
      - id: v
        run: echo "tag=v1.$GITHUB_RUN_NUMBER" >> "$GITHUB_OUTPUT"
      - run: echo "BUILT_AT=$(date -u +%F)" >> "$GITHUB_ENV"
      - run: echo "### Built ${{ steps.v.outputs.tag }} on $BUILT_AT" >> "$GITHUB_STEP_SUMMARY"
  publish:
    needs: version
    runs-on: ubuntu-latest
    steps:
      - run: echo "Publishing ${{ needs.version.outputs.tag }}"   # Publishing v1.42

Remember

  • Step output: append name=value to $GITHUB_OUTPUT
  • GITHUB_ENV affects later steps only
  • Cross-job values go through job outputs and needs.<job>.outputs

Watch out for

  • Reading a GITHUB_ENV variable in the same step that set it: it is only visible from the next step.

Check yourself

  1. How does job B read output tag set by a step in job A?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/passing-information-between-jobs