Commit Graph

1130 Commits

Author SHA1 Message Date
Tim Neutkens a9a8e272c0 Node.js streams: Add forkpoint for CacheComponents (#92444)
## 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.
2026-04-10 12:02:28 +00:00
Matt Mastracci f98a3f1101 [turbopack] Rust dependency caching via sccache (#91873)
## 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?).
2026-04-09 18:42:03 +00:00
Tim Neutkens de7ce396a2 Node.js streams: Fork points (#92252)
### 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.
2026-04-08 19:45:15 +02:00
Luke Sandberg b6ff360b41 Bump turborepo from 2.8.11 to 2.9.4 (#92425)
Bump the `turbo` dependency from `2.8.11` to `2.9.4` (latest stable).
2026-04-06 20:46:21 -07:00
Zack Tanner d5f479c128 ci: remove deploy examples workflow from build-and-deploy (#92324)
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.
2026-04-03 15:10:06 -07:00
Tim Neutkens 4582b5fa93 Reapply "ci: add node-stream test coverage workflow (#89861)" (#91664)
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
2026-04-01 20:42:25 +02:00
dagecko f7de136c60 fix: pin 19 actions to commit SHA, extract 7 expressions to env vars (#92016)
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>
2026-04-01 00:57:59 +00:00
Luke Sandberg 8be5a3c282 [turbopack] Fix CSS HMR on Safari (#92123)
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.
2026-03-31 14:49:53 -07:00
JJ Kasper 1e2b02e570 ci: relax adapter results upload gate (#92127)
## 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
2026-03-30 16:22:19 -07:00
Matt Mastracci eab7a23533 [turbopack] Don't use turborepo to build the docker image (#92029)
# 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.
2026-03-28 13:02:26 -07:00
JJ Kasper b5cb015c5f ci: only upload adapter results for canary runs (#91881)
## 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
2026-03-24 18:20:02 -07:00
JJ Kasper 9920dbace1 ci: upload adapter deploy test results (#91846)
Adds a final step to our e2e deploy test job to upload results for our
adapter for comparison.

x-ref:
https://github.com/vercel/next.js/actions/runs/23471649794/job/68298210825#step:5:40
2026-03-24 12:38:25 -07:00
Matt Mastracci b163a8bf66 [turbopack] Rebuild the docker build scripts (#91799)
## 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+ | ✅ |
2026-03-24 13:07:37 -06:00
Sebastian "Sebbie" Silbermann 3241be2d90 [ci] Allow "rerun failed jobs" to work up until 5 days (#91825) 2026-03-23 18:15:09 +01:00
Matt Mastracci 75193d5f26 [turbopack] Improve regressed build speed on cross-compiled MUSL (#91477)
# 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
2026-03-20 15:12:50 -06:00
Tim Neutkens afbce6a6d2 Revert "ci: add node-stream test coverage workflow (#89861)"
This reverts commit 058d950b15.
2026-03-19 18:34:23 +01:00
Jimmy Lai 058d950b15 ci: add node-stream test coverage workflow (#89861)
## 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>
2026-03-19 16:43:05 +01:00
Luke Sandberg 4a99afc90f fix: test-cargo-unit CI job timing out since LTO was enabled (#91424)
## 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.
2026-03-15 15:07:00 -07:00
Matt Mastracci 2b4bde2ebb Enable thin LTO for release builds (#91343)
# 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.
2026-03-14 12:49:43 -06:00
JJ Kasper 394668e31e test-new-tests: enable adapter in deploy flow (#91269)
## Summary
- export `NEXT_ENABLE_ADAPTER=1` in the `test-new-tests-deploy` workflow
job
- export `NEXT_ENABLE_ADAPTER=1` in the
`test-new-tests-deploy-cache-components` workflow job

## Testing
- `git diff --check`
2026-03-12 10:19:51 -07:00
Benjamin Woodruff 1eab3361c7 fix: Use a pnpm preinstall script to fix catch-22 in next binary creation (#91016)
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" />
2026-03-10 11:21:15 -07:00
Hendrik Liebau 87a8fb2f8f Fix preview version in window.next.version for PR builds (#90937)
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
2026-03-06 12:30:19 +01:00
Hendrik Liebau d08f4dc08c Add experimental.cachedNavigations feature flag (#90928)
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.
2026-03-06 10:39:47 +01:00
Zack Tanner 9ff3b7c424 [ci]: continue-on-error for more gh auth status checks (#90890)
This seems to be failing for our deploy test workflow
([x-ref](https://github.com/vercel/next.js/actions/runs/22685809647/job/65778800145)).

Updating to `continue-on-error` similar to
https://github.com/vercel/next.js/pull/89098 because this check doesn't
seem reliable.

If it fixes, will just remove in both spots all together.
2026-03-04 13:17:19 -08:00
Sebastian "Sebbie" Silbermann 9c31bbdaa9 [ci] Use commit instead of PR number for preview builds in deploy tests (#90722) 2026-03-01 12:59:37 +01:00
JJ Kasper f18e688589 Add custom cleanup script support for deploy tests (#90696)
## 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>
2026-02-28 09:41:50 -08:00
JJ Kasper 683180bfb3 Centralize test timings to fix shard divergence in CI (#90672)
## 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
2026-02-28 00:15:43 +00:00
JJ Kasper 55bb48da25 Ensure we only run main test mode with custom deploy script (#90665)
This ensures we don't try running both webpack and turbopack suites or
the report/PR jobs when a custom deploy script is provided.
2026-02-27 13:49:51 -08:00
Niklas Mischkulnig 38b69ff709 test: Run Adapter e2e tests with Turbopack instead (#90600)
<!-- 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>
2026-02-26 22:22:07 -08:00
Niklas Mischkulnig 91ab570933 test: remove stray TURBOPACK_BUILD=1 (#90602)
Forgot to remove this in https://github.com/vercel/next.js/pull/83335

This env var might filter some tests that should actually run (Webpack doesn't set it at all)
2026-02-26 18:09:49 +01:00
Sebastian "Sebbie" Silbermann a8de0a0044 Enable experimental.reactDebugChannel by default (#90310)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-02-26 16:00:47 +01:00
Niklas Mischkulnig 14ac25b975 Bump Turborepo to 2.8.11 (#90530)
<!-- 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 #

-->
2026-02-25 23:28:38 +01:00
Sebastian "Sebbie" Silbermann 9a8228474e [ci] Always upload Turborepo summary artifact (#90441) 2026-02-24 16:16:56 +01:00
Niklas Mischkulnig 351a67529b Bump Turborepo to 2.8.9 (#90079) 2026-02-23 10:24:49 +01:00
Niklas Mischkulnig 445d880ef9 test: Don't run integration tests twice for Turbopack (#83335)
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
2026-02-18 18:57:16 +01:00
JJ Kasper b0595b17ae ci: only cancel pull_request_stats on PR updates (#90104)
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
2026-02-17 12:10:38 -08:00
Luke Sandberg a7c61c10ad [turbopack] Run the deployment tests for turbopack and webpack (#84360)
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>
2026-02-17 11:52:10 -08:00
JJ Kasper ce738b9f8c Disable jest cache for CI instead of wiping (#90097)
This is aiming to fix sporadic failures from jest transforms which is
most likely caused by the change to output to custom jest-cache folder
and wipe that between runs. Instead this disables the cache via
`--no-cache` flag and also fixes WASM bindings issue that started due to
cache not being available.

x-ref:
https://github.com/vercel/next.js/actions/runs/22109996356/job/63903450669?pr=90096#step:35:493
x-ref:
https://github.com/vercel/next.js/actions/runs/22109996356/job/63903820197?pr=90096#step:35:18167
2026-02-17 10:34:54 -08:00
Benjamin Woodruff 6f94c0128f chore: Don't run build-and-deploy CI job on graphite-base branches (#89982)
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.
2026-02-13 22:44:27 +00:00
Luke Sandberg af4ceab6d4 Enable backtraces in turbopack integration tests (#89935)
## 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
2026-02-13 08:10:20 -08:00
Sebastian "Sebbie" Silbermann 3dafc76fc1 [fragment-scroll] Add experimental.appNewScrollHandler (#83107)
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.
2026-02-12 14:54:38 +01:00
Sebastian "Sebbie" Silbermann c49cc9faf8 [test] Ensure new deploy test builds have the necessary env variables (#89846) 2026-02-11 21:23:27 +01:00
JJ Kasper 0d15dd58bb Add separate E2E deploy env for turbopack tests (#89458)
x-ref: [slack
thread](https://vercel.slack.com/archives/C04KC8A53T7/p1770151130656569?thread_ts=1770107873.440639&cid=C04KC8A53T7)
2026-02-03 21:13:12 +00:00
Benjamin Woodruff a4c1a0cd72 Turbopack: Rename crates/napi to crates/next-napi-bindings and update crate name (#89314)
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.
2026-01-30 15:36:57 -08:00
JJ Kasper b5185dd851 Accept deploy script and log script as inputs (#89253)
Follow-up to https://github.com/vercel/next.js/pull/89206 this accepts
the new script paths as inputs and skips our own adapter's job when
these are provided.
2026-01-29 09:48:49 -08:00
Niklas Mischkulnig e5043d0e4d [ci] Clear Jest transform cache (#89247)
<!-- 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 #

-->
2026-01-29 17:25:08 +01:00
JJ Kasper 1104c45f25 Add full adapters E2E tests to workflow (#89125)
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
2026-01-28 14:16:20 -08:00
Hendrik Liebau 11e295089c [ci] Silence baseline-browser-mapping warnings (#89175)
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
2026-01-28 19:24:27 +01:00
Sebastian "Sebbie" Silbermann b210e2e6f2 [ci] Make gh auth status optional when triggering a release (#89098) 2026-01-27 16:04:16 +01:00
Sebastian "Sebbie" Silbermann 62f400216a Enable pnpm dependency caching in e2e deploy tests (#88953) 2026-01-27 15:07:11 +01:00