Introduction
As workflows are built and become more complex, there is a necessity to share information between steps, jobs, and even workflows themselves.
One of the most common ways to share values is by using GitHub outputs, due to their simplicity and being a built-in feature of workflows.
This material aims to explore the usage of outputs, their limitations, and best practices. Even though it's straightforward, caution should be exercised in certain aspects.
Output between Steps
The syntax to generate an output should follow the pattern:
echo "<output_name>=<output_value>" >> $GITHUB_OUTPUT
One of the simplest examples is sharing between steps within the same job.
on:
push:
jobs:
step-outputs:
runs-on: ubuntu-latest
steps:
- name: Get runner name
id: runner
run: |
echo "name=ubuntu-latest" >> $GITHUB_OUTPUT
- name: Show output
run: echo ${{ steps.runner.outputs.name }}
In the above example, we have two steps: the first generates the output, and the second consumes it.
The first step has the attribute id
with the value runner
, allowing any other step within the same job to consume the generated output.
We can observe the consumption of the output in the second step using the following syntax:
${{ steps.<id_previous_step>.outputs.<output_name> }}
The result of the created workflow will display the value ubuntu-latest
.
Output between Jobs
To share output between jobs, it's necessary to add the output
property to the job that will generate the value.
This property should contain the reference to the step (as described above), and the job that will receive the value must have the needs property with the name of the preceding job.
Observe the example:
on:
push:
jobs:
job-1:
runs-on: ubuntu-latest
outputs:
runner-name: ${{ steps.runner.outputs.name }}
steps:
- name: Set runner name
id: runner
run: |
echo "name=ubuntu-latest" >> $GITHUB_OUTPUT
job-2:
runs-on: ubuntu-latest
needs: job-1
steps:
- name: Show job-1 output
run: |
echo "Output job-1: ${{ needs.job-1.outputs.runner-name}}"
Output with actions/core
It's also possible to use output through the github-script action.
This action is commonly used when integration with GitHub is required.
on:
push:
jobs:
job-actions-core:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v6
id: actions-core
with:
script: |
core.setOutput('result', 'core')
- name: show output actions-core
run: |
echo "${{ steps.actions-core.outputs.result }}"
What Not to Do
Overwriting the GITHUB_OUTPUT Variable
A common mistake to watch out for is overwriting the GITHUB_OUTPUT
variable within the same step. If this happens, all previously saved outputs will be lost.
on:
push:
jobs:
job-output-overwrite:
runs-on: ubuntu-latest
steps:
- name: Overwrite output
id: runner
run: |
echo "name=ubuntu-latest" >> $GITHUB_OUTPUT
echo "so=linux" > $GITHUB_OUTPUT
- name: show output
run: |
echo ${{ steps.runner.outputs.name }}
echo ${{ steps.runner.outputs.so }}
This occurs because the GITHUB_OUTPUT
variable has a file as a reference.
Similar to the /etc/environment
file, the GITHUB_OUTPUT
file is loaded with each new step.
Sharing Secrets
Values stored in secrets cannot be shared as output between jobs.
Let's assume there is a secret with the value my-secret
. To add a secret, simply follow the path Settings > Secrets and variables > Actions > New repository secret
.
Now let's assign the secret to an output.
jobs:
job-1-secret:
runs-on: ubuntu-latest
outputs:
value: ${{ steps.step-1.outputs.value }}
steps:
- name: Set secret as output
id: step-1
run: |
echo "value=${{ secrets.SECRET_OUTPUT }}" >> $GITHUB_OUTPUT
job-2-secret:
runs-on: ubuntu-latest
needs: job-1-secret
steps:
- name: Show output job-1-secret
run: |
echo "Output with secret: ${{ needs.job-1-secret.outputs.value}}"
Upon executing the workflow, the following warning will be received.
Deprecated Output
The syntax below works, but it's deprecated and should not be used as we do not know when it will cease to function.
on:
push:
jobs:
job-deprecated-output:
runs-on: ubuntu-latest
steps:
- name: Output deprecated
id: runner
run: echo "::set-output name=name::ubuntu-latest"
- name: show output
run: echo ${{ steps.runner.outputs.name }}
Upon execution, the following warning can be observed.
For more information, refer to the GitHub post about Deprecating save-state and set-output commands.
Summary
In summary, GitHub workflows allow for sharing information between steps, jobs, and workflows through outputs. However, it's necessary to be mindful of potential syntax errors, value overwrites, and to stay informed about best practices for the tool by following the changelog.
Top comments (2)
Thanks for your article, I'm just getting into GitHub Actions so this will come in handy.
I needed this!!! Thank you so much ❤️