Skip to content

Commit bdd9010

Browse files
committed
ci: name the Ubuntu image instead of asking for the queue
`ubuntu-latest` is the only runner label in this repository that waits for a runner. Between 07:00 and 14:00 UTC its median queue is 15.8 minutes for a single-job lane and 33.4 for CI, while `ubuntu-24.04`, `ubuntu-24.04-arm`, `windows-2025` and `macos-15` all sit at 0.3 minutes in the same window and `macos-latest` and `windows-latest` at 0.1. Outside 07:00-14:00 every label including `ubuntu-latest` is at 0.1, so this is contention during working hours, not a property of the work. The sharpest control is one `gitoxide-helper-admission` run fanning out to three operating systems from a single `created_at`: median queue 15.0 / 0.1 / 0.1 minutes. It is not the `-latest` alias, since two of those three are aliases. It is not our own `concurrency` groups, since every workflow's median `run_started_at - created_at` is 0.0. It is not a self-hosted split, since `runner_group_name` reads `GitHub Actions` on both sides. `ubuntu-latest` resolves to `ubuntu24` today — image `ubuntu24/20260823.283` — so naming `ubuntu-24.04` asks for the same machine and changes no behaviour. Thirteen jobs across the release and packaging workflows already pin it; these eight were the ones still on the alias. `windows-latest` and `macos-latest` are deliberately left alone. They cost nothing to wait for, and pinning them would be a real image change for no measured gain. What this costs is the automatic image upgrade: when GitHub moves `latest`, these labels move by hand. The test that holds the rule says so. Refs #4480
1 parent afbcabd commit bdd9010

9 files changed

Lines changed: 43 additions & 9 deletions

.github/workflows/ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ jobs:
4242
# Renaming it would leave that check unreported on every open pull request
4343
# until the rename merged, and nothing could merge while it was unreported.
4444
test:
45-
runs-on: ubuntu-latest
45+
# Pinned, not `ubuntu-latest`, and the two resolve to the same image today.
46+
# `ubuntu-latest` is the only label in this repository that queues:
47+
# `ci-workflow-policy.test.mjs` holds the rule and the measurements.
48+
runs-on: ubuntu-24.04
4649
timeout-minutes: 45
4750
steps:
4851
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

.github/workflows/copilot-auto-review.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
github.event.pull_request.draft == false &&
3434
!endsWith(github.event.pull_request.user.login, '[bot]') &&
3535
!contains(github.event.pull_request.labels.*.name, 'copilot-skip')
36-
runs-on: ubuntu-latest
36+
runs-on: ubuntu-24.04
3737
timeout-minutes: 5
3838

3939
steps:

.github/workflows/dependency-audit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ concurrency:
5050

5151
jobs:
5252
audit:
53-
runs-on: ubuntu-latest
53+
runs-on: ubuntu-24.04
5454
timeout-minutes: 45
5555
steps:
5656
- name: Check out the repository

.github/workflows/gitoxide-helper-admission.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ jobs:
5757
fail-fast: false
5858
matrix:
5959
os:
60-
- ubuntu-latest
60+
- ubuntu-24.04
6161
- macos-latest
6262
- windows-latest
6363
steps:

.github/workflows/issue-pr-lifecycle.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ concurrency:
4646
jobs:
4747
lifecycle:
4848
if: github.repository == 'apache/maka'
49-
runs-on: ubuntu-latest
49+
runs-on: ubuntu-24.04
5050
timeout-minutes: 15
5151

5252
steps:

.github/workflows/pr-effort-label.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ concurrency:
4646

4747
jobs:
4848
label:
49-
runs-on: ubuntu-latest
49+
runs-on: ubuntu-24.04
5050
timeout-minutes: 10
5151

5252
steps:

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ concurrency:
3434

3535
jobs:
3636
release-identity:
37-
runs-on: ubuntu-latest
37+
runs-on: ubuntu-24.04
3838
timeout-minutes: 10
3939
outputs:
4040
version: ${{ steps.identity.outputs.version }}
@@ -364,7 +364,7 @@ jobs:
364364
# One draft release carries both platforms, so it is created once, after
365365
# every platform has been packaged and verified.
366366
needs: [release-identity, desktop, cli-macos-arm64]
367-
runs-on: ubuntu-latest
367+
runs-on: ubuntu-24.04
368368
timeout-minutes: 15
369369
permissions:
370370
contents: write

.github/workflows/runtime-host-peer-admission.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ concurrency:
5353
jobs:
5454
test:
5555
name: quality
56-
runs-on: ubuntu-latest
56+
runs-on: ubuntu-24.04
5757
timeout-minutes: 45
5858
steps:
5959
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

scripts/ci-workflow-policy.test.mjs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,37 @@ test('the recovery lane pairs its path filter with a nightly run and a main push
375375
assert.match(readWorkflow('windows-recovery.yml'), /\n {4}name: windows_recovery/u);
376376
});
377377

378+
test('no lane asks for the one runner label that queues', () => {
379+
// Measured across a full day of runs, `ubuntu-latest` is the only label here
380+
// that waits for a runner. Between 07:00 and 14:00 UTC its median queue is
381+
// 15.8 minutes for a single-job lane and 33.4 for CI, while every pinned
382+
// label sits at 0.3 and `macos-latest` and `windows-latest` at 0.1. The
383+
// sharpest control is one `gitoxide-helper-admission` run fanning out to
384+
// three operating systems from one `created_at`: 15.0 / 0.1 / 0.1 minutes.
385+
// So it is not the `-latest` alias, and the other two are deliberately left
386+
// alone — they cost nothing and pinning them would change the image.
387+
//
388+
// `ubuntu-latest` resolves to the same image as `ubuntu-24.04` today, which
389+
// is why this costs no coverage. What it does cost is the automatic image
390+
// upgrade: when GitHub moves `latest`, these labels move by hand.
391+
for (const name of readdirSync(WORKFLOW_DIR).filter((file) => file.endsWith('.yml'))) {
392+
// Comments stripped, so explaining the rule in a workflow cannot break it,
393+
// and matrix entries included, since a runner named in a matrix leg costs
394+
// the same wait as one named on `runs-on`.
395+
const declarations = readWorkflow(name)
396+
.replaceAll(/^[ \t]*#.*$/gmu, '')
397+
.match(/^[ \t]*(?:runs-on:|runner:|-)[ \t]*\S+$/gmu);
398+
399+
for (const declaration of declarations ?? []) {
400+
assert.doesNotMatch(
401+
declaration,
402+
/\bubuntu-latest\b/u,
403+
`${name}: ubuntu-latest queues for a runner; name the image instead`,
404+
);
405+
}
406+
}
407+
});
408+
378409
test('the recovery lane keeps every run kind out of one shared concurrency group', () => {
379410
const workflow = readWorkflow('windows-recovery.yml');
380411

0 commit comments

Comments
 (0)