GitHub Actions Tutorial — Action Inputs & Outputs
Action Inputs & Outputs
Actions communicate through inputs (configuration you pass in) and outputs (data the action produces). Understanding this interface is key to chaining actions together effectively.
Passing Inputs with with:
The with: keyword passes inputs to an action:
steps:
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
Each action defines its own inputs in its action.yml file. Check the action’s README or action.yml for available inputs.
Required vs Optional Inputs
# This action has both required and optional inputs
- uses: actions/upload-artifact@v4
with:
name: my-artifact # required
path: ./dist # required
retention-days: 5 # optional (default: 90)
if-no-files-found: error # optional (default: warn)
If you skip a required input, the action will fail with a clear error message.
Reading Action Outputs
Actions produce outputs that downstream steps can read. You need to:
- Give the step an
id: - Reference the output with
${{ steps.<id>.outputs.<name> }}
steps:
- uses: actions/checkout@v4
- name: Get changed files
id: changes
uses: dorny/paths-filter@v3
with:
filters: |
src:
- 'src/**'
docs:
- 'docs/**'
- name: Use the output
run: |
echo "Source changed: ${{ steps.changes.outputs.src }}"
echo "Docs changed: ${{ steps.changes.outputs.docs }}"
Real-World Example — Docker Build and Push
steps:
- uses: actions/checkout@v4
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
id: docker-build
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: myorg/myapp:latest,myorg/myapp:${{ github.sha }}
- name: Image digest
run: echo "Digest: ${{ steps.docker-build.outputs.digest }}"
The docker/build-push-action produces outputs like digest and imageid that you can reference in later steps.
Passing Dynamic Values as Inputs
You can use expressions in with: values:
steps:
- uses: actions/checkout@v4
- name: Set version
id: ver
run: echo "tag=v$(date +%Y%m%d)-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: myorg/myapp:${{ steps.ver.outputs.tag }}
Environment Variables vs Inputs
| Mechanism | Syntax | When to Use |
|---|---|---|
with: inputs |
with: key: value |
Configure an action |
env: variables |
env: KEY: value |
Set env vars for run: commands |
steps:
# 'with:' configures the action's inputs
- uses: actions/setup-node@v4
with:
node-version: '20'
# 'env:' sets environment variables for shell commands
- run: echo "API is $API_URL"
env:
API_URL: https://api.example.com
Common Mistakes
| Mistake | Fix |
|---|---|
| Output is empty | Ensure the step has an id: and check the action docs for correct output name |
| Wrong input name | Check the action’s action.yml for exact input names (case-sensitive) |
Using env: instead of with: |
Actions read with: inputs; env: is for shell commands |
| Input type mismatch | Some inputs expect strings even for booleans: 'true' not true |
Quick Reference
| Concept | Syntax |
|---|---|
| Pass input | with: key: value |
| Step ID | id: my-step |
| Read output | ${{ steps.my-step.outputs.name }} |
| Dynamic input | with: tag: ${{ steps.ver.outputs.tag }} |
← Previous: Checkout & Setup
Next: Step Outputs →