Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 79 additions & 85 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
name: 'Run tests'
name: "Run tests"
on:
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * *' # Run every day at 6am UTC
- cron: "0 6 * * *" # Run every day at 6am UTC
workflow_dispatch:
inputs:
versions:
description: 'The versions of Next.js to test against (quoted and comma separated)'
description: "The versions of Next.js to test against (quoted and comma separated)"
required: false
default: 'latest'
default: "latest"

jobs:
setup:
Expand Down Expand Up @@ -59,25 +59,30 @@ jobs:

steps:
- uses: actions/checkout@v5
- name: Resolve Next.js version
id: resolve-next-version
shell: bash
run: |
RESOLVED_VERSION=$(npm view next@${{ matrix.version }} version)
echo "version=$RESOLVED_VERSION" >> $GITHUB_OUTPUT
echo "Resolved Next.js version for 'next@${{ matrix.version }}' is '$RESOLVED_VERSION'"
- name: Decide Node Version
id: decide-node-version
shell: bash
run: |
NODE_VERSION=18.x
if [ "${{ matrix.version}}" = "canary" ]; then
# this is not ideal, because we set node@20 just when explicitly using canary tag as target
# but next@canary are still on 15 major, so we can't yet use major version of resolved next version
# as condition
if [[ "${{ steps.resolve-next-version.outputs.version }}" == "16."* ]]; then
# Next@16 requires Node.js 20+
NODE_VERSION=20.x
fi
echo "version=$NODE_VERSION" >> $GITHUB_OUTPUT
echo "Node version for 'next@${{ matrix.version }}' is '$NODE_VERSION'"
- name: 'Install Node'
echo "Node version for 'next@${{ steps.resolve-next-version.outputs.version }}' is '$NODE_VERSION'"
Comment on lines +62 to +79
Copy link
Contributor Author

@pieh pieh Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is pretty much the change repeated in couple of places:

  • move Resolve Next.js version step to be before Decide Node Version
  • if resolved next version starts with 16. - use node@20, otherwise - use node@18 (and for next.js repo tests also use same logic to decide if default bundler is webpack or turbopack). We were checking if we test next@canary before because minimum node version bump landed in v15 canaries (but only was released in v16 stable)

everything else in github action workflows is just prettier auto-formatting which makes the diff messy

