Repository: vercel/next.js
Pull request: ci: add node-stream test coverage workflow

## 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

Changed files:
filename: .github/workflows/build_and_test.yml
patch: @@ -812,7 +812,6 @@ jobs:
 
     uses: ./.github/workflows/build_reusable.yml
     with:
-      # Keep Next.js related env variables in sync with additionalEnv in next-deploy.ts
       afterBuild: |
         export __NEXT_CACHE_COMPONENTS=true
         export __NEXT_EXPERIMENTAL_CACHED_NAVIGATIONS=true
@@ -1163,6 +1162,58 @@ jobs:
       stepName: 'test-cache-components-prod-${{ matrix.group }}'
     secrets: inherit
 
+  test-node-streams-dev:
+    name: test node streams dev
+    needs: ['optimize-ci', 'changes', 'build-native', 'build-next']
+    if: ${{ needs.optimize-ci.outputs.skip == 'false' && needs.changes.outputs.docs-only == 'false' }}
+
+    strategy:
+      fail-fast: false
+      matrix:
+        group: [1/6, 2/6, 3/6, 4/6, 5/6, 6/6]
+    uses: ./.github/workflows/build_reusable.yml
+    with:
+      afterBuild: |
+        export __NEXT_USE_NODE_STREAMS=true
+        export __NEXT_CACHE_COMPONENTS=true
+        export __NEXT_EXPERIMENTAL_APP_NEW_SCROLL_HANDLER=true
+        export NEXT_EXTERNAL_TESTS_FILTERS="test/cache-components-tests-manifest.json,test/use-node-streams-tests-manifest.json"
+        export NEXT_TEST_MODE=dev
+        export IS_TURBOPACK_TEST=1
+        export TURBOPACK_DEV=1
+
+        node run-tests.js \
+          --timings \
+          -g ${{ matrix.group }} \
+          --type development
+      stepName: 'test-node-streams-dev-${{ matrix.group }}'
+    secrets: inherit
+
+  test-node-streams-prod:
+    name: test node streams prod
+    needs: ['optimize-ci', 'changes', 'build-native', 'build-next']
+    if: ${{ needs.optimize-ci.outputs.skip == 'false' && needs.changes.outputs.docs-only == 'false' }}
+
+    strategy:
+      fail-fast: false
+      matrix:
+        group: [1/7, 2/7, 3/7, 4/7, 5/7, 6/7, 7/7]
+    uses: ./.github/workflows/build_reusable.yml
+    with:
+      afterBuild: |
+        export __NEXT_USE_NODE_STREAMS=true
+        export __NEXT_CACHE_COMPONENTS=true
+        export __NEXT_EXPERIMENTAL_APP_NEW_SCROLL_HANDLER=true
+        export NEXT_EXTERNAL_TESTS_FILTERS="test/cache-components-tests-manifest.json,test/use-node-streams-tests-manifest.json"
+        export NEXT_TEST_MODE=start
+
+        node run-tests.js \
+          --timings \
+          -g ${{ matrix.group }} \
+          --type production
+      stepName: 'test-node-streams-prod-${{ matrix.group }}'
+    secrets: inherit
+
   tests-pass:
     needs:
       [
@@ -1181,6 +1232,8 @@ jobs:
         'test-cache-components-dev',
         'test-cache-components-prod',
         'test-cache-components-integration',
+        'test-node-streams-dev',
+        'test-node-streams-prod',
         'test-cargo-unit',
         'rust-check',
         'rustdoc-check',

filename: test/use-node-streams-tests-manifest.json
patch: @@ -0,0 +1,14 @@
+{
+  "version": 2,
+  "suites": {},
+  "rules": {
+    "include": [
+      "test/e2e/**/*.test.{t,j}s{,x}",
+      "test/integration/app-*/**/*.test.{t,j}s{,x}",
+      "test/production/app-*/**/*.test.{t,j}s{,x}",
+      "test/development/app-*/**/*.test.{t,j}s{,x}",
+      "test/development/acceptance-app/**/*.test.{t,j}s{,x}"
+    ],
+    "exclude": []
+  }
+}