In GitHub actions, outputs and contexts are essential tools for enhancing the functionality and efficiency of your CI/CD pipelines. Outputs facilitate data sharing between jobs and steps, while contexts provide a rich set of metadata and input variables for more intelligent automation. This topic will explore the specifics of these two features, covering their syntax, best practices, and practical applications for more effective automation solutions.
What are outputs?
In GitHub Actions, an "Output" is a way to store data that a job generates. Think of it like a container where you can put information that other jobs in the workflow might need later. For example, let's say you have a job that calculates the average score of a test. You can store this average score as an output, and then use it in another job that maybe sends out an email report.
Outputs are defined within a job in your GitHub Actions workflow file. They are essentially key-value pairs that you can reference in other jobs. Keys are the names you give to these outputs whereas values are the data you store.
Here's a simple example to illustrate this:
jobs:
job1:
runs-on: ubuntu-latest
outputs:
average_score: ${{ steps.calculate.outputs.score }}
steps:
- id: calculate
run: echo "score=85" >> $GITHUB_ENV
In this example, the job named job1 calculates an average score of 85 and stores it in an output named average_score.
Outputs are incredibly useful for passing data between jobs. They allow you to create more dynamic and interconnected workflows. For instance, one job builds your code and another job deploys it. The build job outputs the location of the built files, and the deploy job can use this output to know where to find the files for deployment.
Contexts in GitHub actions
Contexts serve as a way to access a variety of information that you might need during a workflow run. This information can include details about the workflow itself, variables, the environment of the runner, and even specifics about the job and steps within the workflow. To put it more technically, contexts are objects that contain properties. These properties can be strings or other objects. By using contexts, you can access this information and apply it where needed in your workflow. This enables you to create workflows that are more dynamic and adaptable to different conditions.
Types of contexts
GitHub Actions offers several types of contexts. Each provides different kinds of information. Here are some contexts for reference:
- Runner context: Provides details about the runner executing the job, such as its name, operating system, and architecture.
- Strategy context: Offers information about the matrix execution strategy for the current job.
- Needs context: Includes outputs from all jobs that the current job depends on.
- Matrix context: Contains properties defined in the workflow file that apply to the current job when using a matrix strategy.
- Inputs context: Contains input properties passed to an action, to a reusable workflow, or to a manually triggered workflow.
Here's an example that uses multiple types of contexts in a single YAML file, all within the same matrix strategy.
name: Contexts Example with Same Matrix and Inputs
on:
workflow_dispatch:
inputs:
custom_message:
description: 'Enter a custom message'
required: true
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
outputs:
example_output: "This is an example output."
steps:
- name: Show runner OS
run: echo "The runner operating system is ${{ runner.os }}"
- name: Use strategy context
run: |
echo "The index of the current job in the matrix is ${{ strategy.job-index }}"
echo "The total number of jobs in the matrix is ${{ strategy.job-total }}"
- name: Use input context
run: echo "The custom message is ${{ github.event.inputs.custom_message }}"
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Use needs context
run: echo "Output from build job is ${{ needs.build.outputs.example_output }}"
In this example, the workflow includes two jobs; build and deploy. The build job is part of a matrix strategy that runs on two different operating systems: ubuntu-latest and windows-latest. The strategy.job-index and strategy.job-total contexts reveal that the first job in the matrix (ubuntu-latest) has an index of 0 and is one of two jobs in the matrix. While the second job (windows-latest) has an index of 1 and is also part of the same two-job matrix.
Additionally, the inputs context captures a custom message from the user through the workflow_dispatch event, displayed using github.event.inputs.custom_message. The deploy job, which is not part of the matrix, uses the needs context to access and display an output from the build job, specifically "This is an example output." By integrating these contexts — strategy, inputs, and needs, the workflow achieves a high level of customization and interconnectivity, making it more dynamic and efficient.
Contexts are essential for making your workflows dynamic and responsive to different conditions. For example, you can use the needs context to check if a previous job was successful before running the next job. Or you can use the secrets context to access sensitive information securely.
How contexts interact with outputs
In GitHub Actions, the relationship between contexts and outputs is like a two-way street that allows data to flow seamlessly between different jobs in a workflow. Specifically, the needs Context plays a pivotal role in this interaction. When a job needs to use the output from a previous job, the needs context allows you to access that output. This creates a dependency chain where one job can rely on the results of another, making your workflows more interconnected and dynamic.
One common use case is in a Continuous Integration and Continuous Deployment (CI/CD) pipeline. In such a pipeline, you might have a job that builds your application and another that deploys it. The build job could generate an output containing the version number of the build or the path to the built artifacts. The deploy job could then use the needs context to access this output, ensuring it deploys the correct version or files.
Here's a simplified example to illustrate:
jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.build.outputs.version }}
steps:
- id: build
run: echo "version=1.0.0" >> $GITHUB_ENV
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "Deploying version ${{ needs.build.outputs.version }}"
In this example, the build job outputs the version number "1.0.0" and the deploy job uses this version number to ensure it's deploying the correct release.
Conclusion
We've looked at outputs and contexts in GitHub Actions and how they make workflows more dynamic and efficient. Here are the main points to remember:
-
Outputs are variables that hold data generated within a job. They facilitate the transfer of information between different jobs in a workflow.
-
Contexts provide a range of information about the current state of your workflow. Specific contexts like
runner,strategy,needs, andinputsallow you to customize jobs and steps according to various conditions. -
The
needscontext facilitates interaction between contexts and outputs by accessing outputs from preceding jobs. This enables a more cohesive and interconnected workflow.