Skip to content

GitHub Actions config hardening across the five GPU-CI lecture repos #347

Description

@mmcky

Audit of GitHub Actions settings across the five repositories that run GPU CI on RunsOn, done 2026-07-30 while planning compute capability. Four config items came out of it — all hardening, none urgent.

Item 1 as originally written was wrong and has been corrected in place — it recommended reverting the on-demand decision from #330. See the correction comment for detail.

Repos in scope: lecture-jax, lecture-python.myst, lecture-python-programming, lecture-stats, iuj_feb_2026.

1. Spot pricing is switched off where most of the GPU volume is — CORRECTED, do not action

This item was wrong. See the correction comment below. spot=false is a deliberate org-wide reliability decision from #330 (spot reclamation was killing GPU builds mid-run), not an oversight. The correct action is the opposite: finish the #330 rollout by adding spot=false to the 7 GPU workflows that still lack it — all four in lecture-stats, both in iuj_feb_2026, and publish.yml in lecture-python-programming. The measurements below are accurate; the recommendation drawn from them was not.

Original text, kept for the record

spot=false is set in 10 of 17 GPU workflow files, across lecture-jax (4 of 4), lecture-python.myst (4 of 4) and lecture-python-programming (2 of 3 — publish.yml doesn't set it). lecture-stats and iuj_feb_2026 never set spot, and RunsOn defaults to spot, so those already get it.

Measured over 2026-01-31 → 2026-07-30, 98% of GPU CI wall-clock runs on spot=false — 245.9 of 251.3 hours. Flipping those 10 files to spot=true cuts that portion of the bill by roughly 58–61% at zero cost and with no downside I can see: RunsOn tries spot first and falls back to on-demand automatically when spot capacity is unavailable, at a 2–3 second launch penalty.

The single largest consumer is lecture-python.myst/ci.yml at 123.9 hours — about half of all GPU CI.

2. Fork-PR workflow approval is on GitHub's default rather than the strict setting

All five repos are set to first_time_contributors. The stricter option is all_external_contributors, which requires maintainer approval before any outside contributor's workflow runs rather than only a first-time one.

This is hardening rather than a live problem — it would start to matter if we ever attached a self-hosted runner to these repos, which we haven't. It's a five-click change and worth doing ahead of that rather than as part of it.

3. Actions can approve pull requests on four of five repos

can_approve_pull_request_reviews is true on all but iuj_feb_2026. We have no workflow that uses this, and we're planning triage and maintenance agents whose design says explicitly that a bot never approves or merges — so leaving the capability enabled makes that a convention rather than something actually enforced. Suggest turning it off so the guardrail is real.

4. Default workflow token permissions are write on four of five

default_workflow_permissions is write on all but iuj_feb_2026, which uses read. Broader than anything currently needs, and iuj_feb_2026 demonstrates read is workable. Per-workflow permissions: blocks can grant more where a workflow genuinely needs it.

Suggested order

Item Effort Why now
1 Finish the #330 rollout — add spot=false to the 7 workflows still missing it One PR Closes a known reliability gap. Replaces the original item 1, which was wrong
2 Set approval policy to all_external_contributors Five settings Free, and cheaper before a runner exists than after
3 Disable Actions approving PRs Four settings Makes a planned agent guardrail enforceable
4 Default token permissions to read Four settings Needs a check that nothing breaks

Not established

The organisation-level Actions policy hasn't been read — that needs admin:org, which I don't have. It could constrain or override any of the repo-level settings above, so worth checking before acting on 2–4.

Also worth a sanity check by someone who knows the repos: whether runs-on accepts expressions and which contexts are available at job level isn't documented in GitHub's workflow-syntax reference, which matters if we later want conditional runner selection.

Context and working are in the private project-compute planning repo (research/2026-07-30-gpu-ci-settings-audit.md).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions