From 10439f3c6f058794f7d395dc347663271bf780ce Mon Sep 17 00:00:00 2001 From: Zack Tanner <1939140+ztanner@users.noreply.github.com> Date: Mon, 17 Aug 2026 06:56:34 -0700 Subject: [PATCH 1/3] [ci] Fix backport canary release dispatch (#97383) ## Summary - Use the job-scoped `GITHUB_TOKEN` with explicit `actions: write` permission to dispatch `trigger_release.yml` after a stable backport. - Avoid requesting Actions write access from the release GitHub App, which currently prevents the dispatch token from being created. - Preserve the existing forced preminor canary release behavior. This fixes the failure that left canary semver-behind stable after the `v16.3.1` backport. The evaluation succeeded, but the dispatch failed while creating the App token in the [failing dispatch job](https://github.com/vercel/next.js/actions/runs/31750536217/job/94615208366). ## Verification https://github.com/vercel/next.js/actions/runs/31830288265/job/94864091005 ``` should_dispatch=true reason=Dispatching canary preminor release because stable release 16.3.1 is ahead of 16.3.1-canary.17 released_version=16.3.1 current_canary_version=16.3.1-canary.17 dispatch_input=false auto_dispatch_enabled=true ``` --- .../workflows/sync_backport_canary_release.yml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/.github/workflows/sync_backport_canary_release.yml b/.github/workflows/sync_backport_canary_release.yml index 2d654b7d693c..6e5f81276ad8 100644 --- a/.github/workflows/sync_backport_canary_release.yml +++ b/.github/workflows/sync_backport_canary_release.yml @@ -121,20 +121,14 @@ jobs: needs: evaluate if: ${{ needs.evaluate.outputs.should_dispatch == 'true' && ((github.event_name == 'workflow_dispatch' && inputs.dispatch) || (github.event_name == 'workflow_run' && vars.ENABLE_BACKPORT_CANARY_SYNC == 'true')) }} runs-on: ubuntu-latest - steps: - - name: Create GitHub App token - id: release-app-token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - with: - client-id: ${{ vars.RELEASE_GITHUB_APP_CLIENT_ID }} - private-key: ${{ secrets.RELEASE_GITHUB_APP_PRIVATE_KEY }} - owner: ${{ github.repository_owner }} - repositories: next.js - permission-actions: write + permissions: + actions: write + steps: - uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0 with: - github-token: ${{ steps.release-app-token.outputs.token }} + # workflow_dispatch events created with GITHUB_TOKEN start workflow runs. + github-token: ${{ github.token }} script: | await github.request( "POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches", From d8234277bd907bdff1aab18b9550e8542f332299 Mon Sep 17 00:00:00 2001 From: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com> Date: Mon, 17 Aug 2026 18:41:51 +0200 Subject: [PATCH 2/3] test: restore missing NFT `exports*` unit fixtures (#97459) ### What? Restores the missing `node_modules` fixtures for the `exports`, `exports-fallback`, `exports-only` and `exports-path` cases in `turbopack-tracing`'s NFT unit test suite (`tests/unit.rs`), and enables the two that pass as-is (`exports-only`, `exports-path`). Co-authored-by: vercel-fleet[bot] <308483924+vercel-fleet[bot]@users.noreply.github.com> --- .../exports-fallback/node_modules/pkg/index.js | 1 + .../node_modules/pkg/package.json | 11 +++++++++++ .../node_modules/pkg/require-main.cjs | 1 + .../node_modules/pkg/subdir/import-main.js | 1 + .../node_modules/pkg/subdir/package.json | 1 + .../unit/exports-only/node_modules/pkg/index.js | 1 + .../exports-only/node_modules/pkg/package.json | 17 +++++++++++++++++ .../node_modules/pkg/require-main.cjs | 2 ++ .../node_modules/pkg/subdir/import-main.js | 1 + .../node_modules/pkg/subdir/package.json | 1 + .../node_modules/apollo-upload-client/index.js | 1 + .../apollo-upload-client/package.json | 12 ++++++++++++ .../public/ReactNativeFile.js | 1 + .../node_modules/extract-files/package.json | 12 ++++++++++++ .../extract-files/public/ReactNativeFile.js | 1 + .../test/unit/exports/node_modules/pkg/index.js | 1 + .../unit/exports/node_modules/pkg/package.json | 17 +++++++++++++++++ .../exports/node_modules/pkg/require-main.cjs | 2 ++ .../node_modules/pkg/subdir/import-main.js | 1 + .../node_modules/pkg/subdir/package.json | 1 + .../crates/turbopack-tracing/tests/unit.rs | 15 +++++++++++++-- 21 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/index.js create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/package.json create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/require-main.cjs create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/subdir/import-main.js create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/subdir/package.json create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/index.js create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/package.json create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/require-main.cjs create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/subdir/import-main.js create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/subdir/package.json create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/apollo-upload-client/index.js create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/apollo-upload-client/package.json create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/apollo-upload-client/public/ReactNativeFile.js create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/extract-files/package.json create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/extract-files/public/ReactNativeFile.js create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/index.js create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/package.json create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/require-main.cjs create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/subdir/import-main.js create mode 100644 turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/subdir/package.json diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/index.js b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/index.js new file mode 100644 index 000000000000..914a7c587cf4 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/index.js @@ -0,0 +1 @@ +module.exports = 'legacy index'; diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/package.json b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/package.json new file mode 100644 index 000000000000..60e39b3afe1a --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/package.json @@ -0,0 +1,11 @@ +{ + "name": "pkg", + "exports": { + ".": ["in:valid", { + "node": { + "import": "./subdir/import-main.js", + "require": "./require-main.cjs" + } + }, "./index.js"] + } +} diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/require-main.cjs b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/require-main.cjs new file mode 100644 index 000000000000..c7742045e5c6 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/require-main.cjs @@ -0,0 +1 @@ +module.exports = 'require main'; diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/subdir/import-main.js b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/subdir/import-main.js new file mode 100644 index 000000000000..95bc9efaf5a0 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/subdir/import-main.js @@ -0,0 +1 @@ +export default 'import main'; diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/subdir/package.json b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/subdir/package.json new file mode 100644 index 000000000000..5ffd9800b97c --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-fallback/node_modules/pkg/subdir/package.json @@ -0,0 +1 @@ +{ "type": "module" } diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/index.js b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/index.js new file mode 100644 index 000000000000..914a7c587cf4 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/index.js @@ -0,0 +1 @@ +module.exports = 'legacy index'; diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/package.json b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/package.json new file mode 100644 index 000000000000..e47a15410020 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/package.json @@ -0,0 +1,17 @@ +{ + "name": "pkg", + "main": "index.js", + "exports": { + ".": { + "node": { + "import": "./subdir/import-main.js", + "require": "./require-main.cjs" + } + }, + "./asdf": { + "node": { + "import": "./subdir/import-main.js" + } + } + } +} diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/require-main.cjs b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/require-main.cjs new file mode 100644 index 000000000000..43b69844d0d4 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/require-main.cjs @@ -0,0 +1,2 @@ +import('pkg/asdf'); +module.exports = 'require main'; diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/subdir/import-main.js b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/subdir/import-main.js new file mode 100644 index 000000000000..95bc9efaf5a0 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/subdir/import-main.js @@ -0,0 +1 @@ +export default 'import main'; diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/subdir/package.json b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/subdir/package.json new file mode 100644 index 000000000000..5ffd9800b97c --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-only/node_modules/pkg/subdir/package.json @@ -0,0 +1 @@ +{ "type": "module" } diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/apollo-upload-client/index.js b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/apollo-upload-client/index.js new file mode 100644 index 000000000000..914a7c587cf4 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/apollo-upload-client/index.js @@ -0,0 +1 @@ +module.exports = 'legacy index'; diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/apollo-upload-client/package.json b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/apollo-upload-client/package.json new file mode 100644 index 000000000000..a47bfc47c3b7 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/apollo-upload-client/package.json @@ -0,0 +1,12 @@ +{ + "name": "apollo-upload-client", + "exports": { + ".": { + "import": "./public/index.mjs", + "require": "./public/index.js" + }, + "./public/": "./public/", + "./package": "./package.json", + "./package.json": "./package.json" + } +} diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/apollo-upload-client/public/ReactNativeFile.js b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/apollo-upload-client/public/ReactNativeFile.js new file mode 100644 index 000000000000..f3e40b6795c2 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/apollo-upload-client/public/ReactNativeFile.js @@ -0,0 +1 @@ +module.exports = require('extract-files/public/ReactNativeFile'); diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/extract-files/package.json b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/extract-files/package.json new file mode 100644 index 000000000000..57b1b956efc5 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/extract-files/package.json @@ -0,0 +1,12 @@ +{ + "name": "extract-files", + "exports": { + ".": { + "import": "./public/index.mjs", + "require": "./public/index.js" + }, + "./public/": "./public/", + "./package": "./package.json", + "./package.json": "./package.json" + } +} \ No newline at end of file diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/extract-files/public/ReactNativeFile.js b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/extract-files/public/ReactNativeFile.js new file mode 100644 index 000000000000..898b8ea9b056 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports-path/node_modules/extract-files/public/ReactNativeFile.js @@ -0,0 +1 @@ +module.exports = 'React Native File'; diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/index.js b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/index.js new file mode 100644 index 000000000000..914a7c587cf4 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/index.js @@ -0,0 +1 @@ +module.exports = 'legacy index'; diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/package.json b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/package.json new file mode 100644 index 000000000000..e47a15410020 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/package.json @@ -0,0 +1,17 @@ +{ + "name": "pkg", + "main": "index.js", + "exports": { + ".": { + "node": { + "import": "./subdir/import-main.js", + "require": "./require-main.cjs" + } + }, + "./asdf": { + "node": { + "import": "./subdir/import-main.js" + } + } + } +} diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/require-main.cjs b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/require-main.cjs new file mode 100644 index 000000000000..43b69844d0d4 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/require-main.cjs @@ -0,0 +1,2 @@ +import('pkg/asdf'); +module.exports = 'require main'; diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/subdir/import-main.js b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/subdir/import-main.js new file mode 100644 index 000000000000..95bc9efaf5a0 --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/subdir/import-main.js @@ -0,0 +1 @@ +export default 'import main'; diff --git a/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/subdir/package.json b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/subdir/package.json new file mode 100644 index 000000000000..5ffd9800b97c --- /dev/null +++ b/turbopack/crates/turbopack-tracing/tests/node-file-trace/test/unit/exports/node_modules/pkg/subdir/package.json @@ -0,0 +1 @@ +{ "type": "module" } diff --git a/turbopack/crates/turbopack-tracing/tests/unit.rs b/turbopack/crates/turbopack-tracing/tests/unit.rs index f25f037c4d0e..92f620b2aa2e 100644 --- a/turbopack/crates/turbopack-tracing/tests/unit.rs +++ b/turbopack/crates/turbopack-tracing/tests/unit.rs @@ -102,11 +102,22 @@ static ALLOC: turbo_tasks_malloc::TurboMalloc = turbo_tasks_malloc::TurboMalloc; #[case::esm_export_wildcard("esm-export-wildcard")] #[case::esm_paths("esm-paths")] #[case::esm_paths_trailer("esm-paths-trailer")] +// nft traces a package's legacy `main` in addition to the target its `exports` field +// resolves to (unless nft's `exportsOnly` option is set), so its reference output lists +// `index.js` next to `require-main.cjs`, while Turbopack only traces the file it actually +// resolves to. // #[case::exports("exports")] +// Two reasons: as for `exports` above, nft also traces the legacy resolution (here the +// directory index `index.js`). On top of that, Turbopack resolves this fixture's `exports` +// fallback array to nothing at all, because it stops at the invalid first target +// (`"in:valid"`) instead of continuing with the next entry, so `require-main.cjs` is missed. // #[case::exports_fallback("exports-fallback")] #[case::exports_nomodule("exports-nomodule")] -// #[case::exports_only("exports-only")] -// #[case::exports_path("exports-path")] +// `exports-only` is the same fixture as `exports`, but nft traces it with `exportsOnly: +// true`, which matches Node's (and Turbopack's) semantics of ignoring `main` when an +// `exports` field is present. +#[case::exports_only("exports-only")] +#[case::exports_path("exports-path")] #[case::exports_wildcard("exports-wildcard")] // #[case::ffmpeg_installer("ffmpeg-installer")] #[case::file_folder_slash("file-folder-slash")] From 9e1dc0ebe4300d9f38172378ba471be4fae33618 Mon Sep 17 00:00:00 2001 From: hardfist Date: Tue, 18 Aug 2026 00:55:49 +0800 Subject: [PATCH 3/3] fix(turbo-persistence): allow 32-bit usize conversion (#97288) ### What? Change the pointer-width assertion in `usize_from_u32` from `<` to `<=`, allowing the conversion to compile on 32-bit targets. ### Why? The surrounding comment states that Turbopack assumes a pointer width of at least 32 bits, but the strict comparison rejects exactly 32-bit targets. Since `u32` and `usize` have the same width on these targets, the conversion remains lossless. This currently causes `rspack-turbo-persistence` to fail to compile with `error[E0080]` in Rspack's [`i686-pc-windows-msvc` CI job](https://github.com/web-infra-dev/rspack/actions/runs/31665978273/job/94340544786#step:25:446). ### How? Allow equal source and target bit widths in the compile-time assertion. --- turbopack/crates/turbo-persistence/src/write_batch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/turbopack/crates/turbo-persistence/src/write_batch.rs b/turbopack/crates/turbo-persistence/src/write_batch.rs index 1c837e3e18f4..4b5141cbe7fb 100644 --- a/turbopack/crates/turbo-persistence/src/write_batch.rs +++ b/turbopack/crates/turbo-persistence/src/write_batch.rs @@ -633,7 +633,7 @@ const fn usize_from_u32(value: u32) -> usize { // This should always be true, as we assume at least a 32-bit width architecture for Turbopack. // Since this is a const expression, we expect it to be compiled away. const { - assert!(u32::BITS < usize::BITS); + assert!(u32::BITS <= usize::BITS); }; value as usize }