Skip to content

ci: run our own code on our runners, forks stay on GitHub's - #116

Merged
askalf merged 7 commits into
mainfrom
ci/own-code-on-our-runners
Oct 6, 2026
Merged

askalf merged 7 commits into
mainfrom
ci/own-code-on-our-runners

Conversation

@askalf

@askalf askalf commented Oct 6, 2026

Copy link
Copy Markdown
Owner

Summary

Every required check here ran on GitHub's hosted runners, so each hosted outage held every PR. This follows askalf/dario#1531: our own code moves to cordon-exec, the non-root one-job runners on our host. Fork PRs stay on GitHub's.

A single runs-on expression picks the runner per job. Pushes, same-repo PRs, schedules and dispatches run on our runners. A fork's PR and a Dependabot PR run code nobody here wrote, so they resolve to ubuntu-latest.

Moved (expression):

  • ci.yml test
  • codeql.yml analyze (javascript-typescript), which gets 2G and two threads on our runner (the exec runners share one memory ceiling).
  • labels.yml manifest matches the repo
  • fleet-status-self-test

Moved (literal label, never runs PR code):

  • fleet-status.yml, which posts fleet/verify and fleet/review and runs only the default branch's script.
  • fleet-status-backfill.yml, which runs only on dispatch.

docker-build (required). The exec runners have no Docker daemon, because Docker on our host is root. The job is split three ways:

  • docker-build-inputs (our runner) checks which files changed.
  • docker-build-image (GitHub's runners) is the original build and boot smoke. It runs on every push to main. On a PR it runs only when a file the image is built from changed: the Dockerfile, .dockerignore, package.json/package-lock.json, tsconfig.json, src/, or build.yml.
  • docker-build, the required name, runs on our runner and passes only when the image job passed or was not owed.

The image is built from src/, so a source change still waits on GitHub's runners. A PR that changes only tests, docs, workflows or scripts does not.

Left on GitHub's runners:

  • fuzz.yml: not required, and CPU-heavy on a shared host. Same call as dario#1531.
  • cflite.yml and scorecard.yml: Docker-based actions.
  • release.yml: multi-arch Docker build and push.
  • pr-triage.yml (pull_request_target) and fleet-review-relay.yml (pull_request_review): they handle outside input.

Tests

  • scripts/fleet-status.test.mjs now evaluates the runs-on expression in every workflow that uses it. A fork's PR, a fork's review and a Dependabot PR resolve to ubuntu-latest; a same-repo PR, a push, a schedule and a dispatch resolve to cordon-exec. Any literal label on a PR-triggered workflow must be fleet-status.yml or keep forks off with a job if:. 173 pass locally.
  • This PR's own checks run on cordon-exec. They are the live proof.

GitHub's hosted queue has gone down several times this quarter, and
every required check here ran on ubuntu-latest, so each outage held
every PR. Pushes, same-repo PRs, schedules and dispatches now run on
cordon-exec, the non-root one-job runners on our host. A fork's PR and
a Dependabot PR run code nobody here wrote and stay on GitHub's
runners, chosen per job by one runs-on expression.

docker-build needs a Docker daemon, which cordon-exec does not have.
The image build and boot smoke run on GitHub's runners on every push to
main and on a PR that changes what the image is built from (the
Dockerfile, .dockerignore, the package files, tsconfig.json, src/, or
build.yml); the required check runs here and passes only when that job
passed or was not owed.

fleet-status posts fleet/verify and fleet/review and runs only the
default branch's script, so it moves for every event, as does the
dispatch-only backfill. CodeQL gets 2G and two threads on our runner.
scripts/fleet-status.test.mjs evaluates the expression in each
workflow that uses it.
@github-actions github-actions Bot added github_actions Pull requests that update GitHub Actions code size/M 50-199 hand-written lines labels Oct 6, 2026
@askalf
askalf marked this pull request as ready for review October 6, 2026 17:26

@sprayberry-redline sprayberry-redline left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: request changes. The runner selection keeps fork and Dependabot PR jobs on hosted runners, and the Docker gate checks the image job when its inputs change. The new workflow comments expose an internal deployment path that should be removed before merging.

1. Blocking: .github/workflows/ci.yml:18

# non-root one-job runners on our host (platform deploy/gha-runners), so GitHub's hosted

The comment publishes the internal runner deployment location, platform deploy/gha-runners. The same location is also added to codeql.yml, fleet-status-self-test.yml and labels.yml; none of these workflows needs that location to explain runner selection.

Suggested fix:

Remove the internal deployment location from all four comments. Keep the explanation of the runner label and fork isolation.

rule:secret-exposure

@sprayberry-redline sprayberry-redline left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: request changes. The runner selection keeps ordinary fork and Dependabot PR jobs on hosted runners, and the Docker input list matches the Dockerfile. The new path filter can skip the image check for source filenames that Git quotes.

1. Blocking: .github/workflows/build.yml:47

      files=$(git diff --name-only "$BASE_SHA" HEAD)

With Git's default core.quotePath setting, a PR changing only src/café.ts produces a quoted pathname beginning with a double quote, not src/. The subsequent grep does not match it, sets changed=false, and the required docker-build job succeeds without building the changed image. Filenames containing tabs or newlines have the same problem.

Suggested fix:

Read NUL-delimited paths from git diff --name-only -z and match each complete path without Git's display quoting. Add a regression case for a non-ASCII source filename alongside ordinary source and docs-only changes.

rule:none

@github-actions github-actions Bot added tests Test suite and CI size/L 200-799 hand-written lines and removed size/M 50-199 hand-written lines labels Oct 6, 2026

@sprayberry-redline sprayberry-redline left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: approve. The runner expressions keep fork and Dependabot PR jobs on hosted runners while moving trusted jobs to cordon-exec. The Docker input filter matches the Dockerfile's inputs, covers unusual filenames and moves in its tests, and keeps the required check failing when an owed image build fails.

@askalf
askalf merged commit 20534d9 into main Oct 6, 2026
13 checks passed
@askalf
askalf deleted the ci/own-code-on-our-runners branch October 6, 2026 18:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

github_actions Pull requests that update GitHub Actions code size/L 200-799 hand-written lines tests Test suite and CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants