Contexts and Expressions

Contexts, Expressions and the github Object

Anything inside ${{ }} is an expression, evaluated by GitHub 29 before the step reaches the runner. It reads contexts: github (event, ref, SHA, actor, and the webhook payload as github.event), inputs, env, vars, secrets, steps, needs, runner, matrix and a few more; runs-on and a job's if cannot use env.

The context job of fundamentals.ymlYAML
  context:
    runs-on: ${{ inputs.runner || 'ubuntu-24.04' }}
    steps:
      - name: Show some context values
        env:
          EVENT: ${{ github.event_name }}
          REF: ${{ github.ref }}
          PR: ${{ github.event.pull_request.number || 'none' }}
          RUNNER: ${{ format('{0}/{1}', runner.os, runner.arch) }}
          ON_MAIN: ${{ github.ref == 'refs/heads/main' }}
        run: |
          echo "event=$EVENT ref=$REF pr=$PR on_main=$ON_MAIN"
          echo "runner=$RUNNER image=$ImageOS/$ImageVersion node=$(node --version)"

It printed these lines in the runs for pull request #16, its merge, and the manual run on ubuntu-26.04:

Output of 61
event=pull_request ref=refs/pull/16/merge pr=16 on_main=false
runner=Linux/X64 image=ubuntu24/20260920.314.1 node=v22.23.2
event=push ref=refs/heads/main pr=none on_main=true
runner=Linux/X64 image=ubuntu24/20260920.314.1 node=v22.23.2
event=workflow_dispatch ref=refs/heads/main pr=none on_main=true
runner=Linux/X64 image=ubuntu26/20260920.143.1 node=v24.21.0

On a pull request github.ref is the test-merge ref of Actions and Git Storage. github.event.pull_request is null for other events, and || returns its first truthy operand, hence none. Functions include contains, startsWith, fromJSON, hashFiles and toJSON (toJSON(github) dumps the whole object while you debug).