GitHub Actions: CI/CD Workflows From First Run to Secure Deployments · Pipelines, Deployments and Security
Pipelines: Job Dependencies, Outputs and Artifacts
Order jobs with needs, pass values with job outputs, and move build files between jobs with artifacts.
What you'll build
A three-job pipeline: build a package, test it, and deploy it, where the build's version and files flow to the later jobs.
The idea
Each job runs on its own fresh machine, so jobs share data explicitly:
needs:makes a job wait for others. If a needed job fails, the dependent job is skipped.- Job outputs pass small strings: declare
outputs:on the job, read${{ needs.<job>.outputs.<name> }}. - Artifacts pass files:
actions/upload-artifactin one job andactions/download-artifactin another. Artifacts are also kept on the run page for download. if: ${{ always() }}makes a job (such as a notification) run even when its dependencies failed.
The code
name: Pipeline
on:
push:
branches: [main]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.ver.outputs.version }}
steps:
- uses: actions/checkout@v4
- id: ver
run: echo "version=2.1.${GITHUB_RUN_NUMBER}" >> "$GITHUB_OUTPUT"
- run: mkdir dist && tar -czf dist/app.tar.gz src
- uses: actions/upload-artifact@v4
with:
name: app
path: dist/app.tar.gz
retention-days: 7
test:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: app
- run: tar -tzf app.tar.gz
deploy:
needs: [build, test]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: app
- run: echo "Deploying ${{ needs.build.outputs.version }}"
Output
actionlint: no problems found workflow: Pipeline triggers: push (branches: main) jobs, in the order they run: build: runs on ubuntu-latest | 4 step(s) test: runs on ubuntu-latest | 2 step(s) | after build deploy: runs on ubuntu-latest | 2 step(s) | after build, test
Run this on your computer — see “Get Started” for setup.
Common mistakes
- Expecting files to persist between jobs. They don't; upload and download an artifact.
- Forgetting
needsfor the output. A job can only read outputs of jobs it lists inneeds. - Large or sensitive artifacts. Artifacts are readable by anyone with repository access and count against storage; set
retention-days. - Using the same artifact name from a matrix. In v4 names must be unique per run; add the matrix value to the name.
Key points
needsorders jobs; failed dependencies skip dependents.- Outputs carry small values, artifacts carry files.
always()runs cleanup or notification jobs after failures. Further reading: GitHub Docs.
Practice questions
How would the deploy job get the compiled package from the build job?
Answer
The build job uploads it with actions/upload-artifact and the deploy job downloads it with actions/download-artifact, because jobs run on separate machines.
What is the difference between a job output and an artifact?
Answer
A job output is a small string value passed through the needs context. An artifact is a file or folder stored by GitHub and downloaded by later jobs or by people.
Open in the app to mark lessons complete, take notes and track your progress.