Chapter 08Lesson 01~145 minutes

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.

Hosted runnersImagesLabelsEphemeral jobsRuntime evidence

Learning objectives

  • Explain the complete path from runs-on label 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 -latest is 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.

Hosted-runner lifecycle and evidence boundary
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.

Versioned OS labels reduce one source of drift, not all drift.

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.

Next lesson

Cross-OS runner probe

Run one controlled probe on Ubuntu, Windows, and optionally macOS; compare safe metadata and then pin Python with an immutable official setup action.

Knowledge check

What does runs-on: ubuntu-24.04 guarantee?

Can two separate hosted jobs rely on the same temp file?

Why record ImageVersion?

Why is ubuntu-latest unsuitable as a strict reproducibility pin?

What evidence separates a runner problem from an external-service problem?

Official references and version notes

Version and compatibility note

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.