Events, contexts, expressions, and secrets form the programmable backbone of every Actions workflow.
Contexts
Contexts are objects containing information about the workflow run, runner, job, and more. Access them with the ${{ }} expression syntax.
| Context |
Contains |
Example |
github |
Event payload, repo, ref, actor |
${{ github.ref_name }} |
env |
Environment variables |
${{ env.NODE_ENV }} |
secrets |
Encrypted secrets |
${{ secrets.API_KEY }} |
vars |
Configuration variables |
${{ vars.DEPLOY_URL }} |
job |
Current job status, outputs |
${{ job.status }} |
steps |
Step outputs and outcomes |
${{ steps.build.outputs.version }} |
runner |
Runner OS, arch, temp dir |
${{ runner.os }} |
needs |
Outputs from dependent jobs |
${{ needs.build.outputs.tag }} |
matrix |
Current matrix values |
${{ matrix.node-version }} |
Expressions & Functions
# Conditionals
if: github.event_name == 'push'
if: contains(github.event.head_commit.message, '[skip ci]')
if: startsWith(github.ref, 'refs/tags/v')
if: always() # run even if previous steps fail
if: failure() # run only if previous steps failed
if: cancelled() # run only if workflow was cancelled
# String functions
${{ format('Hello {0}', github.actor) }}
${{ join(github.event.issue.labels.*.name, ', ') }}
# JSON functions
${{ toJSON(github.event) }}
${{ fromJSON(steps.metadata.outputs.json) }}
# Comparison operators
if: github.event.pull_request.draft == false
if: github.run_attempt > 1
Secrets & Variables
# Secrets: encrypted, masked in logs
# Set in: Settings > Secrets and variables > Actions
# Repository secrets
${{ secrets.DEPLOY_TOKEN }}
# Organization secrets (shared across repos)
${{ secrets.ORG_NPM_TOKEN }}
# Environment secrets (scoped to environment)
${{ secrets.PROD_DATABASE_URL }}
# GITHUB_TOKEN: auto-generated per workflow run
${{ secrets.GITHUB_TOKEN }}
# or equivalently:
${{ github.token }}
GITHUB_TOKEN permissions: Defaults to read-only for forked PRs. Configure with the permissions key at the workflow or job level. Always follow least-privilege.
Step Outputs
steps:
- name: Get version
id: version
run: echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
- name: Use version
run: echo "Deploying ${{ steps.version.outputs.tag }}"
# Job outputs (for cross-job communication)
jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.tag }}
steps:
- id: version
run: echo "tag=v1.2.3" >> $GITHUB_OUTPUT
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "Deploying ${{ needs.build.outputs.version }}"