## What?
Building on top of the changes in #92252. This PR implements similar
fork points for the path when cacheComponents is enabled. Both the
development and production path are implemented.
## What
Use sccache, backed by the Vercel artifact cache, when compiling Rust
code.
## Why
Each CI runner compiles ~960 external Rust crates from scratch (~5 min)
on binary cache misses, even though `Cargo.lock` rarely changes between
commits. Some workflows don't cache and always build from scratch.
## Notes
Builds will use a local cache on each runner, but we've got a lot of
these runners and they'll take some time to populate that local, fastest
level of cache.
Windows builds are currently hitting ~68% of cached compilations for a
reason that isn't totally clear. Linux builds are caching correctly,
however. A follow-up pass at this work will use an incremental turborepo
caching strategy to improve this, and another pass will experiment with
cross-compiling Windows from Linux which will likely also help.
Linux builds that don't change Rust files at all are nearly
instantaneous (as before), and Linux builds that change Rust files will
complete in approximately 1/2 the time. `check` builds are ~1min faster
(~25% faster).
LTO-heavy runs like the benchmark builders are currently still slow
(approx unchanged), needs further investigation (may be related to git
hash embedding?).
### What?
Implements native Node.js stream support for the RSC / HTML rendering.
This first step does not include cacheComponents / static generation.
Instead of converting between Node.js Readable streams and Web
ReadableStreams at every boundary, the rendering pipeline now uses
native Node.js `Transform`/`PassThrough`/`Readable` streams end-to-end
when the useNodeStreams experimental flag is enabled.
### Why?
The current rendering pipeline has a bottleneck on Web Streams. Each
step adds overhead: buffering, scheduling mismatches, and unnecessary
memory copies. Node.js streams are the native I/O primitive on the
server. Using them directly eliminates these conversion and
scheduling/promise costs.
This is the foundational plumbing needed to run the full app render
pipeline on native Node.js streams, which improves server-side rendering
throughput.
### How?
**Stream transform reimplementation** (`stream-ops.node.ts`):
All web `TransformStream`-based transforms have been reimplemented as
Node.js `Transform` streams:
- `createBufferedTransformStream` — coalesces chunks written in the same
microtask into a single `Uint8Array`
- `createFlightDataInjectionTransform` — interleaves RSC flight data
chunks with the HTML stream
- `createHeadInsertionTransform` — inserts server-generated HTML
(polyfills, scripts) before `</head>`
- `createMetadataTransform` — finds and replaces the `«nxt-icon»` meta
mark
- `createDeferredSuffixTransform` — appends the document suffix after
the first HTML chunk
- `createMoveSuffixTransform` — moves `</body></html>` to the end of the
stream
- `createHtmlDataDplIdTransform` — inserts a `data-dpl-id` attribute on
the opening `<html>` tag
- `createRootLayoutValidatorTransform` — validates `<html>` and `<body>`
tags are present (dev only)
**`ReplayableNodeStream`** (`app-render-prerender-utils.ts`):
New class that buffers all chunks from a source `Readable` and allows
creating multiple independent replay streams via `createReplayStream()`.
This replaces the web stream `tee()` operation for `ReactServerResult`
when using Node.js streams. Uses pull-based delivery (`_read()`) to
avoid AsyncLocalStorage context issues — chunks are only delivered when
the consumer reads, keeping them inside the correct ALS scope during
Fizz's `performWork`. Includes 392 lines of unit tests covering
buffering, live replay, error propagation, multiple independent replays,
subscriber cleanup, and dispose behavior.
**Native rendering functions**:
- `renderToNodeFlightStream` — calls React's `renderToPipeableStream`
directly, pipes to a `PassThrough`
- `renderToNodeFizzStream` — calls `renderToPipeableStream` for HTML
rendering without the web stream wrapper
- `createNodeInlinedDataStream` — wraps RSC flight data in `<script>`
tags using `Buffer` operations and `isUtf8()` for encoding detection
**`continueFizzStream` rewritten for Node.js**:
Instead of converting to web streams and delegating to
`webContinueFizzStream`, the Node.js path pipes through a chain of
native `Transform` streams directly: buffer → dpl-id → metadata →
deferred suffix → flight data injection → root layout validator → move
suffix → head insertion.
**API renames for clarity**:
- `renderToFlightStream` → `renderToWebFlightStream` /
`renderToNodeFlightStream`
- `renderToFizzStream` → `renderToWebFizzStream` /
`renderToNodeFizzStream`
- `createInlinedDataStream` → `createWebInlinedDataStream` /
`createNodeInlinedDataStream`
- `createDebugChannel` → `createWebDebugChannel` /
`createNodeDebugChannel`
**`app-render.tsx` fork points**:
The main render function now branches on
`process.env.__NEXT_USE_NODE_STREAMS` at two key points:
1. RSC rendering — uses `renderToNodeFlightStream` +
`createNodeDebugChannel`
2. HTML rendering — uses `renderToNodeFizzStream` + native
`continueFizzStream` with `createNodeInlinedDataStream`
All pre-render, cache components, and dev staged-render paths continue
to use web streams.
**CI updates** (`.github/workflows/build_and_test.yml`):
The `use-node-streams` test jobs now run without
`__NEXT_CACHE_COMPONENTS` / `__NEXT_EXPERIMENTAL_CACHED_NAVIGATIONS` /
`__NEXT_EXPERIMENTAL_APP_NEW_SCROLL_HANDLER` to isolate the Node.js
streams path.
We don't need to deploy a single image component example every time
`build_and_deploy` runs. If something about this example changes, it can
be manually re-deployed.
Re-apply #89861.
Somehow the tests passed in the PR but failed after merging. Will dig
into it.
Edit: Dug into it, there was a missing env var. Fixed and ready to merge
now.
PR doesn't add the Node.js streams code path. Implementation starts in
#90500
Re-submission of #91933. Had a problem with my fork and had to delete
it, which closed the original PR. Apologies for the noise.
## Summary
This PR pins all GitHub Actions to immutable commit SHAs instead of
mutable version tags and extracts expressions from `run:` blocks into
`env:` mappings.
- Pin 19 unpinned actions across workflow files to full 40-character
SHAs
- Add version comments for readability (e.g., `@abc123 # v1.0.9`)
- Extract 2 secrets and 5 workflow_dispatch inputs from run blocks to
env vars
## Changes by file
| File | Changes |
|------|---------|
| build_and_deploy.yml | Pinned ijjk/rust-cache, ast-grep/action,
taiki-e/install-action to SHA |
| build_reusable.yml | Pinned ijjk/rust-cache,
SimenB/github-actions-cpu-cores to SHA |
| cancel.yml | Pinned withgraphite/graphite-ci-action to SHA, extracted
GRAPHITE_TOKEN to env var |
| lock.yml | Pinned dessant/lock-threads to SHA |
| notify_slack.yml | Pinned slackapi/slack-github-action to SHA (2
instances) |
| publish_canary.yml | Extracted NPM_TOKEN_ELEVATED to env var |
| publish_release.yml | Extracted 5 workflow_dispatch inputs to env vars
|
| retry_deploy_test.yml | Pinned dtolnay/rust-toolchain to SHA |
| triage.yml | Pinned balazsorban44/nissuer to SHA |
| turbopack_benchmark.yml | Pinned taiki-e/install-action,
ijjk/rust-cache, CodSpeedHQ/action to SHA |
| turbopack_benchmark_wasm.yml | Pinned taiki-e/install-action,
CodSpeedHQ/action to SHA |
| turbopack_benchmark_xtask.yml | Pinned taiki-e/install-action,
CodSpeedHQ/action to SHA |
## Actions Pinned
| Action | Version | SHA |
|--------|---------|-----|
| ijjk/rust-cache | turbo-cache-v1.0.9 | a34594c45081... |
| ast-grep/action | v1.5.0 | cf62e780f0c8... |
| taiki-e/install-action | nextest / v2 | 3a0adb... / 7627fb... |
| withgraphite/graphite-ci-action | main | ee395f3a7825... |
| dessant/lock-threads | v5 | 1bf7ec25051f... |
| slackapi/slack-github-action | v1.25.0 | 6c661ce58804... |
| SimenB/github-actions-cpu-cores | v2 | 97ba232459a8... |
| dtolnay/rust-toolchain | stable | 631a55b12751... |
| balazsorban44/nissuer | 1.10.0 | 92ef22afd6a7... |
| CodSpeedHQ/action | v4 | 1c8ae4843586... |
## A note on internal action pinning
This PR pins all actions including org-owned ones. Best practice is to
pin everything \u2014 the tj-actions/changed-files attack was an
internally maintained action that was compromised, and every repo
referencing it by tag silently executed attacker code. That said, it's
your codebase. If you'd prefer to leave org-owned actions unpinned, let
us know and we'll adjust the PR.
## How to verify
Review the diff \u2014 each change is mechanical and preserves workflow
behavior:
- **SHA pinning**: `action@v3` becomes `action@abc123 # v3` \u2014
original version preserved as comment
- **Expression extraction**: `${{ expr }}` in `run:` moves to `env:`
block, referenced as `$ENV_VAR` in the script
- No workflow logic, triggers, or permissions are modified
I put up some research on this on
[Twitter](https://x.com/vigilance_one/status/2036581210663616729) and a
[research
site](https://www.vigilantdefense.com/research/github-top-50k-repos-cicd-security-scan)
if you want more context. I wrote a scanner called Runner Guard and open
sourced it [here](https://github.com/Vigilant-LLC/runner-guard).
If you have any questions, reach out. I'll be monitoring comms.
\\- Chris Nyhuis (dagecko)
---------
Co-authored-by: Benjamin Woodruff <github@benjam.info>
Co-authored-by: Benjamin Woodruff <benjamin.woodruff@vercel.com>
Fixes#91818
**Regression source:** Commit `b7e4c6a011` ("Turbopack: transpile
CHUNK_SUFFIX") introduced `getChunkSuffixFromScriptSrc()` which reads
query strings from `<script>` tags. On Safari, this picks up the `?ts=`
param injected by the server-side cache-busting workaround in
`render.tsx` (for [WebKit
#187726](https://bugs.webkit.org/show_bug.cgi?id=187726)), baking it
into `ASSET_SUFFIX`. This causes HMR CSS URLs to match the preloaded URL
exactly, re-triggering the Safari preload cache bug and preventing style
updates.
**Changes:**
- **`dev-backend-dom.ts`**: Match existing `<link>` elements by base
path (strip query string) so selectors work across HMR updates with
different `?ts=` values. Add Safari to the Firefox cache-busting branch
so new stylesheet links always get a fresh `?ts=`.
- **`hmr-client.ts`**: Fix `mergeChunkUpdates` so a `total` update
always supersedes any prior update type.
## Summary
- simplify `upload-adapter-test-results` condition to use the effective
Next version value
- run upload when version does not start with `http` (allows `canary`
and release tags)
- keep existing owner and deploy-script safeguards
## Why
- release runs can have `target_commitish` as a commit SHA, which caused
valid canary release runs to skip upload
# What
The turborepo cache appears to corrupt or truncate the docker file in
the cache - we can instead just hit the API directly and skip a few
steps.
## Summary
- gate `upload-adapter-test-results` to only run when triggered from the
`canary` branch
- support both trigger paths:
- `workflow_dispatch` on `canary`
- `release` where `target_commitish` is `canary`
- keep existing deploy-script and owner safeguards
## Why
The native binary build system uses 3 different napi-rs Docker images
that are opaque, can't be customized, and require runtime toolchain
downloads. Each CI run downloads compilers and sysroots from scratch,
wasting ~5 minutes per build. There's no way to customize the build
environment or share toolchains across the 4 Linux targets.
Some smoke tests are added to ensure that node.js can actually load the
binaries we build - we don't actually perform much beyond that, just
making sure it survives the dynamic linker and correctly exposes the
node APIs.
We also are able to enable `--icf=all`. This appears to (consistently)
chop off about ~1-2% of the binary size.
## What
Replaces the 3 napi-rs Docker images with a single custom
`next-swc-builder` Dockerfile based on Ubuntu 20.04 that can
cross-compile all 4 Linux targets (x86_64/aarch64 × gnu/musl) from
either an x86_64 or aarch64 host. All toolchains are baked into the
image.
Key changes:
- **`docker/native-builder.Dockerfile`**: Ubuntu 20.04 with clang/lld,
GNU cross-sysroots via `crossbuild-essential`, musl sysroots from
musl.cc, Node.js 20, pinned Rust nightly, and `cargo-rustflags` for flag
resolution
- **`scripts/docker-native-build.sh`**: Inner build script that
constructs RUSTFLAGS via `cargo rustflags --config` (merges
`.cargo/config.toml` with cross-compilation overrides), sets up CC/CXX
per target, and runs the napi build
- **`scripts/docker-native-build.js`**: Node.js local build orchestrator
replacing the bash wrapper, with `--quick`, `--rebuild`, `--test` flags
and smoke testing via `getTargetTriple()`
- **`scripts/docker-image-cache.js`**: Turbo-cached Docker image
(save/load with `--load` for cache hit handling)
- **`.cargo/config.toml`**: Added musl `crt-static` flag, removed
cross-compilation flags (now in build script)
- **CI workflows**: Docker image cached via turbo remote cache,
`build-docker-image` turbo task, simplified `build_and_deploy.yml`
## How
All 4 Linux targets use clang as the C compiler + linker driver with
`gnu-lld-cc` flavor (rust-lld does actual linking). Cross-compilation
uses `--target` + `--sysroot`:
- **GNU targets**: Ubuntu multiarch sysroots from
`crossbuild-essential-{amd64,arm64}`
- **Musl targets**: musl.cc cross-toolchain sysroots with GCC crt files
copied into sysroot lib (works around clang 10's `--gcc-toolchain`
limitation)
RUSTFLAGS are resolved inside the container via `cargo rustflags` which
merges `.cargo/config.toml` (base flags like `-Zunstable-options`, musl
`crt-static`) with per-target cross flags passed as `--config` inline
TOML.
The Docker image is cached via turbo's remote cache (~885 MB tar). On
cache hit, `docker load` restores it in seconds. On miss, the full image
build takes ~2 minutes.
### glibc compatibility
Building on Ubuntu 20.04 (glibc 2.31) ensures broad compatibility. The
table below shows the minimum glibc version required by major Linux
distributions ([source](https://repology.org/project/glibc/versions)):
| Distribution | glibc | Compatible? |
|---|---|---|
| Ubuntu 20.04 (Focal) | 2.31 | ✅ baseline |
| Ubuntu 22.04 (Jammy) | 2.35 | ✅ |
| Ubuntu 24.04 (Noble) | 2.39 | ✅ |
| Debian 11 (Bullseye) | 2.31 | ✅ |
| Debian 12 (Bookworm) | 2.36 | ✅ |
| RHEL / AlmaLinux 8 | 2.28 | ❌ EOL May 2029 (security only) |
| RHEL / AlmaLinux 9 | 2.34 | ✅ |
| Amazon Linux 2 | 2.26 | ❌ EOL June 2026 |
| Amazon Linux 2023 | 2.34 | ✅ |
| Fedora 40+ | 2.39+ | ✅ |
| Arch Linux | 2.41+ | ✅ |
# What
Refactor build_and_deploy.yml to make it more maintainable, add
documentation to all of the quirky flags we use and remove any flags
that are not doing anything useful.
# Non-goals
- wasm builds were left out of the matrix, but could probably be added
in at a later date
- cross-compilation flags should probably not live in .cargo/config.toml
but rather in a .cargo/cross-config.toml we conditionally include, but
this would add some complexity.
# Why
After enabling LTO, our MUSL target builds got significantly slower.
This wins back a good chunk of the performance that we lost by using
cross-compilation to MUSL on docker images that are not slow as heck,
while also trying to clean up this workflow that has accumulated some
cruft over the years.
The timings are fairly unstable because of uncertain build machine
variability, but I've tried to capture uncached runs where possible. I
believe we can state that LTO has a _slight_ increase in compile time,
but MUSL builds are faster than the pre-LTO state of things.
# Changes
- Refactor build_and_deploy.yml: replace per-target matrix entries with
mmm-matrix declarative config, consolidate docker build script inline,
pin actions to commit SHAs
- Simplify .cargo/config.toml using cfg(true) (RFC 3695) to eliminate
rustflag duplication across target sections
- Remove GNU linker flags (rust-lld is now default on x86_64-linux-gnu)
- Use rust-lld directly for musl targets, remove unused armv7 section
- Add cargo xtask print-rustflags to replace .github/rustflags.yml
- Release profile: thin LTO + codegen-units=64 for faster builds
- Add --log-order stream to TURBO_ARGS for live build output
- Remove mold linker integration from CI
## Summary
Run existing app-dir tests with `__NEXT_USE_NODE_STREAMS=true` in CI to
validate the node stream rendering path alongside the default web stream
path.
- New CI job in `build_and_test.yml` that runs a curated set of app-dir
tests with the flag enabled
- `test/use-node-streams-tests-manifest.json`: manifest of tests to run
in node-stream mode
## Test plan
- [x] CI job triggers and runs tests successfully
- [x] Does not affect existing CI jobs
---------
Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
## What
Fixes the `test cargo unit` CI job which has been consistently timing out (30 min) on canary since #91343 landed on Mar 14.
## Why
Two issues were contributing to the timeout:
1. **LTO on unit test binaries**: #91343 added `lto = "thin"` to `[profile.release]`. The `release-with-assertions` profile (used by `test-cargo-unit`) inherits from `release`, so it inherited LTO. Unlike the native binary build which only links one artifact, `cargo nextest run --workspace` builds test binaries for dozens of crates — each requiring its own LTO link pass. This pushed the build from ~8 minutes to 30+ minutes, exceeding the job timeout.
2. **No remote cache timeout or streaming output**: The `turbo run test-cargo-unit` command had no `--remote-cache-timeout` (unlike the build step which uses `--remote-cache-timeout 60`) and used turbo's default grouped log output, which buffers all output until the task completes. This made the job appear completely silent for 30 minutes before being killed, making it impossible to diagnose.
## How
- Added a `release-with-assertions-no-lto` cargo profile that inherits from `release-with-assertions` but disables LTO, and switched `test-cargo-unit` to use it. The production native build continues to use `release-with-assertions` with LTO.
- Added `--remote-cache-timeout 60 --log-order stream` to the turbo command for `test-cargo-unit` for parity with the build step and real-time output visibility.
# What
Add `lto = "thin"` to the workspace-level `[profile.release]` in
`Cargo.toml`.
# Why
Thin LTO enables cross-crate optimization at link time, improving
runtime
performance of the final artifacts (next-napi-bindings native module,
turbopack-cli binary, and benchmarks) without the full build time cost
of
fat LTO.
# How
Added `lto = "thin"` to the workspace root `[profile.release]` section.
This applies to all release-profile link targets in the workspace,
including
binaries, cdylibs, and benchmarks. The `release-with-assertions` and
`release-with-debug` profiles inherit from `release`, so they also
benefit.
We've had a longstanding issue where you'd have to run `pnpm i` _twice_ on a fresh checkout because `pnpm` wouldn't set up binary symlinks until after the binary exists, but the binary wouldn't exist until after `pnpm build` was done:
https://github.com/vercel/next.js/blob/canary/.github/workflows/build_reusable.yml#L303-L311
This solves that problem using a pnpm preinstall script that creates stub binaries for these files if they don't exist yet (because we haven't run `pnpm build`).
## Test Plan
```
git clean -fxd
pnpm i
pnpm build
pnpm test-start test/e2e/app-dir/next-image/
pnpm test-start-turbo test/e2e/app-dir/next-image/
```
I tested this both locally and inside of a fresh ubuntu VM.
Running `pnpm next` after `pnpm i` but before `pnpm build` gives a helpful error message:
<img width="946" height="125" alt="Screenshot 2026-03-06 at 9 37 14 PM" src="https://github.com/user-attachments/assets/4517e8bd-60ca-44f2-a34c-f7f3ec56c634" />
Preview builds served via `vercel-packages.vercel.app` were showing the
published canary version instead of the PR-specific preview version.
This happened because `create-preview-tarballs.js` updated
`package.json` after the build, but the version was already baked into
the compiled `dist/` files by `setNextVersion` in `taskfile-swc.js`.
This extracts the version computation from `create-preview-tarballs.js`
into a new `set-preview-version.js` script that runs before `pnpm run
build`, so the compiled output naturally includes the correct version.
`create-preview-tarballs.js` now reads the version from
`packages/next/package.json` instead of computing it independently.
## Test Plan
1. Create a new app: `pnpm create next-app@canary`
2. Install the preview build from this PR: `pnpm i
https://vercel-packages.vercel.app/next/commits/06681c21e886a97e39d277808780884151c00318/next`
3. Run `pnpm dev` and inspect `next.version` in DevTools — should show
`16.2.0-preview-06681c21-20260306` instead of the canary version
The recent Cached Navigations feature introduced navigation-level
caching into the segment cache, where static and dynamic RSC data from
navigations and initial HTML loads is cached so that repeat visits can
be served instantly. This feature is currently gated behind
`cacheComponents`, meaning it activates for all projects that enable
Cache Components.
This change introduces a new `experimental.cachedNavigations` flag that
independently controls the Cached Navigations behavior. The flag
defaults to `false` so we can investigate potential regressions that the
feature might have introduced without affecting the broader Cache
Components functionality.
The flag requires `cacheComponents` to also be enabled and throws a
configuration error if `cachedNavigations` is set without it. On the
server, the staged rendering paths in `app-render.tsx` (both RSC request
handling and initial HTML rendering) now check `cacheComponents &&
cachedNavigations` before producing staged responses. On the client,
`process.env.__NEXT_EXPERIMENTAL_CACHED_NAVIGATIONS` is used alongside
`process.env.__NEXT_CACHE_COMPONENTS` for compile-time dead code
elimination in the stream tee (`app-index.tsx`) and the response
processing (`fetch-server-response.ts`).
The cached navigations test suite enables the flag via `next.config.ts`,
and the Cache Components CI jobs export
`__NEXT_EXPERIMENTAL_CACHED_NAVIGATIONS=true` to maintain test coverage.
## Summary
- Adds `cleanupScriptPath` workflow dispatch input and
`NEXT_TEST_CLEANUP_SCRIPT_PATH` env var to `test_e2e_deploy_release.yml`
(webpack + turbopack jobs)
- Adds `cleanupUsingCustomScript()` method to `NextDeployInstance`
following the same pattern as the existing deploy and logs scripts
- Calls the cleanup script in `destroy()` before existing teardown logic
---------
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
## Summary
For context we discovered jobs were not reliably always running in
https://github.com/vercel/next.js/pull/90668 as addapters + turbopack
group ran more tests than just turbopack group.
- Each sharded test sub-job independently fetched test timings from KV
via a turbo task. Because turbo cache keys can vary across job groups
and KV can return slightly different data at different times, the
sharding algorithm produced different test-to-shard assignments across
groups — causing some tests to be missing entirely and others to run in
multiple shards.
- Adds a `--require-timings` flag to `run-tests.js` that fails loudly if
`test-timings.json` can't be loaded from disk, preventing silent
fallback to KV or round-robin.
- Adds a `testTimingsArtifact` input to `build_reusable.yml` that
downloads a pre-built timings artifact instead of fetching via turbo.
When unset (default), existing behavior is preserved.
- In both `test_e2e_deploy_release.yml` and `build_and_test.yml`,
timings are now fetched once in a setup job, uploaded as a GitHub
artifact, and downloaded by all sub-jobs — guaranteeing identical shard
assignments across all job groups.
## Test plan
- [ ] Verify `build_and_test.yml` jobs pick up the shared `test-timings`
artifact
- [ ] Verify `test_e2e_deploy_release.yml` deploy jobs pick up the
shared `test-timings` artifact
- [ ] Verify workflows that don't pass `testTimingsArtifact` (e.g.
`integration_tests_reusable.yml`, `pull_request_stats.yml`) still use
the turbo fallback path unchanged
<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:
## For Contributors
### Improving Documentation
- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide
### Fixing a bug
- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md
### Adding a feature
- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md
## For Maintainers
- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change
### What?
### Why?
### How?
Closes NEXT-
Fixes #
-->
Co-authored-by: JJ Kasper <jj@jjsweb.site>
<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:
## For Contributors
### Improving Documentation
- Run `pnpm prettier-fix` to fix formatting issues before opening the PR.
- Read the Docs Contribution Guide to ensure your contribution follows the docs guidelines: https://nextjs.org/docs/community/contribution-guide
### Fixing a bug
- Related issues linked using `fixes #number`
- Tests added. See: https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md
### Adding a feature
- Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. (A discussion must be opened, see https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added (https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md
## For Maintainers
- Minimal description (aim for explaining to someone not on the team to understand the PR)
- When linking to a Slack thread, you might want to share details of the conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic behind a change
### What?
### Why?
### How?
Closes NEXT-
Fixes #
-->
This should reduce some duplicate CI jobs.
This split existed to support separate dev/prod manifests for skipping tests. That's not needed anymore, so we can just switch to the Webpack setup. This manual partitioning of `integration` tests into dev vs prod was brittle anyway
We still need this setup for rspack though
This avoids cancelling on canary branch when a commit is merged while
previous commit is still running
## Summary
- keep cancel-in-progress behavior for pull_request runs
- stop canceling in-progress runs for follow-up pushes to canary by
using a per-run concurrency group for push events
x-ref:
https://github.com/vercel/next.js/actions/runs/22113161316/job/63914496141
Fork the set of deployment tests so they run with both turbopack and
webpack. Now that turbopack is the default bundler we need this
coverage.
Because we are now running twice as many tests, decrease concurrency,
otherwise we hit rate limits on vercel. There were attempts to improve
rate limit recovery in the vercel CLI
(https://github.com/vercel/vercel/pull/14443 and
https://github.com/vercel/vercel/pull/14407) which helped but did not
solve the issue. Also there was an investigation into the API service
where we discovered some suspicious but ultimately correct code
(https://github.com/vercel/api/pull/55967).
The basic issue is that the vercel CLI polls `api-deployments-get`
fairly aggressively at the beginning of a deploymnet, and since we start
so many deployments in parallel we will always hit the rate limits. The
recovery logic in the CLI is good but has (reasonably) a fixed set of
retries it will attempt, inevitably some tasks get unlucky. So retrying
the test does work, but really we should slow down which is what we do
here. 😥https://github.com/vercel/next.js/actions/runs/20290161194/job/58272593085
Fixes PACK-5613
---------
Co-authored-by: JJ Kasper <jj@jjsweb.site>
We don't need/want preview builds for these base branches, it's a waste
of CI capacity.
Relevant docs:
https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#onpushbranchestagsbranches-ignoretags-ignore
> Use the branches filter when you want to include branch name patterns
or when you want to both include and exclude branch names patterns. Use
the branches-ignore filter when you only want to exclude branch name
patterns. You cannot use both the branches and branches-ignore filters
for the same event in a workflow.
> If you define only tags/tags-ignore or only branches/branches-ignore,
the workflow won't run for events affecting the undefined Git ref. If
you define neither tags/tags-ignore or branches/branches-ignore, the
workflow will run for events affecting either branches or tags.
## Enable Rust backtraces in CI tests
### What?
Added `RUST_BACKTRACE=1` environment variable to all Turbopack-related test workflows.
### Why?
This change enables detailed Rust backtraces when Turbopack encounters errors during CI tests, making it easier to diagnose and fix issues that occur in the Rust components.
Notably, some assertions/panics are about detecting race conditions, e.g.
```
thread 'tokio-runtime-worker' (1056161) panicked at turbopack/crates/turbo-tasks-backend/src/backend/operation/mod.rs:426:13:
Concurrent task lock acquisition detected. This is not allowed and indicates a bug. It can lead to deadlocks.
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
Rather than painfully attempting to reproduce locally we can just run with the env var all the time and perhaps that will be enough to figure out rare issues
Just plumbing and enabling that flag in the experimental shards. The flag will enable our Layout router to use Fragment refs for scroll restoration. Implementation will be done in a follow-up.
Disclaimer: This PR is entirely claude+opencode generated.
- Crate name said `next-swc-napi`, which was confusing, because this has a lot more than swc bindings nowdays.
- The crate name didn't match the directory name, which often confused agents.
This does not change the npm package name, as that would likely have a much larger blast radius, and could break more things, to a point where it may not be worth it.
<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:
## For Contributors
### Improving Documentation
- Run `pnpm prettier-fix` to fix formatting issues before opening the PR.
- Read the Docs Contribution Guide to ensure your contribution follows the docs guidelines: https://nextjs.org/docs/community/contribution-guide
### Fixing a bug
- Related issues linked using `fixes #number`
- Tests added. See: https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md
### Adding a feature
- Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. (A discussion must be opened, see https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added (https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md
## For Maintainers
- Minimal description (aim for explaining to someone not on the team to understand the PR)
- When linking to a Slack thread, you might want to share details of the conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic behind a change
### What?
### Why?
### How?
Closes NEXT-
Fixes #
-->
This updates to run the entire E2E deploy tests same as we do currently
but with adapters enabled to catch regressions there. These run on a
separate test team to isolate from existing test team and avoid rate
limits.
Test run of the workflow done here
https://github.com/vercel/next.js/actions/runs/21418745794
The warnings from `baseline-browser-mapping` about outdated data fail some tests that don't expect the CLI output. By updating the dependency we avoid showing the warning for now, and by setting the environment variable `BASELINE_BROWSER_MAPPING_IGNORE_OLD_DATA` we should silence any future warnings as well.
related:
- #86625
- #86653