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 assteps.<id>.outputs.name.GITHUB_ENV:echo "NAME=value" >> "$GITHUB_ENV"makesNAMEan environment variable for all following steps of the job (not the current one).GITHUB_PATH: append a directory to put it onPATHfor 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.42Remember
- 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.