If you run self-hosted GitHub Actions runners, put this date in your calendar: September 25, 2026. That's when GitHub permanently stops queuing jobs to runners on outdated versions. Before that, brownouts: Sep 7, 9, 11, 14, 16, 18 — on Config + Runtime days, outdated runners don't register and don't execute jobs.
The failure mode is quiet. Nothing in your workflow errors out. The runner log says Runner version v2.xxx.0 is deprecated and cannot receive messages and every job targeting it sits in Queued. If you use Actions Runner Controller, auto-update is disabled by design, so the image tag in your Helm values is effectively a scheduled outage with an unknown date.
What changed on September 3
GitHub shipped an endpoint that returns the end-of-life date for any runner version:
gh api orgs/<org>/actions/runners/deprecations/2.334.0
{
"runner_version": "2.334.0",
"runtime_deprecates_at": "2026-08-10T00:00:00Z",
"registration_deprecates_at": "..."
}
Two things I learned running this against real versions:
- The documented rule is "30 days after release", but the API returns roughly 63–71 days for current versions. If you were computing this from release dates, your numbers are wrong in both directions.
- The runner list endpoint now includes each runner's
version, so you don't need an agent on the machines.
One command for the whole fleet
I wrapped the two endpoints in a small open-source gh extension:
gh extension install canblmz1/gh-runner-eol
gh runner-eol audit <org> --scan .
43 self-hosted runners · 3 versions · 4 pinned refs in .
OVERDUE 18 runners v2.334.0 runtime support ended 2026-08-10 26 days overdue
WARNING 12 runners v2.336.0 runtime support ends 2026-09-15 10 days left
OK 13 runners v2.337.0 no end-of-life scheduled
Pinned in source
OVERDUE Dockerfile:1 ghcr.io/actions/actions-runner:2.335.0 22 days overdue
WARNING deploy/values.yaml:5 ghcr.io/actions/actions-runner:2.336.0 10 days left
--scan is the part I care about most: it greps Dockerfiles, ARC Helm values, RUNNER_VERSION= variables and download URLs for pinned versions, and resolves each one against the API. Those are the runners you haven't scaled up yet — a live-runner dashboard can't see them.
It also runs as a GitHub Action with SARIF output, so a pinned line shows up as a Code Scanning annotation in the PR that introduces it, and exits non-zero on overdue so a weekly schedule can page you.
- uses: canblmz1/gh-runner-eol@v0
with:
target: my-org
token: ${{ secrets.RUNNER_EOL_TOKEN }}
scan: .
format: sarif
- uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: runner-eol.sarif
Gotchas
- The workflow
GITHUB_TOKENcannot read self-hosted runners (403). Use a fine-grained PAT or GitHub App token with Self-hosted runners: read (org) or Administration: read (repo). Or runmode: scanfor source-only. - It's read-only and deliberately does not upgrade or manage runners. ARC, GARM and friends do that; this only answers "what breaks, and when".
Repo: https://github.com/canblmz1/gh-runner-eol (MIT). If it misses a pinned-version shape in your repo, there's an issue template for exactly that — a regex and a test is a 10-line PR.
**
**
Top comments (0)