GitHub-Hosted Runners, Images, Labels, Hardware, and Runtime Behavior: Core Concepts and Mental Model
A workflow label such as ubuntu-latest looks simple,
but it selects a changing execution environment: an OS image,
architecture, hardware class, preinstalled software set, filesystem
layout, shell behavior, network identity, and fresh-job lifecycle.
This lesson builds a runner-first mental model so you can explain
exactly where a job ran and which mutable dependencies influenced
its result.
Learning objectives
-
Explain the complete path from
runs-onlabel to hosted image, architecture, hardware, job process and teardown. - Distinguish workflow configuration from runner image state, toolchain state, workspace state and external network state.
- Read safe runner metadata without dumping credentials or the entire environment.
-
Explain why
-latestis a moving compatibility choice rather than a reproducibility pin. - Identify which evidence must be preserved to reproduce a hosted-runner failure later.
1. The label is not the machine
runs-on is a routing request. GitHub resolves the label
to an eligible hosted runner class, provisions a fresh instance for
the job, starts the runner process, executes ordered steps, and
destroys the instance when the job ends. Reproducibility therefore
depends on more than the YAML label.
flowchart TD A[runs-on label] --> B[Eligible hosted image and architecture] B --> C[Fresh job instance] C --> D[Runner context and image release] D --> E[Shell and toolchain] E --> F[Workspace / temp / tool cache] F --> G[Network and external services] G --> H[Job result and logs] H --> I[Instance teardown]
The important distinction is causal: the label requests a class; the actual image release and tools are runtime dependencies; the workspace exists only inside that job; external systems outlive the runner and require separate verification.
2. State inventory before execution
| State | Examples | Owner / lifetime |
|---|---|---|
| Workflow routing | runs-on: ubuntu-24.04 |
Repository workflow revision; persists in Git. |
| Runner context |
runner.os, runner.arch,
runner.temp
|
GitHub Actions job runtime. |
| Hosted image |
ImageOS, ImageVersion,
included-software manifest
|
GitHub image release; updated independently of your repository. |
| Toolchain | Python, Node, Java, Git, Docker, compilers | Image preinstall or explicit setup action. |
| Job filesystem | GITHUB_WORKSPACE, temp files |
Fresh job instance; destroyed after job. |
| External state | Package registry, API, database, cloud target | External system; not deleted when the runner is torn down. |
3. Current label map: useful, but time-stamped
As of this chapter's verification date,
ubuntu-latest selects Ubuntu 24.04 x64,
windows-latest selects Windows Server 2025 x64, and
macos-latest selects macOS 26 on Arm64. GitHub can
migrate a -latest label to a newer stable image after
advance notice. That is why production evidence should record the
actual image release, not merely the friendly label.
ubuntu-24.04 fixes the OS generation, but the weekly
image release can still update preinstalled packages. Pin the
application toolchain explicitly when correctness depends on a
particular version.
4. Fresh job instance means job-local filesystem
All steps in one hosted job execute on the same provisioned
instance, so they can exchange files through the workspace or temp
directory. A second job receives another fresh instance. If job B
needs a file from job A, use an explicit cross-job transport such as
an artifact or a reproducible rebuild—not an assumption that
/tmp or C:\temp survives.
permissions: {}
jobs:
first:
runs-on: ubuntu-24.04
steps:
- run: printf 'job-a\n' > "$RUNNER_TEMP/job-a.txt"
second:
runs-on: ubuntu-24.04
steps:
- run: |
test ! -e "$RUNNER_TEMP/job-a.txt"
echo 'fresh_job_state=true'
5. Read-only runner inspection
Start with a probe that records only non-sensitive runtime facts. Do not dump the whole environment, because later chapters may introduce secrets.
name: runner-readonly-probe
on: workflow_dispatch
permissions: {}
jobs:
inspect:
runs-on: ubuntu-24.04
steps:
- name: Safe runner metadata
shell: bash
run: |
set -euo pipefail
printf 'runner_os=%s\n' '${{ runner.os }}'
printf 'runner_arch=%s\n' '${{ runner.arch }}'
printf 'image_os=%s\n' "${ImageOS:-unknown}"
printf 'image_version=%s\n' "${ImageVersion:-unknown}"
printf 'workspace=%s\n' "$GITHUB_WORKSPACE"
printf 'temp=%s\n' "$RUNNER_TEMP"
uname -a
python3 --version
git --version
The exact ImageVersion is more useful than “Ubuntu
24.04” when diagnosing a regression that appeared after an image
rollout.
6. Hardware is a runner-class input
Standard hosted hardware depends on repository visibility and
OS/architecture. Public Linux/Windows standard runners currently
have more CPU/RAM than their private-repository counterparts. macOS,
Arm64, ubuntu-slim, and larger runners differ again.
Avoid code that infers correctness from a presumed core count, disk
size, or CPU vendor.
Performance measurements on hosted runners are especially sensitive to this boundary. A CI runtime change can come from application code, dependency changes, image updates, queueing, storage, or hardware class. Record enough state to separate those causes.
7. Network identity is not a stable machine identity
Standard GitHub-hosted runners use GitHub-managed networking with broad published IP ranges that can change. GitHub specifically discourages treating the full hosted-runner IP list as a simple internal allowlist. Static IP and private-network options belong to larger-runner/self-hosted designs and carry plan and platform constraints.
8. Common wrong mental models
- “latest means newest vendor OS.” It means GitHub's latest stable supported image and can lag the vendor's newest release.
- “Versioned OS label freezes packages.” Image software still changes over time.
- “My file will be there in the next job.” Hosted jobs receive separate instances.
- “The preinstalled Python is my dependency contract.” It is image state; use an explicit setup mechanism when version matters.
- “A green job proves an external target is healthy.” Runner completion and external service health are different states.
9. DevOps operating implication
A credible run record ties the source SHA to the workflow SHA,
runs-on label, actual image release, architecture,
toolchain versions, job/step result, and any external side effect.
That evidence transforms “CI broke on GitHub” into a testable
hypothesis about a specific execution dependency.
Knowledge check
What does runs-on: ubuntu-24.04 guarantee?
It selects the Ubuntu 24.04 hosted image class, but it does not freeze the weekly image release or every preinstalled tool version.
Can two separate hosted jobs rely on the same temp file?
No. Normal hosted jobs use fresh instances; use explicit data transport or rebuild the state.
Why record ImageVersion?
It identifies the concrete hosted image release used by the run, which helps correlate failures with image rollouts.
Why is ubuntu-latest unsuitable as a strict
reproducibility pin?
GitHub can migrate the label to a newer stable OS image and also updates image software over time.
What evidence separates a runner problem from an external-service problem?
Runner/image/tool logs identify local execution state, while separate API/service health evidence verifies the external target.
Official references and version notes
- GitHub-hosted runners reference — current standard/larger runner behavior, filesystem, networking, IP and privilege details.
-
Choosing the runner for a job
— current
runs-onlabels, public/private standard runner specifications and architecture availability. - Using GitHub-hosted runners — current fresh-instance execution model and runner selection.
- GitHub Actions runner images — authoritative current image-label mappings, image releases, weekly update cadence and included-software manifests.
- Ubuntu 24.04 software manifest — current Ubuntu 24.04 image software inventory; verify the run-specific image release rather than assuming this file is frozen.
- Windows Server 2025 software manifest — current Windows Server 2025 image software inventory.
- macOS 26 software manifest — current macOS 26 Arm64 hosted-image inventory.
-
Runner context
— current
runner.os,runner.arch,runner.temp,runner.tool_cacheand related context fields. - Default environment variables — current workspace, temp, repository, run and runner-related default environment state.
- Larger runners concept — current larger-runner plan boundaries and features such as additional resources, groups, autoscaling, GPU and networking options.
- Larger runners reference — current larger-runner hardware/network restrictions, static-IP and macOS caveats.
- setup-python releases — current official action release history; Chapter 08 uses an immutable SHA corresponding to v7.0.0.
Version-sensitive runner behavior was rechecked against current
primary GitHub documentation on 2026-09-09. At
verification time, ubuntu-latest maps to Ubuntu 24.04
x64, windows-latest to Windows Server 2025 x64, and
macos-latest to macOS 26 Arm64; Ubuntu 26.04 and
selected Arm64 images are available in preview. GitHub states that
runner-image software is typically updated weekly and that
-latest migrations are gradual, so a successful run
must record the actual image version/toolchain rather than
treating a label as a frozen machine. For standard hosted runners,
every normal job receives a fresh hosted instance; steps inside
one job share that instance, while separate jobs do not share its
filesystem. The ubuntu-slim single-CPU option is a
special container-on-shared-VM case and is not used in mandatory
labs. Current public-repository standard Linux/Windows x64 runners
provide 4 CPU/16 GB RAM/14 GB SSD, while private-repository
standard Linux/Windows x64 runners provide 2 CPU/8 GB RAM/14 GB
SSD; macOS and Arm64 classes have different specifications.
Hardware figures are therefore plan/repository/image inputs, not
universal constants. Larger runners are optional
organization/enterprise features and are not required for course
completion. Official actions/setup-python v7.0.0 is
pinned in examples to
5fda3b95a4ea91299a34e894583c3862153e4b97. The
mandatory probe logs only safe runner/tool metadata and never
dumps the complete environment or contexts.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.