Skip to content

fix(ci): install a pinned wasm-opt instead of apt, and bound the wasm jobs - #2314

Merged
chaliy merged 1 commit into
mainfrom
claude/pensive-hypatia-veez7o
Aug 19, 2026
Merged

chaliy merged 1 commit into
mainfrom
claude/pensive-hypatia-veez7o

Conversation

@chaliy

@chaliy chaliy commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

What changed

The WASM web package job no longer installs binaryen from apt. Both it and
publish-wasm.yml's build-wasm go through a new
scripts/install-binaryen.sh, which fetches a version-pinned,
SHA-256-verified
binaryen release archive with explicit connect/total
timeouts and retries, and extracts bin/wasm-opt only (it is statically
linked, so 19 MB of the 102 MB archive is all that is needed).

Both jobs also gain timeout-minutes: 30.

Three things improve beyond unblocking CI:

  • wasm-opt -Oz output becomes reproducible. It previously tracked
    whichever binaryen the runner image's Ubuntu happened to carry. That binary
    optimizes the artifact published to npm.
  • The download is integrity-checked. Binaryen ships no signature and no
    checksum file for its release assets, so the pinned SHA-256 is the only thing
    between a tampered asset and a published wasm bundle.
  • CI and the release can no longer drift apart on how they install the
    tool, since there is now one script instead of two copies of a shell line.

Why

apt-get update && apt-get install -y binaryen stalled indefinitely on two
separate main runs:

Run Commit Outcome
32170059933 136f11b3 binaryen step ran 6h00m → run cancelled
32218864077 986bfc7 binaryen step 4h+ when caught, cancelled manually

That step's healthy duration is 9–14 seconds:

run 32123897979  binaryen step  14s  ✅
run 32120969690  binaryen step   9s  ✅
run 32070967641  binaryen step   9s  ✅
run 32170059933  binaryen step  6h  ❌ cancelled at the job ceiling

So main went red twice for an apt mirror stall unrelated to any diff, and
each time it held a runner for six hours. Two independent faults made that
possible — an unbounded network install, and no timeout-minutes on the job
(ci.yml has none on any job, while every other workflow in this repo sets
them). This fixes both for the affected jobs.

publish-wasm.yml carried the identical apt call, so the same stall would have
silently held a release for six hours.

Before / After

Before — unpinned, unbounded, duplicated in two workflows:

- name: Install binaryen (wasm-opt)
  run: sudo apt-get update && sudo apt-get install -y binaryen

After — one script, pinned and bounded:

$ sudo ./scripts/install-binaryen.sh
==> downloading binaryen 125
==> verifying checksum
binaryen-version_125-x86_64-linux.tar.gz: OK
==> installing wasm-opt to /usr/local/bin
wasm-opt version 125 (version_125)

Verified locally that the installed binary accepts the exact flag set
crates/bashkit-wasm/scripts/build.sh passes
(-Oz --enable-bulk-memory --enable-nontrapping-float-to-int --enable-sign-ext),
and that re-running the script is idempotent.

main is green again on the re-run of the cancelled job
(32218864077 attempt 2),
so this PR is the durable fix rather than the unblock.

Tests. test_web_ci_exercises_release_wasm_optimization asserted the literal
string apt-get install -y binaryen, so it had to change; it now asserts CI and
the release install through the same script, which is a stronger invariant than
the string it replaced. Two new tests guard what the fix must keep — no
apt-installed binaryen, a bounded download, a pinned version and checksum, and a
timeout on both wasm build jobs. Each was mutation-checked:

mutation: restore the apt install   → FAIL test_binaryen_install_is_pinned_and_bounded
mutation: drop timeout-minutes      → FAIL test_wasm_build_jobs_cannot_hang_past_the_job_ceiling
mutation: drop the checksum verify  → FAIL test_binaryen_install_is_pinned_and_bounded
restored                            → OK (53 tests)

Risk

  • Low
  • No library, build, or runtime code changes; CI configuration, one shell
    script, and its tests.
  • If the pinned binaryen URL ever 404s the job fails fast and loudly, rather
    than degrading — which is the intent. Bumping means editing version and
    checksum together in one file.
  • build.sh still treats wasm-opt as optional and skips -Oz when it is
    absent, so local builds without the tool are unaffected.
  • Not addressed here deliberately: the other nine ci.yml jobs still carry no
    timeout-minutes. Only these two demonstrated a hang, so I scoped the change
    to them rather than picking values for jobs I have no timing evidence for.
    Worth a follow-up.

Checklist

  • Tests added or updated — one updated, two added, all three mutation-checked
  • Backward compatibility considered — wasm-opt stays optional for local
    builds; no consumer-visible change

Generated by Claude Code

… jobs

`apt-get update && apt-get install -y binaryen` stalled indefinitely on two
separate `main` runs (32170059933 on 136f11b, 32218864077 on 986bfc7). The
step normally takes ~10 seconds. With no `timeout-minutes` on the job, each
stall ran to GitHub's 6-hour ceiling and took the whole CI run down as
`cancelled` — `main` went red twice for an apt mirror problem unrelated to
any diff. `publish-wasm.yml` carried the same call, where a stall would have
held a release the same way.

Both workflows now install wasm-opt through `scripts/install-binaryen.sh`:

- No apt. The binaryen release archive is fetched with explicit
  connect/total timeouts and retries, so a stalled mirror fails in minutes.
- Version pinned, so `wasm-opt -Oz` output no longer depends on whichever
  binaryen the runner image's Ubuntu carries. That artifact ships to npm.
- SHA-256 pinned. Binaryen publishes no signature or checksum file, so this
  is the only integrity check standing between a tampered release asset and
  a published wasm bundle.
- Extracts `bin/wasm-opt` only — it is statically linked, so 19 MB of the
  102 MB archive is all that is needed.

Both jobs also gain `timeout-minutes: 30`, so a future stall of any kind
fails fast and re-runnable rather than burning a runner for six hours.

`test_web_ci_exercises_release_wasm_optimization` pinned the old apt string;
it now asserts CI and the release install wasm-opt through the same script,
which also catches the two workflows drifting apart. Two new tests guard the
properties the fix has to keep: no apt-installed binaryen, bounded download,
pinned version + checksum, and a timeout on both wasm build jobs. All three
were mutation-checked to fail when the fix is reverted.
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
bashkit 0914c03 Commit Preview URL

Branch Preview URL
Aug 19 2026, 09:30 AM

@chaliy
chaliy merged commit 988657e into main Aug 19, 2026
21 checks passed
@chaliy
chaliy deleted the claude/pensive-hypatia-veez7o branch August 19, 2026 09:44
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