The Workflow File
Workflows are YAML files stored in .github/workflows with name, on, and jobs keys.
Syntax
.github/workflows/<name>.ymlEvery workflow is a .yml file inside .github/workflows/. YAML uses indentation (spaces, never tabs) to show structure.
Top-level keys
name— a label shown in the Actions tab.on— the event(s) that trigger the workflow.jobs— the work to run, one or more jobs.
You can have many workflow files; each is independent and appears separately in the Actions tab.
Example
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: echo "Building the project..."When to use it
- A developer stores a .github/workflows/ci.yml file to define the project's CI pipeline entirely in version-controlled code.
- A team splits workflows into separate YAML files for CI, CD, and nightly jobs so each file remains focused and easy to maintain.
- A developer uses YAML anchors and env blocks in a workflow file to avoid repeating the same configuration across multiple jobs.
More examples
Workflow file basic anatomy
Shows the top-level keys of a complete workflow file: name, on triggers, env variables, and a single job with ordered steps.
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
env:
NODE_VERSION: '20'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- run: npm ci
- run: npm testUse workflow-level and job-level env
Workflow-level env is available to all jobs; job-level env is scoped to that job only and can override the workflow value.
env:
APP_ENV: staging
jobs:
deploy:
runs-on: ubuntu-latest
env:
DEPLOY_REGION: us-east-1
steps:
- run: echo "Deploying $APP_ENV to $DEPLOY_REGION"Set output from one step to another
Writes a key=value pair to GITHUB_OUTPUT so a later step in the same job can read it via the steps context.
steps:
- id: version
run: echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
- name: Use version
run: echo "Building version ${{ steps.version.outputs.tag }}"
Discussion