Skip to content

ci: automate the skiplang bootstrap bump (manual workflow)#1479

Merged
mbouaziz merged 3 commits into
mainfrom
automate-bootstrap-bump
Jul 23, 2026
Merged

ci: automate the skiplang bootstrap bump (manual workflow)#1479
mbouaziz merged 3 commits into
mainfrom
automate-bootstrap-bump

Conversation

@mbouaziz

Copy link
Copy Markdown
Contributor

Automates the bootstrap-compiler bump — today a careful, ~40-minute manual sequence across two repos — behind a single manual trigger, so the toil goes away and the verification is guaranteed to run.

What it does

workflow_dispatch → on ubuntu-24.04:

  1. bin/bump_bootstrap.sh: build stage1 with the current bootstrap, make promote, then verify the promoted compiler on a clean rebuild — the self-hosting fixpoint (stage2 and stage3 skc.ll identical) and the full compiler test suite. Any failure exits non-zero and nothing is published.
  2. Push the new IR to SkipLabs/skiplang-bootstrap.
  3. Open a PR here bumping the skiplang/compiler/bootstrap submodule pointer.

Merging that PR — the step that changes what everyone builds from — stays a human decision, and CI re-runs the fixpoint + tests against the new pointer before it can land. A dry_run input builds and verifies without pushing or opening a PR.

Two issues an adversarial review caught, and how they're handled

  • Non-fast-forward wedge. Committing the new IR on top of the pinned submodule SHA and pushing to skiplang-bootstrap main is rejected whenever main has advanced (e.g. an earlier bump whose PR hasn't merged), wedging every future run after a 40-min rebuild. Fixed by reparenting the IR onto the current remote main tip (fetch + reset --soft + commit), so the push is always a fast-forward. Reproduced the wedge and confirmed the fix locally; main stays linear with every IR reachable.
  • Token exfiltration. workflow_dispatch runs the workflow and its scripts from the selected ref with full secret access, so a write-access user could dispatch a crafted branch to steal the cross-repo token. The job runs in a bootstrap-publish environment whose deployment-branch policy must allow only main, which blocks the secret for any other ref.

The review also flagged — and I verified as not an issue — that SKIP_CAPACITY is unneeded on the 16 GB runner (the same compiler builds on the same runners in docker-publish without it).

Maintainer setup before the first run

  1. Fine-grained PAT (org SkipLabs), repo access to both skiplang-bootstrap and skip, permissions Contents: R/W + Pull requests: R/W + Metadata.
  2. Environment bootstrap-publish on SkipLabs/skip: deployment-branch policy → selected branches → main only; store the PAT as an environment secret named BOOTSTRAP_BUMP_TOKEN (environment, not repo/org — a repo secret isn't gated by the environment). Optionally add required reviewers for a per-run approval gate.
  3. Validate with a dry_run from main (build + verify, no writes) before the first real bump.

Verified as far as is possible without running it: actionlint + shellcheck clean; the make sequence traced against the real Makefile; the check-bootstrap/uncommitted-submodule interaction, the fast-forward fix, and the git submodule status behaviour reproduced locally. The compiler build/test itself can only be exercised on the runner — hence the dry_run-from-main first.

— Mehdi (with Claude Opus 4.8, xhigh effort)

🤖 Generated with Claude Code

mbouaziz added 3 commits July 23, 2026 13:41
The mechanical core of a bootstrap bump, previously a careful manual sequence:
build stage1 with the current bootstrap, promote its IR into the bootstrap
submodule, then verify the promoted compiler in isolation by rebuilding it
clean and asserting the self-hosting fixpoint (stage2 and stage3 skc.ll
identical) plus the full test suite.

The Makefile's own fixpoint check is `-diff` (leading dash, exit code ignored),
so it never fails a build; this asserts it and exits non-zero on any failure,
leaving the promoted files in place for the caller to commit but guaranteeing a
non-converging or test-failing compiler is never published.
Wraps bin/bump_bootstrap.sh in a workflow_dispatch action that, once the rebuild
and verification pass, pushes the new IR to SkipLabs/skiplang-bootstrap and opens
a PR here bumping the submodule pointer. Manual only: whether to bump is a
judgement call, and merging the PR -- the step that changes what everyone builds
from -- stays a human decision that re-runs CI against the new pointer.

Two things an adversarial review caught and this handles:

- The IR is reparented onto the current skiplang-bootstrap main tip before
  pushing, so the push is always a fast-forward. Committing on top of the pinned
  (possibly stale) submodule SHA would be rejected non-fast-forward whenever main
  had advanced -- e.g. an earlier bump whose PR had not merged -- wedging every
  later run. IR snapshots are self-contained, so the parent commit is immaterial.

- The job runs in a `bootstrap-publish` environment. workflow_dispatch executes
  the workflow and its scripts from the selected ref with full secret access, so
  the cross-repo token is gated behind an environment whose deployment-branch
  policy allows only main; a crafted-branch dispatch cannot reach it.

A dry_run input builds and verifies without pushing or opening a PR.
The token's write access was first exercised at the push step, i.e. only after
bin/bump_bootstrap.sh had already spent ~40 minutes rebuilding and testing the
compiler. A fine-grained PAT that is unscoped, read-only, or not yet approved by
the org would waste that whole build before failing -- the same late-failure the
docker-publish check_push_access preflight was added to avoid.

Add bin/check_bootstrap_token.sh, run as the first step after checkout: GET
/repos/<repo> for both skiplang-bootstrap and skip and assert .permissions.push,
so a mis-scoped token fails in about a second with a clear remedy.
@mbouaziz
mbouaziz merged commit 2b35e62 into main Jul 23, 2026
8 checks passed
@mbouaziz
mbouaziz deleted the automate-bootstrap-bump branch July 23, 2026 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant