Skip to content

Run Next.js repo tests #869

Run Next.js repo tests

Run Next.js repo tests #869

Workflow file for this run

name: Run Next.js repo tests
on:
workflow_call:
pull_request:
branches: [main]
schedule:
- cron: '0 3 * * *' # Run every day at 3am UTC
workflow_dispatch:
inputs:
versions:
description: 'The versions of Next.js to test against (escape-quoted and comma separated)'
required: false
# TODO(serhalp) Ideally this would simply accept bare quotes but we're having trouble
# parsing that so this will do for now.
default: "\\\"latest\\\""
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true
env:
NODE_VERSION: 18.18.0
PNPM_VERSION: 8.9.0
NEXT_REPO: vercel/next.js
NEXT_TEST_MODE: deploy
NEXT_JUNIT_TEST_REPORT: true
# In older versions of Next.js both of these need to be set to enable junit reporting
DATADOG_TRACE_NEXTJS_TEST: true
DATADOG_API_KEY: foo
TEST_CONCURRENCY: 2
NEXT_E2E_TEST_TIMEOUT: 600000
NEXT_TELEMETRY_DISABLED: 1
NEXT_SKIP_NATIVE_POSTINSTALL: 1
TURBO_API: ${{ secrets.TURBO_API }}
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: next-runtime-minimal
TURBO_TEAMID: team_netlify
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: 1d5a5c76-d445-4ae5-b694-b0d3f2e2c395
NEXT_TEST_CONTINUE_ON_ERROR: 1
next-path: next.js
runtime-path: opennextjs-netlify
GH_TOKEN: ${{ github.token }}
jobs:
setup:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'run-e2e-tests')) }}
outputs:
version_spec: ${{ steps.set-matrix.outputs.version_spec }}
group: ${{ steps.set-matrix.outputs.group }}
total: ${{ steps.set-matrix.outputs.total }}
steps:
- name: Set Next.js versions to test
id: set-matrix
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
VERSION_SELECTORS=[${{ github.event.inputs.versions }}]
echo "group=[1, 2, 3, 4]" >> $GITHUB_OUTPUT
echo "total=4" >> $GITHUB_OUTPUT
elif [ "${{ github.event_name }}" == "pull_request" ]; then
VERSION_SELECTORS=[\"latest\"]
echo "group=[1, 2, 3, 4]" >> $GITHUB_OUTPUT
echo "total=4" >> $GITHUB_OUTPUT
else
VERSION_SELECTORS=[\"latest\",\"canary\",\"14.2.15\",\"13.5.1\"]
echo "group=[1, 2, 3, 4]" >> $GITHUB_OUTPUT
echo "total=4" >> $GITHUB_OUTPUT
fi
VERSION_SPEC="["
for QUOTED_SELECTOR in $(echo $VERSION_SELECTORS | jq -c '.[]'); do
SELECTOR=$(echo $QUOTED_SELECTOR | xargs)
if [ "${VERSION_SPEC}" != "[" ]; then
VERSION_SPEC+=","
fi
VERSION=$(npm view next@$SELECTOR version)
TAG="v$VERSION"
VERSION_SPEC+="{\"selector\":\"$SELECTOR\",\"tag\":\"$TAG\",\"version\":\"$VERSION\"}"
done
VERSION_SPEC+="]"
echo "version_spec=$VERSION_SPEC" >> $GITHUB_OUTPUT
e2e:
needs: setup
# `playwright install` fails on Ubuntu 24.04+ with older versions of playwright (which 13.5.1 has)
runs-on: "${{ matrix.version_spec.selector == '13.5.1' && 'ubuntu-22.04' || 'ubuntu-latest' }}"
name: Test next@${{ matrix.version_spec.selector }} group ${{ matrix.group }}/${{ needs.setup.outputs.total }}
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
version_spec: ${{ fromJson(needs.setup.outputs.version_spec) }}
group: ${{ fromJson(needs.setup.outputs.group) }}
steps:
- name: checkout Next.js repo
uses: actions/checkout@v4
with:
repository: ${{ env.NEXT_REPO }}
path: ${{ env.next-path }}
ref: ${{ matrix.version_spec.tag }}
- name: checkout runtime repo
uses: actions/checkout@v4
with:
path: ${{ env.runtime-path }}
- name: setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: setup pnpm/yarn
run: corepack enable
- name: get pnpm store
id: pnpm-store
run: echo "PATH=$(pnpm store path --silent)" >> ${GITHUB_OUTPUT}
- name: cache pnpm deps
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-store.outputs.PATH }}
key: pnpm-store-${{ hashFiles('next.js/pnpm-lock.yaml') }}
restore-keys: |
pnpm-store-
- name: get npm cache
id: npm-cache
run: echo "PATH=$(npm config get cache)" >> ${GITHUB_OUTPUT}
- name: cache npm deps
uses: actions/cache@v4
with:
path: ${{ steps.npm-cache.outputs.PATH }}
key: node-cache-${{ hashFiles('opennextjs-netlify/package-lock.json') }}
restore-keys: |
node-cache-
- name: patch Next.js
run: |
cp ../${{ env.runtime-path }}/tests/netlify-deploy.ts test/lib/next-modes/
git apply ../${{ env.runtime-path }}/tests/e2e-utils.patch || git apply ../${{ env.runtime-path }}/tests/e2e-utils-v2.patch
working-directory: ${{ env.next-path }}
- name: install Next.js
run: pnpm install
working-directory: ${{ env.next-path }}
- name: build Next.js
run: pnpm build
working-directory: ${{ env.next-path }}
- name: install swc
run: pnpm add --workspace-root @next/swc-linux-x64-gnu@${{ matrix.version_spec.version }}
working-directory: ${{ env.next-path }}
- name: Install Deno
uses: denoland/setup-deno@v1
with:
# Should match the `DENO_VERSION_RANGE` from https://github.com/netlify/edge-bundler/blob/main/node/bridge.ts#L17
deno-version: v1.37.0
- name: install runtime
run: npm install --ignore-scripts
working-directory: ${{ env.runtime-path }}
- name: build runtime
run: npm run build
working-directory: ${{ env.runtime-path }}
- name: Prepare Netlify CLI
# Control netlify-cli as a regular dev dep but expose it globally for test fixtures to use
run: npm install -g "netlify-cli@$(npm list --json --depth=0 netlify-cli | jq -r ".dependencies[\"netlify-cli\"].version")"
working-directory: ${{ env.runtime-path }}
- name: Install Playwright Browsers
run: npx playwright install --with-deps
working-directory: ${{ env.next-path }}
- name: Get test filters
id: test-filters
run: |
# This is when the manifest version was changed
if [ `npx semver -p -r ">=14.0.4-canary.26" ${{ matrix.version_spec.version }}` ]; then
echo "filters=../opennextjs-netlify/tests/netlify-e2e.cjs" >> $GITHUB_OUTPUT
echo "skip-retry=../opennextjs-netlify/tests/e2e-skip-retry.json" >> $GITHUB_OUTPUT
else
echo "filters=../opennextjs-netlify/tests/netlify-e2e-legacy.json" >> $GITHUB_OUTPUT
echo "skip-retry=../opennextjs-netlify/tests/e2e-skip-retry-legacy.json" >> $GITHUB_OUTPUT
fi
- name: run tests
env:
NODE_ENV: production
NEXT_EXTERNAL_TESTS_FILTERS: ${{ steps.test-filters.outputs.filters }}
NEXT_TEST_SKIP_RETRY_MANIFEST: ${{ steps.test-filters.outputs.skip-retry }}
run: node run-tests.js -g ${{ matrix.group }}/${{ needs.setup.outputs.total }} -c ${TEST_CONCURRENCY} --type e2e --timings
working-directory: ${{ env.next-path }}
- name: Upload Test Results
if: success() || failure()
uses: actions/upload-artifact@v4
with:
name: test-result-${{matrix.version_spec.selector}}-${{ matrix.group }}
path: ${{ env.next-path }}/test/test-junit-report/*.xml
publish-test-results:
name: 'E2E Test Summary (${{matrix.version_spec.selector}})'
needs:
- e2e
- setup
runs-on: ubuntu-latest
permissions:
checks: write
contents: read
issues: read
if: success() || failure()
strategy:
matrix:
version_spec: ${{ fromJson(needs.setup.outputs.version_spec) }}
steps:
- name: checkout runtime repo
uses: actions/checkout@v4
- name: Install Deno
uses: denoland/setup-deno@v1
- name: Download Artifacts
uses: actions/download-artifact@v4
with:
pattern: test-result-${{matrix.version_spec.selector}}-*
path: artifacts
- name: Get and format Github issues
if: success() || failure()
run: |
gh issue list --label "Next.js e2e test failure" --json url,body > report/issues.json
deno run -A tools/deno/ghIssues2json.ts tests/test-config.json report/issues.json
- name: Publish Test Report
id: publish-test-results
if: success() || failure()
run: |
deno run -A tools/deno/junit2json.ts artifacts ${{ matrix.version_spec.tag }} > report/test-results.json
deno run -A tools/deno/generate-md.ts >> $GITHUB_STEP_SUMMARY
- name: Upload Test JSON
uses: actions/upload-artifact@v4
with:
# TODO(serhalp) Consider renaming this. It's misleading, since it's just an identifier,
# but it's formatted like a filename, and happens to be almost - but not quite - the
# actual filename.
name: ${{matrix.version_spec.selector}}-test-results.json
path: report/test-results.json