Merge remote-tracking branch 'origin/ni/1-libnode-loader' into ni/13-libnode-packs

This commit is contained in:
Malte Ubl
2026-10-26 11:15:43 -07:00
1828 changed files with 119099 additions and 19983 deletions
+40 -2
View File
@@ -126,6 +126,8 @@ jobs:
SCRIPTC_TEST_WORKERS: "1"
- name: Verify mixed-source generated AST getters
run: pnpm generate:ts7-ast --check
- name: Verify the generated IR field readers
run: pnpm generate:ir-fields --check
native_macos:
needs: [validation_scope, lanes]
@@ -354,6 +356,37 @@ jobs:
- run: tar -xzf "$RUNNER_TEMP/native-linux-x64-gnu.tar.gz"
- run: pnpm test tests/harness/effect.test.ts tests/harness/effect4.test.ts
# The sanitized three.js nodes build alone: beside the san corpus's other
# workers it took 860 to more than 1200 seconds of its shard
# (SCRIPTC_THREE_SANITIZED_NODES_JOB in scripts/ci-test-plan.mjs). It keeps
# the corpus's LeakSanitizer settings.
three_nodes_san:
needs: [validation_scope, lanes, native_linux]
if: ${{ needs.validation_scope.outputs.full == 'true' && needs.lanes.outputs.linux == 'true' }}
name: test (Linux, san, three.js nodes)
runs-on: ubuntu-24.04
timeout-minutes: 40
env:
SCRIPTC_SAN: "1"
ASAN_OPTIONS: detect_leaks=1
LSAN_OPTIONS: suppressions=${{ github.workspace }}/tests/harness/lsan.supp:print_suppressions=0
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 11.1.3
- uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: pnpm
- run: pnpm install --frozen-lockfile
- uses: actions/download-artifact@v4
with:
name: native-linux-x64-gnu
path: ${{ runner.temp }}
- run: tar -xzf "$RUNNER_TEMP/native-linux-x64-gnu.tar.gz"
- run: pnpm test tests/harness/three.test.ts -t "'nodes' runs statically through LLVM on 'native'"
# Build each instrumented seed once. Downstream contracts retain the same
# compiler and source artifacts without repeating seed construction.
bootstrap_seed:
@@ -547,6 +580,8 @@ jobs:
if: ${{ needs.validation_scope.outputs.full == 'true' && needs.lanes.outputs.linux == 'true' }}
name: test (tsgo and tsc-ts give the same IR)
runs-on: ubuntu-24.04
# The two corpus compiles run back to back and take close to 30 minutes on a
# slow hosted runner, so a 30-minute limit cancels otherwise healthy runs.
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
@@ -641,8 +676,9 @@ jobs:
# Shard 1 additionally runs package/install and link-parity contracts
# before its LLVM differential slice. The slice itself can take ~10
# minutes on a cold hosted runner, so 20 minutes cancels an otherwise
# healthy job before the differential completes.
timeout-minutes: 35
# healthy job before the differential completes. Slow runners need more
# headroom than that, so the limit is 50 minutes.
timeout-minutes: 50
strategy:
fail-fast: false
matrix:
@@ -955,6 +991,7 @@ jobs:
tests_macos,
native_linux,
effects,
three_nodes_san,
bootstrap_seed,
bootstrap,
linux_host_clang,
@@ -987,6 +1024,7 @@ jobs:
lane tests_macos "${{ needs.tests_macos.result }}" "${{ needs.lanes.outputs.macos }}"
lane native_linux "${{ needs.native_linux.result }}" "${{ needs.lanes.outputs.linux }}"
lane effects "${{ needs.effects.result }}" "${{ needs.lanes.outputs.effects }}"
lane three_nodes_san "${{ needs.three_nodes_san.result }}" "${{ needs.lanes.outputs.linux }}"
lane bootstrap_seed "${{ needs.bootstrap_seed.result }}" "${{ needs.lanes.outputs.bootstrap }}"
lane bootstrap "${{ needs.bootstrap.result }}" "${{ needs.lanes.outputs.bootstrap }}"
lane linux_host_clang "${{ needs.linux_host_clang.result }}" "${{ needs.lanes.outputs.linux }}"
+93
View File
@@ -0,0 +1,93 @@
name: LLVM distribution
# Builds the LLVM that the Linux release helpers link
# (native/llvm-codegen/llvm-dist.mjs): LLVM from its release sources with
# ThinLTO and native/llvm-codegen/llvm.profdata.gz, for each Linux
# architecture. Each job builds a helper against it and one against LLVM's
# release archive, requires the two to give identical objects on this
# checkout's helper inputs (scripts/check-llvm-dist.mjs), prints both
# helpers' times, and attaches the archive to the LLVM_DIST_TAG release.
# The arm64 build uses the profile collected on x64; its job log reports how
# many functions the profile no longer matches. Run it after a profile refresh
# or an LLVM version change, with a new LLVM_DIST_TAG.
on:
workflow_dispatch:
permissions:
contents: read
concurrency: ${{ github.workflow }}
jobs:
build:
name: Build LLVM (${{ matrix.arch }})
if: github.repository == 'vercel-labs/scriptc'
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: ubuntu-24.04
llvm_asset: LLVM-22.1.8-Linux-X64
- arch: arm64
runner: ubuntu-24.04-arm
llvm_asset: LLVM-22.1.8-Linux-ARM64
runs-on: ${{ matrix.runner }}
# About an hour for LLVM on 4 cores, and 5 minutes for each helper link.
timeout-minutes: 240
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 11.1.3
- uses: actions/setup-node@v4
with:
node-version: "24"
cache: pnpm
- name: Install LLVM's release archive and sources
run: |
sudo apt-get update
sudo apt-get install --yes ninja-build zlib1g-dev libzstd-dev
base=https://github.com/llvm/llvm-project/releases/download/llvmorg-22.1.8
curl -fL --retry 3 -o "$RUNNER_TEMP/llvm.tar.xz" "$base/${{ matrix.llvm_asset }}.tar.xz"
tar -xJf "$RUNNER_TEMP/llvm.tar.xz" -C "$RUNNER_TEMP"
mv "$RUNNER_TEMP/${{ matrix.llvm_asset }}" "$RUNNER_TEMP/llvm-22.1.8"
curl -fL --retry 3 -o "$RUNNER_TEMP/llvm-src.tar.xz" "$base/llvm-project-22.1.8.src.tar.xz"
tar -xJf "$RUNNER_TEMP/llvm-src.tar.xz" -C "$RUNNER_TEMP"
rm "$RUNNER_TEMP/llvm.tar.xz" "$RUNNER_TEMP/llvm-src.tar.xz"
echo "$RUNNER_TEMP/llvm-22.1.8/bin" >> "$GITHUB_PATH"
- run: pnpm install --frozen-lockfile
- run: pnpm --filter @scriptc/compiler --filter scriptc build
- name: Build the distribution
run: >-
node scripts/build-llvm-dist.mjs --source "$RUNNER_TEMP/llvm-project-22.1.8.src"
--prefix "$RUNNER_TEMP/dist/scriptc-llvm-22.1.8-linux-${{ matrix.arch }}"
--archive "$RUNNER_TEMP/scriptc-llvm-22.1.8-linux-${{ matrix.arch }}.tar.xz"
--work "$RUNNER_TEMP/llvm-dist-work"
- name: Build a helper against each LLVM
env:
HELPER: llvm-linux-${{ matrix.arch }}-gnu
run: |
LLVM_DIR="$RUNNER_TEMP/llvm-22.1.8/lib/cmake/llvm" pnpm --filter "@scriptc/$HELPER" build:native
cp "packages/$HELPER/bin/scriptc-llvm-codegen" "$RUNNER_TEMP/helper-release-archive"
LLVM_DIR="$RUNNER_TEMP/dist/scriptc-llvm-22.1.8-linux-${{ matrix.arch }}/lib/cmake/llvm" \
SCRIPTC_LLVM_THINLTO=1 pnpm --filter "@scriptc/$HELPER" build:native
cp "packages/$HELPER/bin/scriptc-llvm-codegen" "$RUNNER_TEMP/helper-profiled"
- name: Compare the helpers
run: >-
node scripts/check-llvm-dist.mjs --baseline "$RUNNER_TEMP/helper-release-archive"
--candidate "$RUNNER_TEMP/helper-profiled" --rounds 3 --work "$RUNNER_TEMP/llvm-check"
- name: Attach the archive to the release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ARCHIVE: ${{ runner.temp }}/scriptc-llvm-22.1.8-linux-${{ matrix.arch }}.tar.xz
run: |
tag=$(node --input-type=module -e "import { LLVM_DIST_TAG } from './native/llvm-codegen/llvm-dist.mjs'; console.log(LLVM_DIST_TAG)")
# Both architectures' jobs create the release if it is missing.
gh release view "$tag" > /dev/null 2>&1 ||
gh release create "$tag" --target "$GITHUB_SHA" --title "$tag" --latest=false \
--notes "LLVM 22.1.8 built with ThinLTO and the helper profile, for the Linux LLVM helpers (scripts/build-llvm-dist.mjs)." ||
gh release view "$tag" > /dev/null
gh release upload "$tag" "$ARCHIVE" "$ARCHIVE.sha256" --clobber
+41
View File
@@ -0,0 +1,41 @@
name: Prune caches
# Pull request caches are scoped to that pull request, so once it is closed no
# run can use them again. Deleting them keeps the repository under its cache
# size limit, so caches that main and open pull requests use are not evicted.
on:
pull_request:
types: [closed]
schedule:
- cron: "17 6 * * *"
workflow_dispatch:
permissions:
actions: write
pull-requests: read
jobs:
prune:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Delete caches of closed pull requests
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail
# Read both lists in full before deleting anything: deleting while the cache
# listing pages shifts later pages, and a failed request must stop the job
# instead of leaving open pull requests out of the list.
open=$(gh api --paginate "repos/$REPO/pulls?state=open&per_page=100" --jq '.[].number')
caches=$(gh api --paginate "repos/$REPO/actions/caches?per_page=100" \
--jq '.actions_caches[] | select(.ref | startswith("refs/pull/")) | "\(.id) \(.ref)"')
while read -r id ref; do
[ -n "$id" ] || continue
number=$(echo "$ref" | cut -d/ -f3)
if ! grep -qx "$number" <<<"$open"; then
gh api --method DELETE "repos/$REPO/actions/caches/$id" >/dev/null
echo "deleted cache $id ($ref)"
fi
done <<<"$caches"
+211 -12
View File
@@ -83,6 +83,7 @@ jobs:
spawnSync('git', ['diff', '--quiet', run.head_sha, 'HEAD', '--', '.',
':(exclude).github/workflows/release.yml', ':(exclude)scripts/verify-native-cli.mjs',
':(exclude)scripts/package-native-cli.mjs', ':(exclude)tests/harness/native-cli-packaging.test.ts',
':(exclude)scripts/wait-npm-available.mjs', ':(exclude)tests/harness/npm-available.test.ts',
]).status !== 0) continue;
const artifacts = api(`repos/${repo}/actions/runs/${run.id}/artifacts?per_page=100`).artifacts
.filter((artifact) => !artifact.expired && artifact.size_in_bytes > 0);
@@ -100,10 +101,65 @@ jobs:
if (receiptRun) appendFileSync(process.env.GITHUB_OUTPUT, `receipt_run=${receiptRun}\n`);
NODE
build-native-packages:
name: Build native package (${{ matrix.platform }})
# Collects the native compiler's profile and function layout on this commit
# (scripts/refresh-cli-profile.mjs, scripts/refresh-cli-layout.mjs), so every
# platform's CLI build optimizes and lays out the code it compiles. The
# committed ones fall behind main within a day or two. If this job fails,
# the CLI builds use the committed profile and layout.
cli-profile:
name: Collect the native compiler profile
needs: check-release
if: needs.check-release.outputs.should_release == 'true' && needs.check-release.outputs.reuse_artifacts != 'true'
runs-on: ubuntu-24.04
timeout-minutes: 45
continue-on-error: true
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 11.1.3
- uses: actions/setup-node@v4
with:
node-version: "24"
cache: pnpm
- uses: ./.github/actions/llvm-linux
- run: pnpm install --frozen-lockfile
- uses: ./.github/actions/zig
- uses: ./.github/actions/native-packages
with:
target: linux-x64-gnu
- run: pnpm --filter @scriptc/compiler --filter scriptc build
- name: Check out tsc-ts
run: |
git clone --quiet --depth 1 https://github.com/vercel-labs/tsc-ts "$RUNNER_TEMP/tsc-ts"
echo "tsc-ts $(git -C "$RUNNER_TEMP/tsc-ts" rev-parse HEAD)"
npm ci --prefix "$RUNNER_TEMP/tsc-ts"
- name: Collect the profile
run: >-
node scripts/refresh-cli-profile.mjs --tsc-ts "$RUNNER_TEMP/tsc-ts" --jobs 4
--output "$RUNNER_TEMP/cli-profile/cli.profdata.gz" --work "$RUNNER_TEMP/cli-profile-work"
- name: Collect the function layout
run: >-
node scripts/refresh-cli-layout.mjs --jobs 4 --instrumented "$RUNNER_TEMP/cli-profile-work/cli"
--output "$RUNNER_TEMP/cli-profile/cli.layout.gz"
- uses: actions/upload-artifact@v4
with:
name: cli-profile
path: |
${{ runner.temp }}/cli-profile/cli.profdata.gz
${{ runner.temp }}/cli-profile/cli.layout.gz
retention-days: 7
if-no-files-found: error
build-native-packages:
name: Build native package (${{ matrix.platform }})
needs: [check-release, cli-profile]
# Runs when the profile job fails; the CLI builds then use the committed profile.
if: >-
!cancelled() && needs.check-release.outputs.should_release == 'true' &&
needs.check-release.outputs.reuse_artifacts != 'true'
strategy:
fail-fast: false
matrix:
@@ -124,6 +180,7 @@ jobs:
runtime: runtime-linux-x64-gnu
cli: cli-linux-x64-gnu
llvm_asset: LLVM-22.1.8-Linux-X64
llvm_dist: x64
use_zig: true
- platform: linux-arm64
runner: ubuntu-24.04-arm
@@ -131,6 +188,7 @@ jobs:
runtime: runtime-linux-arm64-gnu
cli: cli-linux-arm64-gnu
llvm_asset: LLVM-22.1.8-Linux-ARM64
llvm_dist: arm64
use_zig: true
- platform: windows-x64
runner: windows-2022
@@ -146,6 +204,7 @@ jobs:
seed_helper: llvm-linux-x64-gnu
cli_target: x86_64-linux-musl
llvm_asset: LLVM-22.1.8-Linux-X64
llvm_dist: x64
use_zig: true
- platform: linux-arm64-musl
runner: ubuntu-24.04-arm
@@ -155,12 +214,14 @@ jobs:
seed_helper: llvm-linux-arm64-gnu
cli_target: aarch64-linux-musl
llvm_asset: LLVM-22.1.8-Linux-ARM64
llvm_dist: arm64
use_zig: true
- platform: wasm32-wasi
runner: ubuntu-24.04
helper: llvm-linux-x64-gnu
runtime: runtime-wasm32-wasi
llvm_asset: LLVM-22.1.8-Linux-X64
llvm_dist: x64
use_zig: true
runs-on: ${{ matrix.runner }}
# The Intel macOS build took 24 minutes for 0.3.2 and passed 30 for 0.3.3.
@@ -191,6 +252,28 @@ jobs:
mv "$RUNNER_TEMP/${{ matrix.llvm_asset }}" "$RUNNER_TEMP/llvm-22.1.8"
echo "LLVM_DIR=$RUNNER_TEMP/llvm-22.1.8/lib/cmake/llvm" >> "$GITHUB_ENV"
echo "$RUNNER_TEMP/llvm-22.1.8/bin" >> "$GITHUB_PATH"
# The Linux helpers link LLVM built with ThinLTO and a profile of the
# helper's code generation (native/llvm-codegen/llvm-dist.mjs), from a
# release of this repository. Without that archive they link LLVM's
# release archive, which gives the same objects more slowly. The
# wasm32-wasi job also uploads the x64 GNU helper, so it selects the same.
- name: Select the profiled LLVM distribution (Linux)
if: matrix.llvm_dist != ''
env:
ARCH: ${{ matrix.llvm_dist }}
run: |
tag=$(node --input-type=module -e "import { LLVM_DIST_TAG } from './native/llvm-codegen/llvm-dist.mjs'; console.log(LLVM_DIST_TAG)")
asset=$(node --input-type=module -e "import { llvmDistAsset } from './native/llvm-codegen/llvm-dist.mjs'; console.log(llvmDistAsset(process.env.ARCH))")
base="https://github.com/$GITHUB_REPOSITORY/releases/download/$tag"
if curl -fsSL --retry 3 -o "$RUNNER_TEMP/$asset" "$base/$asset" &&
curl -fsSL --retry 3 -o "$RUNNER_TEMP/$asset.sha256" "$base/$asset.sha256" &&
(cd "$RUNNER_TEMP" && sha256sum --check "$asset.sha256"); then
tar -xJf "$RUNNER_TEMP/$asset" -C "$RUNNER_TEMP"
echo "SCRIPTC_HELPER_LLVM_DIR=$RUNNER_TEMP/${asset%.tar.xz}/lib/cmake/llvm" >> "$GITHUB_ENV"
echo "The helper links $asset from release $tag"
else
echo "::warning::$asset is not available from release $tag; the helper links LLVM's release archive"
fi
- uses: vercel-labs/setup-zig@v1
if: matrix.use_zig == true
with:
@@ -229,7 +312,15 @@ jobs:
- name: Build native packages (POSIX)
if: matrix.platform != 'windows-x64'
run: |
pnpm --filter @scriptc/${{ matrix.helper }} build:native
if [ -n "${SCRIPTC_HELPER_LLVM_DIR:-}" ]; then
LLVM_DIR="$SCRIPTC_HELPER_LLVM_DIR" SCRIPTC_LLVM_THINLTO=1 pnpm --filter @scriptc/${{ matrix.helper }} build:native || {
echo "::warning::the helper did not build against the profiled LLVM; it links LLVM's release archive"
rm -rf node_modules/.cache/scriptc-${{ matrix.helper }}
pnpm --filter @scriptc/${{ matrix.helper }} build:native
}
else
pnpm --filter @scriptc/${{ matrix.helper }} build:native
fi
if [ "${{ matrix.use_zig }}" = true ]; then
CC=zig AR=zig pnpm --filter @scriptc/${{ matrix.runtime }} build:native
else
@@ -243,6 +334,33 @@ jobs:
- name: Build host helper for cross-libc bootstrap
if: matrix.seed_helper != ''
run: pnpm --filter @scriptc/${{ matrix.seed_helper }} build:native
- name: Download the profile collected on this commit
id: cli-profile
if: matrix.cli != ''
continue-on-error: true
uses: actions/download-artifact@v4
with:
name: cli-profile
path: ${{ runner.temp }}/cli-profile
# Without the artifact, SCRIPTC_NATIVE_PROFILE_USE and SCRIPTC_NATIVE_LAYOUT
# stay unset and build-native-cli.mts uses the committed profile and layout.
- name: Select the native compiler profile
if: matrix.cli != ''
shell: bash
env:
COLLECTED: ${{ steps.cli-profile.outcome == 'success' && format('{0}/cli-profile/cli.profdata.gz', runner.temp) || '' }}
run: |
if [ -n "$COLLECTED" ]; then
echo "SCRIPTC_NATIVE_PROFILE_USE=$COLLECTED" >> "$GITHUB_ENV"
echo "The native CLI builds with the profile collected on $GITHUB_SHA"
layout="$(dirname "$COLLECTED")/cli.layout.gz"
if [ -f "$layout" ]; then
echo "SCRIPTC_NATIVE_LAYOUT=$layout" >> "$GITHUB_ENV"
echo "The native CLI builds with the function layout collected on $GITHUB_SHA"
fi
else
echo "::warning::No profile was collected on this commit; the native CLI builds with the committed profile"
fi
- name: Build native CLI distribution
if: matrix.cli != ''
env:
@@ -317,12 +435,15 @@ jobs:
(needs.check-release.outputs.reuse_artifacts == 'true' ||
(needs.build-native-packages.result == 'success' && needs.build-mobile-runtime-packs.result == 'success'))
runs-on: ubuntu-latest
timeout-minutes: 15
# Two waits for npm availability of at most 25 minutes each.
timeout-minutes: 70
environment: Release
permissions:
contents: read
actions: read
id-token: write
outputs:
uploads: ${{ steps.publish.outputs.uploads }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -342,7 +463,7 @@ jobs:
VERSION: ${{ needs.check-release.outputs.version }}
RECEIPT_RUN: ${{ needs.check-release.outputs.receipt_run }}
run: |
touch "$RUNNER_TEMP/npm-accepted.txt"
touch "$RUNNER_TEMP/npm-accepted.txt" "$RUNNER_TEMP/npm-accepted-times.txt"
# Include this run so re-running only failed jobs restores its receipts.
for run in "$GITHUB_RUN_ID" "$RECEIPT_RUN"; do
if [ -z "$run" ]; then continue; fi
@@ -351,6 +472,7 @@ jobs:
if [ "$count" -eq 0 ]; then continue; fi
gh run download "$run" --repo "$GITHUB_REPOSITORY" --pattern "npm-accepted-$VERSION-*" --dir "$RUNNER_TEMP/npm-receipts/$run"
find "$RUNNER_TEMP/npm-receipts/$run" -name npm-accepted.txt -exec cat {} + >> "$RUNNER_TEMP/npm-accepted.txt"
find "$RUNNER_TEMP/npm-receipts/$run" -name npm-accepted-times.txt -exec cat {} + >> "$RUNNER_TEMP/npm-accepted-times.txt"
done
- name: Setup pnpm
@@ -400,6 +522,7 @@ jobs:
done
- name: Publish to npm
id: publish
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -419,10 +542,14 @@ jobs:
# Upload acceptance and public availability are separate states.
# Save acceptance immediately so retries never depend on registry lag.
# npm-release.txt lists every package of the release, and
# npm-accepted-times.txt the time npm accepted each upload, for the
# npm-available job.
publish_dir() {
dir="$1"
packed="${2:-}"
name=$(node -p "require('./$dir/package.json').name")
echo "$name@$VERSION" >> "$RUNNER_TEMP/npm-release.txt"
if grep -Fxq "$name@$VERSION" "$RUNNER_TEMP/npm-accepted.txt"; then
echo "$name@$VERSION upload already accepted, skipping"
return 0
@@ -439,6 +566,7 @@ jobs:
publish_log="$RUNNER_TEMP/npm-publish.log"
if npm publish "$packed" $PROVENANCE --access public 2>&1 | tee "$publish_log"; then
echo "$name@$VERSION" >> "$RUNNER_TEMP/npm-accepted.txt"
echo "$name@$VERSION $(date +%s)" >> "$RUNNER_TEMP/npm-accepted-times.txt"
return 0
else
publish_status=${PIPESTATUS[0]}
@@ -461,8 +589,8 @@ jobs:
}
# pnpm pack resolves workspace dependencies; npm handles OIDC.
# Publish dependencies first. Registry propagation after an accepted
# upload must not block the remaining packages or the GitHub release.
# Publish dependencies first. The npm-available job waits for the
# packages that nothing in this release depends on.
publish_dir packages/runtime
publish_dir packages/runtime-darwin-arm64
publish_dir packages/llvm-darwin-arm64
@@ -482,32 +610,88 @@ jobs:
publish_dir packages/runtime-wasm32-wasi
publish_dir packages/runtime-win32-x64-msvc
publish_dir packages/llvm-win32-x64-msvc
# A native CLI package depends on its platform's LLVM helper and
# runtime pack packages, and scriptc on the native CLI packages.
# Each group publishes only once the packages it depends on
# resolve, so an install never finds a package whose dependencies
# npm is still processing. A rerun skips accepted uploads and waits
# again.
wait_available() {
awk 'FILENAME == ARGV[1] { accepted[$1] = $2; next } { print $1, accepted[$1] }' \
"$RUNNER_TEMP/npm-accepted-times.txt" "$RUNNER_TEMP/npm-release.txt" > "$RUNNER_TEMP/npm-wait.txt"
node scripts/wait-npm-available.mjs "$RUNNER_TEMP/npm-wait.txt" --interval 30 --timeout 1500
}
wait_available
for pkg in packages/cli-*; do publish_dir "$pkg"; done
publish_dir packages/compiler
publish_dir packages/experimental
publish_dir packages/node
publish_dir packages/threads
publish_dir packages/types
wait_available
publish_dir packages/cli
echo "All package uploads accepted; npm registry propagation may continue after this job." >> "$GITHUB_STEP_SUMMARY"
# Each package of the release with the time its upload was accepted,
# when a run recorded it.
{
echo "uploads<<NPM_UPLOADS"
awk 'FILENAME == ARGV[1] { accepted[$1] = $2; next } { print $1, accepted[$1] }' \
"$RUNNER_TEMP/npm-accepted-times.txt" "$RUNNER_TEMP/npm-release.txt"
echo "NPM_UPLOADS"
} >> "$GITHUB_OUTPUT"
- name: Save accepted upload receipts
if: always()
uses: actions/upload-artifact@v4
with:
name: npm-accepted-${{ needs.check-release.outputs.version }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/npm-accepted.txt
path: |
${{ runner.temp }}/npm-accepted.txt
${{ runner.temp }}/npm-accepted-times.txt
if-no-files-found: ignore
retention-days: 90
# Publish standalone native distributions and the surface manifest after
# npm publishing succeeds. The release body comes from the marked changelog.
github-release:
name: Create GitHub Release
# Waits until every package of the release resolves on the npm registry,
# and reports each package's time from upload to available. Fails with the
# packages that are still missing after 2 hours. It only reads from the
# registry; the next release run retries it, and publishing skips uploads
# npm already accepted.
npm-available:
name: Wait for npm availability
needs: [check-release, publish]
if: >-
!cancelled() && needs.check-release.outputs.should_release == 'true' && needs.publish.result == 'success'
runs-on: ubuntu-latest
timeout-minutes: 135
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
- name: Wait for every package to resolve
env:
UPLOADS: ${{ needs.publish.outputs.uploads }}
run: |
printf '%s\n' "$UPLOADS" > "$RUNNER_TEMP/npm-uploads.txt"
node scripts/wait-npm-available.mjs "$RUNNER_TEMP/npm-uploads.txt"
# Publish standalone native distributions and the surface manifest after
# every npm package resolves. The release body comes from the marked
# changelog.
github-release:
name: Create GitHub Release
needs: [check-release, publish, npm-available]
if: >-
!cancelled() && needs.check-release.outputs.should_release == 'true' && needs.npm-available.result == 'success'
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
@@ -559,6 +743,21 @@ jobs:
- name: Package standalone compilers
run: node scripts/package-native-cli.mjs packages /tmp/scriptc-release-assets
# The profile the native CLIs were built with. Runs that reuse native
# builds from before the cli-profile job, or whose profile job failed,
# have none; their CLIs used the committed profile.
- name: Download the native compiler profile
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RUN: ${{ needs.check-release.outputs.artifact_run }}
VERSION: ${{ needs.check-release.outputs.version }}
run: |
if gh run download "$RUN" --repo "$GITHUB_REPOSITORY" --name cli-profile --dir "$RUNNER_TEMP/cli-profile"; then
mv "$RUNNER_TEMP/cli-profile/cli.profdata.gz" "/tmp/scriptc-release-assets/scriptc-$VERSION-cli.profdata.gz"
else
echo "Run $RUN has no cli-profile artifact"
fi
- name: Create GitHub Release
run: |
VERSION="${{ needs.check-release.outputs.version }}"