Understanding the execution model explains puzzling behaviour like edits not taking effect or runs that never start.
When an event arrives, GitHub reads .github/workflows/ at a specific commit, which depends on the event: the pushed commit for push, the PR merge commit for pull_request, the default branch for schedule, workflow_dispatch defaults and pull_request_target. That is why a fix to a scheduled workflow only matters once merged to the default branch, and why pull_request_target uses the base branch's trusted copy.
Each matching workflow becomes a run with a run_id, a run_number and an attempt count for re-runs. GitHub evaluates the job graph: jobs whose needs are met and whose job-level if is true are queued; matrices are expanded into individual jobs at that point, which is why a matrix can depend on an earlier job's output.
A queued job waits for a runner matching its runs-on labels. Hosted runners are limited by your plan's concurrent job quota; self-hosted ones by how many are online. A job with no matching runner waits up to 24 hours before failing.
On the runner, the runner application downloads all referenced actions first (so a broken uses: fails before any step), then executes steps, streaming logs back. Limits to remember: jobs run at most 6 hours on hosted runners, workflow runs at most 35 days, and re-running failed jobs reuses the same commit and workflow definition.
Example
# Inspect runs and attempts with the GitHub CLI
gh run list --workflow ci.yml --limit 3
# STATUS TITLE WORKFLOW BRANCH EVENT ID
# ✓ Fix parser CI main push 123456789
gh run view 123456789 --log-failed # only the failing steps' logs
gh run rerun 123456789 --failed # new attempt, same commit and YAML
gh workflow run deploy.yml -f environment=staging # workflow_dispatch
gh run watch # follow a run liveRemember
- The workflow file is read at the event's commit (default branch for schedule)
- Matrices expand when a job becomes ready, so they can use earlier outputs
- Re-runs reuse the original commit and workflow definition
Watch out for
- Editing a workflow and re-running an old run, expecting the edit to apply.