- name: "Install Node"
uses: actions/setup-node@v5
with:
node-version: ${{ steps.decide-node-version.outputs.version }}
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
cache: "npm"
cache-dependency-path: "**/package-lock.json"
- uses: oven-sh/setup-bun@v2
- name: setup pnpm/yarn
run: |
Expand All @@ -89,9 +94,9 @@ jobs:
with:
# Should match the `DENO_VERSION_RANGE` from https://github.com/netlify/build/blob/main/packages/edge-bundler/node/bridge.ts#L20
deno-version: v2.2.4
- name: 'Install dependencies'
- name: "Install dependencies"
run: npm ci
- name: 'Prepare Netlify CLI'
- name: "Prepare Netlify CLI"
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
run: |
Expand All @@ -104,20 +109,13 @@ jobs:
- uses: actions/cache@v4
id: playwright-cache
with:
path: '~/.cache/ms-playwright'
key: '${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.version }}'
path: "~/.cache/ms-playwright"
key: "${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.version }}"
restore-keys: |
${{ runner.os }}-playwright-
- name: Install Playwright Browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: npx playwright install --with-deps
- name: Resolve Next.js version
id: resolve-next-version
shell: bash
run: |
RESOLVED_VERSION=$(npm view next@${{ matrix.version }} version)
echo "version=$RESOLVED_VERSION" >> $GITHUB_OUTPUT
echo "Resolved Next.js version for 'next@${{ matrix.version }}' is '$RESOLVED_VERSION'"
- name: Run Playwright tests
run: npm run test:ci:e2e -- --shard=${{ matrix.shard }}/5
env:
Expand All @@ -143,31 +141,36 @@ jobs:
version: ${{ fromJson(needs.setup.outputs.matrix) }}
exclude:
- os: windows-2025
version: '13.5.1'
version: "13.5.1"
- os: windows-2025
version: '14.2.15'
version: "14.2.15"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v5
- name: Resolve Next.js version
id: resolve-next-version
shell: bash
run: |
RESOLVED_VERSION=$(npm view next@${{ matrix.version }} version)
echo "version=$RESOLVED_VERSION" >> $GITHUB_OUTPUT
echo "Resolved Next.js version for 'next@${{ matrix.version }}' is '$RESOLVED_VERSION'"
- name: Decide Node Version
id: decide-node-version
shell: bash
run: |
NODE_VERSION=18.x
if [ "${{ matrix.version}}" = "canary" ]; then
# this is not ideal, because we set node@20 just when explicitly using canary tag as target
# but next@canary are still on 15 major, so we can't yet use major version of resolved next version
# as condition
if [[ "${{ steps.resolve-next-version.outputs.version }}" == "16."* ]]; then
# Next@16 requires Node.js 20+
NODE_VERSION=20.x
fi
echo "version=$NODE_VERSION" >> $GITHUB_OUTPUT
echo "Node version for 'next@${{ matrix.version }}' is '$NODE_VERSION'"
- name: 'Install Node'
- name: "Install Node"
uses: actions/setup-node@v5
with:
node-version: ${{ steps.decide-node-version.outputs.version }}
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
cache: "npm"
cache-dependency-path: "**/package-lock.json"
- name: Prefer npm global on windows
if: runner.os == 'Windows'
# On Windows by default PATH prefers corepack bundled with Node.js
Expand All @@ -186,19 +189,12 @@ jobs:
with:
# Should match the `DENO_VERSION_RANGE` from https://github.com/netlify/edge-bundler/blob/e55f825bd985d3c92e21d1b765d71e70d5628fba/node/bridge.ts#L17
deno-version: v2.2.4
- name: 'Install dependencies'
- name: "Install dependencies"
run: npm ci
- name: 'Build'
- name: "Build"
run: npm run build
- name: 'Vendor deno helpers for integration tests'
- name: "Vendor deno helpers for integration tests"
run: node tools/vendor-deno-tools.js
- name: Resolve Next.js version
id: resolve-next-version
shell: bash
run: |
RESOLVED_VERSION=$(npm view next@${{ matrix.version }} version)
echo "version=$RESOLVED_VERSION" >> $GITHUB_OUTPUT
echo "Resolved Next.js version for 'next@${{ matrix.version }}' is '$RESOLVED_VERSION'"
- name: Compute Fixtures Cache Key
id: fixture-cache-key
# Fixtures only need to be rebuilt if either fixture or support files change,
Expand All @@ -215,14 +211,14 @@ jobs:
key:
integration-fixtures-${{ runner.os }}-${{steps.resolve-next-version.outputs.version}}-${{
steps.fixture-cache-key.outputs.key }}
- name: 'Prepare Fixtures'
- name: "Prepare Fixtures"
if: steps.cache-fixtures.outputs.cache-hit != 'true'
run: npm run pretest
env:
NEXT_VERSION: ${{ matrix.version }}
NEXT_RESOLVED_VERSION: ${{ steps.resolve-next-version.outputs.version }}
NODE_OPTIONS: --import ${{ github.workspace }}/tools/fetch-retry.mjs
- name: 'Unit and integration tests'
- name: "Unit and integration tests"
run: npm run test:ci:unit-and-integration -- --shard=${{ matrix.shard }}/8
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
Expand All @@ -241,25 +237,30 @@ jobs:
version: ${{ fromJson(needs.setup.outputs.matrix) }}
steps:
- uses: actions/checkout@v5
- name: Resolve Next.js version
id: resolve-next-version
shell: bash
run: |
RESOLVED_VERSION=$(npm view next@${{ matrix.version }} version)
echo "version=$RESOLVED_VERSION" >> $GITHUB_OUTPUT
echo "Resolved Next.js version for 'next@${{ matrix.version }}' is '$RESOLVED_VERSION'"
- name: Decide Node Version
id: decide-node-version
shell: bash
run: |
NODE_VERSION=18.x
if [ "${{ matrix.version}}" = "canary" ]; then
# this is not ideal, because we set node@20 just when explicitly using canary tag as target
# but next@canary are still on 15 major, so we can't yet use major version of resolved next version
# as condition
if [[ "${{ steps.resolve-next-version.outputs.version }}" == "16."* ]]; then
# Next@16 requires Node.js 20+
NODE_VERSION=20.x
fi
echo "version=$NODE_VERSION" >> $GITHUB_OUTPUT
echo "Node version for 'next@${{ matrix.version }}' is '$NODE_VERSION'"
- name: 'Install Node'
- name: "Install Node"
uses: actions/setup-node@v5
with:
node-version: ${{ steps.decide-node-version.outputs.version }}
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
cache: "npm"
cache-dependency-path: "**/package-lock.json"
- name: setup pnpm/yarn
run: corepack enable
shell: bash
Expand All @@ -268,25 +269,18 @@ jobs:
with:
# Should match the `DENO_VERSION_RANGE` from https://github.com/netlify/build/blob/main/packages/edge-bundler/node/bridge.ts#L20
deno-version: v2.2.4
- name: 'Install dependencies'
- name: "Install dependencies"
run: npm ci
- name: 'Build'
- name: "Build"
run: npm run build
- name: 'Prepare Netlify CLI'
- name: "Prepare Netlify CLI"
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
run: |
# Control netlify-cli as a regular dev dep but expose it globally for test fixtures to use
npm install -g "netlify-cli@$(npm list --json --depth=0 netlify-cli | jq -r ".dependencies[\"netlify-cli\"].version")"
npx netlify login
- name: Resolve Next.js version
id: resolve-next-version
shell: bash
run: |
RESOLVED_VERSION=$(npm view next@${{ matrix.version }} version)
echo "version=$RESOLVED_VERSION" >> $GITHUB_OUTPUT
echo "Resolved Next.js version for 'next@${{ matrix.version }}' is '$RESOLVED_VERSION'"
- name: 'Smoke tests'
- name: "Smoke tests"
run: npm run test:ci:smoke
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
Expand All @@ -296,36 +290,36 @@ jobs:

