Syntax Reference
Top-Level Structureโ
name: Workflow Name # displayed in GitHub UI
on: ... # triggers (see core-concepts)
env: # workflow-level env vars (available to all jobs)
NODE_ENV: production
jobs:
job-id: # arbitrary key, used in needs:
runs-on: ubuntu-latest
env: ... # job-level env vars
steps: ...
Contextsโ
Contexts are objects available inside ${{ }} expressions.
| Context | Description |
|---|---|
github.sha | The commit SHA that triggered the workflow |
github.ref | Branch or tag ref (e.g. refs/heads/main) |
github.actor | Username that triggered the run |
github.event_name | Event that triggered (e.g. push, pull_request) |
github.repository | owner/repo string |
env.MY_VAR | Env var set at workflow/job/step level |
secrets.NAME | Secret from repo/org settings |
needs.job-id.outputs.key | Output from an upstream job |
matrix.<property> | Current matrix dimension value (e.g. matrix.os, matrix.node-version) |
Expressionsโ
Use ${{ }} anywhere in YAML values:
- name: Print branch
run: echo "Branch is ${{ github.ref }}"
- name: Use secret
env:
TOKEN: ${{ secrets.MY_TOKEN }}
run: curl -H "Authorization: Bearer $TOKEN" ...
Built-in Functionsโ
| Function | Example | Returns |
|---|---|---|
contains(str, substr) | contains(github.ref, 'main') | bool |
startsWith(str, prefix) | startsWith(github.ref, 'refs/tags/') | bool |
endsWith(str, suffix) | endsWith(github.actor, 'bot') | bool |
format(str, args...) | format('Hello {0}', github.actor) | string |
join(array, sep) | join(matrix.os, ', ') | string |
toJSON(value) | toJSON(github.event) | string |
fromJSON(string) | fromJSON(steps.parse.outputs.result) | object |
if: Conditionalsโ
Apply to jobs or individual steps. Uses expression syntax without ${{ }}.
jobs:
deploy:
if: github.ref == 'refs/heads/main' # only run on main
runs-on: ubuntu-latest
steps:
- name: Only on push (not PR)
if: github.event_name == 'push'
run: echo "deploying"
- name: Only on failure of previous step
if: failure()
run: echo "something went wrong"
Common condition functions:
| Function | When it's true |
|---|---|
success() | All previous steps passed (default) |
failure() | Any previous step failed |
always() | Regardless of previous step results |
cancelled() | Workflow was cancelled |
Job Outputsโ
Pass data from one job to another using outputs + needs.
jobs:
build:
runs-on: ubuntu-latest
outputs:
image-tag: ${{ steps.tag.outputs.tag }} # expose step output as job output
steps:
- name: Set image tag
id: tag
run: echo "tag=${{ github.sha }}" >> $GITHUB_OUTPUT
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Use tag from build job
run: echo "Deploying ${{ needs.build.outputs.image-tag }}"
Reusable Workflowsโ
Split common pipelines into shared workflow files called by other workflows.
Caller (/.github/workflows/ci.yml):
jobs:
security:
uses: ./.github/workflows/security-scan.yml # local reusable workflow
with:
environment: production
secrets: inherit # pass all secrets through
Called workflow (/.github/workflows/security-scan.yml):
on:
workflow_call: # makes this workflow callable
inputs:
environment:
required: true
type: string
secrets:
TOKEN:
required: false
jobs:
scan:
runs-on: ubuntu-latest
steps:
- run: echo "Scanning for ${{ inputs.environment }}"