Files
qwen-code/scripts
Shaojin Wen 07835d248f fix(ci): pin and cache the standalone runtime archives (#15159)
* fix(ci): pin and cache the standalone runtime archives

The standalone runtime regression downloaded Node 24.19.0 and Bun 1.3.14
on every run, after first fetching Node's checksum list and Bun's npm
metadata, with no retry. That cost minutes per run on the shared runners
and turned an npm 502 into a red required check on an unrelated change.

Pin the published digests for the four supported platforms so archives
are verified without metadata requests, keep verified archives in a
cache directory when one is configured, and retry downloads. The
required Linux unit-test job points the cache at a host-wide directory
on persistent self-hosted runners.

* fix(ci): keep a verified runtime download when the cache is unusable

If the cache directory, or a directory on its path, cannot be searched,
writing the archive fails as intended, but removing the temporary file
then throws too (EACCES, or ENOTDIR when the path runs through a file):
`force` only ignores a missing file. The verified archive already in
memory was discarded, the regression never started, and the script
tests chained after it were skipped.

Make that cleanup best-effort like the rest of the cache write. The
download-and-cache logic moves unchanged into scripts/lib so it can be
tested; the tests cover cache reuse, replacing a copy that fails
verification, a cache path through a file, and an unsearchable cache
directory (skipped as root, where permissions do not apply).

* fix(scripts): retry unverified runtime downloads and sweep the host cache

Verify each download attempt, so a truncated or stale 200 body is retried
like a failed request, and name both digests when the pin never matches.
Retry logs now include the undici error cause, and cache hits and writes
each log a line. The CI step reports the cache path and size.

Entries no run has used for a week (previous pins, partial files left by
a killed run) are removed after each successful run; a run refreshes the
mtime of the archive it uses, so revisions still in flight keep theirs.

Tests cover retries, verification per attempt, the uncached path, the
sweep, the CI wiring, and gate the permission case on the shared
permission-bits probe so it also runs on root lanes with DAC caps dropped.

* fix(ci): sweep the runtime cache only after a run fetched both archives

The Node fetch swept every other entry unused for a week, so after a
quiet week it removed the Bun archive the same run was about to reuse
and Bun was downloaded again. Fetches now only mark their archive as
used; ci() sweeps once after both fetches, sparing the archives it used.
The sweep skips non-files and keeps going past an entry it cannot
remove, and a cached copy that fails verification is logged.

Also:
- export the same host-wide cache to release.yml's quality_scripts,
  which runs the same regression on a persistent host
- move the pinned versions and digests to
  scripts/lib/standalone-runtime-pins.js and check their shape
- pin the wiring itself: the export step's gate, its GITHUB_ENV write
  and its position before the consuming step, in both workflows
- cover the write-then-rename into the cache
2026-10-24 01:26:23 +08:00
..
2025-08-27 15:23:21 +08:00