Repository navigation
Set up the pinned Node in every Rust CI job and drop the unused trusted-server-js deps #1204
Description
Description
Two small pieces of build hygiene around the TSJS build that every Rust build runs.
1. Most Rust CI jobs build the TSJS bundles with the runner's Node, not the pinned one
trusted-server-core depends on trusted-server-js (crates/trusted-server-core/Cargo.toml:47). The trusted-server-js build script runs npm ci when node_modules is missing, then npm run build unless TSJS_SKIP_BUILD=1, and embeds the resulting bundles (crates/trusted-server-js/build.rs:41-85). A fresh CI checkout has no node_modules, so every job that compiles core runs a Node build.
.tool-versions pins nodejs 24.12.0. Only two of the eleven jobs that compile core run actions/setup-node with that version before building. A third sets it up only after its Rust build. The other eight use whatever Node the runner image has on PATH. For the images used by recent runs, that is Node.js 22.23.2 on ubuntu-24.04 (image 20260907.300) and Node.js 24.20.0 on macos-26-arm64 (image 20260907.0351), per the images' software lists. Nothing in the repository flags the mismatch: crates/trusted-server-js/lib/package.json has no engines field, and there is no .nvmrc or .npmrc.
As a result, the bundles embedded in most of the Rust artifacts that CI builds, tests and lints are produced by a different Node major than the Vitest and format jobs use on Linux. The Node version can also change with a runner image update, with no change in the repository. crates/trusted-server-adapter-cloudflare/build.sh:2-6 already works around a related local problem (sourcing nvm because the build script picked up the wrong system Node), which shows the build script's Node matters.
2. The Cloudflare and Spin adapters declare a trusted-server-js dependency they never use
crates/trusted-server-adapter-cloudflare/Cargo.toml:33 and crates/trusted-server-adapter-spin/Cargo.toml:35 both have:
trusted-server-js = { workspace = true }Neither crate's sources or tests mention trusted_server_js, and no commit ever has (git log -G trusted_server_js -- crates/trusted-server-adapter-cloudflare crates/trusted-server-adapter-spin is empty). Both crates were created with the line: Cloudflare in #643 and Spin in #735. #614 had already removed the same direct dependency from the Fastly adapter as "accessed transitively via trusted-server-core". Core still depends on the crate, so this is dependency-graph hygiene. Removing the lines does not remove the Node requirement. It does make the graph that the #1194 crate split has to redraw accurate.
Steps to reproduce
Jobs that compile core, at a4e01eb
The last column counts tsjs: Building per-module bundles lines in the job log of a recent run whose workflow files are identical to a4e01eb. test.yml and format.yml counts come from runs 35968913882 and 35968913845 (head 7e3997a), and integration-tests.yml counts from run 35974697391 (head bf96305).
| Workflow / job | Compiles core | Pinned Node set up before the Rust build | TSJS builds in log |
|---|---|---|---|
test.yml / test-rust |
yes (cargo test-fastly) |
yes (test.yml:54-57, added for the template-cache harness) |
5 |
test.yml / test-axum |
yes | no | 13 |
test.yml / test-cloudflare |
yes | no | 3 |
test.yml / test-spin |
yes | no | 4 |
test.yml / test-parity |
yes (trusted-server-integration-tests depends on core) |
no | 2 |
test.yml / test-cli (macOS) |
yes | no | 10 |
test.yml / test-typescript |
no | yes | 0 |
format.yml / format-rust |
yes (all clippy steps) | no | 7 |
format.yml / check-claude-md-symlink, format-typescript, format-docs |
no | JS jobs yes | 0 |
integration-tests.yml / prepare-artifacts |
yes (composite action builds Fastly, Axum, Cloudflare; the Viceroy config script builds the integration-tests crate) | no | 4 |
integration-tests.yml / integration-tests |
yes (cargo test of the integration-tests crate) |
yes (integration-tests.yml:93-96) |
1 |
integration-tests.yml / integration-tests-fastly-ec |
yes (composite action builds Axum, then cargo test) |
no | 2 |
integration-tests.yml / browser-tests |
yes (composite action builds Axum) | only after the Rust build (integration-tests.yml:181-184) |
1 |
deploy-docs.yml / build, deploy |
no | docs job yes | n/a |
codeql.yml / analyze |
no cargo step (build-mode: none) |
no | n/a |
The composite action .github/actions/setup-integration-test-env/action.yml reads the Node version (:42-45) and exports it, but never calls actions/setup-node. integration-tests-fastly-ec and browser-tests do not pass build-axum: "false", so the action's default (:16-19) builds Axum in both jobs. In the browser job log, the Axum build's TSJS step ran at 08:32:15 and setup-node at 08:32:39.
To see the Node versions:
gh api -H "Accept: application/vnd.github.raw" \
"repos/actions/runner-images/contents/images/ubuntu/Ubuntu2404-Readme.md?ref=ubuntu24/20260907.300" | grep -n "Node.js"
gh api -H "Accept: application/vnd.github.raw" \
"repos/actions/runner-images/contents/images/macos/macos-26-arm64-Readme.md?ref=macos-26-arm64/20260907.0351" | grep -n "Node.js"Observed. Line 26 of each list is the Node on PATH. The #### Node.js sections list the cached versions that setup-node can select, 22.23.2 and 24.20.0 on both images.
26:- Node.js 22.23.2
196:#### Node.js
26:- Node.js 24.20.0
127:#### Node.js
The unused dependency
rustc's unused_crate_dependencies lint, applied to each adapter library only:
cargo rustc -p trusted-server-adapter-cloudflare --lib --target wasm32-unknown-unknown --features cloudflare -- -W unused-crate-dependencies
cargo rustc -p trusted-server-adapter-spin --lib --target wasm32-wasip1 --features spin -- -W unused-crate-dependenciesObserved, on the production wasm builds:
warning: extern crate `trusted_server_js` is unused in crate `trusted_server_adapter_cloudflare`
warning: extern crate `trusted_server_js` is unused in crate `trusted_server_adapter_spin`
On the native host target the lint also flags dependencies that are only used under cfg(target_arch = "wasm32"), so a workspace-wide lint would be noisy. trusted_server_js is the only dependency flagged on the wasm feature builds.
With the two lines deleted, on a copy of a4e01eb:
cargo check -p trusted-server-adapter-cloudflare -p trusted-server-adapter-spin --all-targets -> Finished
cargo test -p trusted-server-adapter-cloudflare -p trusted-server-adapter-spin -> 22 + 23 + 49 + 38 passed
cargo check -p trusted-server-adapter-cloudflare --target wasm32-unknown-unknown --features cloudflare -> Finished
cargo check -p trusted-server-adapter-spin --target wasm32-wasip1 --features spin -> Finished
The workspace entry is trusted-server-js = { path = "crates/trusted-server-js" } (Cargo.toml:115), with no features, so removing the direct edges does not change feature resolution.
Expected behavior
- Every CI job that compiles
trusted-server-corebuilds the TSJS bundles with the Node version in.tool-versions, the same one the JS jobs use. - Adapter crates declare only the dependencies they use.
Actual behavior
- 8 of 11 Rust-building jobs never set up the pinned Node, and 1 sets it up only after its Rust build. On Linux those builds use Node 22.
- Cloudflare and Spin carry an unused direct
trusted-server-jsdependency.
Root cause
- The Node setup was added job by job for specific needs. In
test-rust, for example, the step is named "Use Node.js for the served-seam contract":scripts/template-cache-local-test.sh, which that job runs, needsnodeto execute the GPT bundle (:69-70,:657). It was not added as a prerequisite of the core build script. - The composite integration action resolves the Node version but does not install it.
- The adapter crates copied a dependency line that Remove unused dependencies and disable unnecessary test targets #614 had already removed from the Fastly adapter.
Impact
- CI reproducibility, not correctness today: all these jobs pass. The risk is a silent change in bundle output, or a build failure, when the runner image's Node changes or when
.tool-versionsmoves. Upgrade to Rust 1.98.1 and align dependencies with EdgeZero #1124 and Upgrade to Rust 1.98.1 and align dependencies with EdgeZero #1123 plan to move it to 24.20.0, and that bump would not reach these jobs. - The unused dependency has no runtime effect.
Proposed fix
- Add an
actions/setup-node@v4step that reads.tool-versions, astest-rustdoes, before the first cargo command intest-axum,test-cloudflare,test-spin,test-parity,test-cliandformat-rust. - In
.github/actions/setup-integration-test-env/action.yml, addactions/setup-node@v4withnode-version: ${{ steps.node-version.outputs.node-version }}right after the "Retrieve Node.js version" step. That coversprepare-artifacts,integration-tests-fastly-ecandbrowser-tests. The latersetup-nodesteps inintegration-testsandbrowser-teststhen only matter for their npm cache settings. - Optionally, pass
cache: npmwithcache-dependency-path: crates/trusted-server-js/lib/package-lock.jsonso the build script'snpm ciis cached. - Delete
trusted-server-js = { workspace = true }from the Cloudflare and SpinCargo.tomlfiles and let Cargo updateCargo.lock.
Optional, separate from this task: neither integration-tests-fastly-ec nor browser-tests uses the Axum binary its composite step builds. The Fastly EC job runs only test_ec_lifecycle_fastly, AXUM_BINARY_PATH is read only by tests/environments/axum.rs, and the browser tests never mention Axum. Passing build-axum: "false" would save one full Rust build per job.
Done when
- Every job in the table that compiles core runs
actions/setup-nodewith the.tool-versionsNode before its first cargo command, and the composite action does the same. - A CI run shows
node-version: 24.12.0(or the current pin) in the setup step of each of those jobs. - The Cloudflare and Spin
Cargo.tomlfiles no longer listtrusted-server-js,Cargo.lockis updated, andcargo check-cloudflare,cargo check-spin,cargo test-cloudflareandcargo test-spinpass.
Affected area
CI / Tooling
Version
main at a4e01eb
Related
- Remove unused dependencies and disable unnecessary test targets #614 (closed) and PR Remove unused dependencies and disable unnecessary test targets #615 (merged): removed the same unused
trusted-server-jsdependency from the Fastly adapter. - Upgrade to Rust 1.98.1 and align dependencies with EdgeZero #1124 (open) and PR Upgrade to Rust 1.98.1 and align dependencies with EdgeZero #1123 (draft): bump the Node pin in
.tool-versionsto 24.20.0. With this task done, the bump reaches every Rust job. - build.rs should use
npm run ciinstead of install to prevent package-lock.json changes in diffs #378 (closed): asked forbuild.rsto usenpm ciinstead ofnpm install, which it does today. - Define integrations crate split and ordered configuration #1194 (draft spec): adds a second JS crate (
trusted-server-integrations-js) whose build script also runs the Node build, so each Rust build would run two. Setting up Node in every job covers both.
Activity
Pin Node before building ts and log scanned lines in lint-domains job