merge-reports:
if: always()
needs: [setup,e2e]
needs: [setup, e2e]
strategy:
fail-fast: false
matrix:
version: ${{ fromJson(needs.setup.outputs.matrix) }}

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 18
- name: Install dependencies
run: npm ci
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 18
- name: Install dependencies
run: npm ci

- name: Download blob reports from GitHub Actions Artifacts
uses: actions/download-artifact@v5
with:
path: all-blob-reports
pattern: blob-report-${{ matrix.version }}-*
merge-multiple: true
- name: Download blob reports from GitHub Actions Artifacts
uses: actions/download-artifact@v5
with:
path: all-blob-reports
pattern: blob-report-${{ matrix.version }}-*
merge-multiple: true

- name: Merge reports
run: |
npx playwright merge-reports --reporter html ./all-blob-reports
npx playwright merge-reports --reporter json ./all-blob-reports > merged_reports.json
- name: Merge reports
run: |
npx playwright merge-reports --reporter html ./all-blob-reports
npx playwright merge-reports --reporter json ./all-blob-reports > merged_reports.json

- name: Upload HTML report
uses: actions/upload-artifact@v4
with:
name: html-report-${{ matrix.version }}-attempt-${{ github.run_attempt }}
path: playwright-report
retention-days: 14
- name: Upload HTML report
uses: actions/upload-artifact@v4
with:
name: html-report-${{ matrix.version }}-attempt-${{ github.run_attempt }}
path: playwright-report
retention-days: 14
16 changes: 6 additions & 10 deletions .github/workflows/test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,12 @@ jobs:
shell: bash
run: |
NODE_VERSION=18.x
if [ "${{ matrix.version_spec.selector }}" = "canary" ]; then
# this is not ideal, because we set node@20 just when explicitly using canary tag as target
# but next@canary are still on 15 major, so we can't yet use major version of resolved next version
# as condition
if [[ "${{ matrix.version_spec.version }}" == "16."* ]]; then
# Next@16 requires Node.js 20+
NODE_VERSION=20.x
fi
echo "version=$NODE_VERSION" >> $GITHUB_OUTPUT
echo "Node version for 'next@${{ matrix.version_spec.selector }}' is '$NODE_VERSION'"
echo "Node version for 'next@${{ matrix.version_spec.version }}' is '$NODE_VERSION'"

- name: Decide default bundler
id: decide-default-bundler
Expand All @@ -132,14 +130,12 @@ jobs:
# so we need to set IS_WEBPACK_TEST, IS_TURBOPACK_TEST env vars accordingly
# to ensure tests assert behavior of the default bundler
DEFAULT_BUNDLER="webpack"
if [ "${{ matrix.version_spec.selector }}" = "canary" ]; then
# this is not ideal, because we set turbopack default just when explicitly using canary tag as target
# but next@canary are still on 15 major, so we can't yet use major version of resolved next version
# as condition
if [[ "${{ matrix.version_spec.version }}" == "16."* ]]; then
# Next@16 defaults to Turbopack
DEFAULT_BUNDLER="turbopack"
fi
echo "default_bundler=$DEFAULT_BUNDLER" >> $GITHUB_OUTPUT
echo "Default bundler for 'next@${{ matrix.version_spec.selector }}' is '$DEFAULT_BUNDLER'"
echo "Default bundler for 'next@${{ matrix.version_spec.version }}' is '$DEFAULT_BUNDLER'"

- name: setup node
uses: actions/setup-node@v5
Expand Down
4 changes: 0 additions & 4 deletions tests/fixtures/proxy-i18n-skip-normalize/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,3 @@ export async function proxy(request: NextRequest) {
return response
}
}

export const config = {
runtime: 'nodejs',
}
Comment on lines -19 to -22
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this cause build failures now:

[proxy-i18n-skip-normalize] > Build error occurred
[proxy-i18n-skip-normalize] Error: Route segment config is not allowed in Proxy file at "./proxy.ts". Proxy always runs on Node.js runtime. Learn more: https://nextjs.org/docs/messages/middleware-to-proxy

Note that this test fixture was added yesterday specifically for next@16 while there were lot of Next.js PRs still in flight and I wasn't sure what the handling will be - see #3190 (review)

6 changes: 4 additions & 2 deletions tests/utils/next-version-helpers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ export function shouldHaveAppRouterNotFoundInPrerenderManifest() {
export function shouldHaveAppRouterGlobalErrorInPrerenderManifest() {
// https://github.com/vercel/next.js/pull/82444

// this is not used in any stable version yet
return isNextCanary() && nextVersionSatisfies('>=15.5.1-canary.4')
return (
(isNextCanary() && nextVersionSatisfies('>=15.5.1-canary.4')) ||
nextVersionSatisfies('>=16.0.0')
)
Comment on lines +44 to +47
Copy link
Contributor Author

@pieh pieh Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another change that graduated from canary-only to be enabled in stable releases (this is used in our tests only to make correct assertions, it doesn't change actual support for it)

}

export function hasNodeMiddlewareSupport() {
Expand Down
Loading