first commit
Some checks failed
Test examples / Test Examples (20) (push) Has been cancelled
Test examples / Test Examples (22) (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Trigger Release / start (push) Has been cancelled
Stale issue handler / stale (push) Has been cancelled
Update Font Data / create-pull-request (push) Has been cancelled
build-and-deploy / deploy-target (push) Has been cancelled
build-and-deploy / build (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / build-wasm (nodejs) (push) Has been cancelled
build-and-deploy / build-wasm (web) (push) Has been cancelled
build-and-deploy / Deploy preview tarball (push) Has been cancelled
build-and-deploy / Potentially publish release (push) Has been cancelled
build-and-deploy / publish-turbopack-npm-packages (push) Has been cancelled
build-and-deploy / Deploy examples (push) Has been cancelled
build-and-deploy / thank you, build (push) Has been cancelled
build-and-deploy / Upload Turbopack Bytesize metrics to Datadog (push) Has been cancelled
Rspack Next.js development integration tests / Rspack integration tests (push) Has been cancelled
Rspack Next.js production integration tests / Rspack integration tests (push) Has been cancelled
Turbopack Next.js development integration tests / Next.js integration tests (push) Has been cancelled
Turbopack Next.js production integration tests / Next.js integration tests (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack development test manifest (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack production test manifest (push) Has been cancelled
Upload bundler test manifests to areweturboyet.com / Upload test results (push) Has been cancelled
Update React / create-pull-request (push) Has been cancelled
test-e2e-project-reset-cron / reset-test-project (push) Has been cancelled
Notify about the top 15 issues/PRs/feature requests (most reacted) in the last 90 days / run (push) Has been cancelled

This commit is contained in:
Arian Tron
2026-03-10 19:37:31 +03:30
commit 61f56f997c
27684 changed files with 2784175 additions and 0 deletions

714
.github/workflows/build_and_deploy.yml vendored Normal file
View File

@@ -0,0 +1,714 @@
# Update all mentions of this name in vercel-packages when changing.
name: build-and-deploy
on:
push:
# Don't run when tags or graphite base branches are pushed
branches-ignore:
- 'graphite-base/**'
# we need the preview tarball for deploy tests
pull_request:
types: [opened, synchronize]
workflow_dispatch:
concurrency:
# Limit concurrent runs to 1 per PR,
# but allow concurrent runs on push if they potentially use different source code
group: ${{ github.event_name == 'pull_request' && format('{0}-pr-{1}', github.workflow, github.ref_name) || format('{0}-sha-{1}', github.workflow, github.sha) }}
cancel-in-progress: true
env:
NAPI_CLI_VERSION: 2.18.4
TURBO_VERSION: 2.8.11
NODE_LTS_VERSION: 20
CARGO_PROFILE_RELEASE_LTO: 'true'
TURBO_TEAM: 'vercel'
TURBO_CACHE: 'remote:rw'
# Without this environment variable, rust-lld will fail because some dependencies defaults to newer version of macOS by default.
#
# See https://doc.rust-lang.org/rustc/platform-support/apple-darwin.html#os-version for more details
MACOSX_DEPLOYMENT_TARGET: 11.0
jobs:
deploy-target:
runs-on: ubuntu-latest
# Don't trigger this job on `pull_request` events from upstream branches.
# Those would already run this job on the `push` event
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork }}
outputs:
value: ${{ steps.deploy-target.outputs.value }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- run: echo "${{ github.event.after }}"
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- name: Determine deploy target
# 'force-preview' performs a full preview build but only if acknowledged i.e. workflow_dispatch
# 'automated-preview' for pushes on branches other than 'canary' for integration testing.
# 'staging' for canary branch since that will eventually be published i.e. become the production build.
id: deploy-target
run: |
if [[ $(node ./scripts/check-is-release.js 2> /dev/null || :) == v* ]];
then
echo "value=production" >> $GITHUB_OUTPUT
elif [ '${{ github.ref }}' == 'refs/heads/canary' ]
then
echo "value=staging" >> $GITHUB_OUTPUT
elif [ '${{ github.event_name }}' == 'workflow_dispatch' ]
then
echo "value=force-preview" >> $GITHUB_OUTPUT
elif [[ $(node scripts/run-for-change.mjs --not --type docs --exec echo 'false') != 'false' ]];
then
echo "value=skipped" >> $GITHUB_OUTPUT
else
echo "value=automated-preview" >> $GITHUB_OUTPUT
fi
- name: Print deploy target
run: echo "Deploy target is '${{ steps.deploy-target.outputs.value }}'"
build:
if: ${{ needs.deploy-target.outputs.value != 'skipped' }}
needs:
- deploy-target
runs-on: ubuntu-latest
env:
NEXT_TELEMETRY_DISABLED: 1
# we build a dev binary for use in CI so skip downloading
# canary next-swc binaries in the monorepo
NEXT_SKIP_NATIVE_POSTINSTALL: 1
steps:
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- uses: actions/checkout@v4
with:
fetch-depth: 25
- id: get-store-path
run: echo STORE_PATH=$(pnpm store path) >> $GITHUB_OUTPUT
- uses: actions/cache@v4
timeout-minutes: 5
id: cache-pnpm-store
with:
path: ${{ steps.get-store-path.outputs.STORE_PATH }}
key: pnpm-store-v2-${{ hashFiles('pnpm-lock.yaml') }}
# Do not use restore-keys since it leads to indefinite growth of the cache.
- run: pnpm install
- name: Set preview version
if: ${{ contains(fromJSON('["automated-preview","force-preview"]'), needs.deploy-target.outputs.value) }}
run: |
node scripts/set-preview-version.js "${{ github.sha }}"
pnpm install --no-frozen-lockfile
- run: pnpm run build
- uses: actions/cache@v4
timeout-minutes: 5
id: cache-build
with:
path: ./*
key: ${{ github.sha }}-${{ github.run_number }}-${{ github.run_attempt}}
# Build binaries for publishing
build-native:
if: ${{ needs.deploy-target.outputs.value != 'skipped' }}
needs:
- deploy-target
defaults:
run:
shell: bash -leo pipefail {0}
strategy:
fail-fast: false
matrix:
exclude:
# only build the binaries we run automated tests against
# linux GNU x64
- settings:
target: ${{ needs.deploy-target.outputs.value == 'automated-preview' && 'aarch64-apple-darwin' }}
- settings:
target: ${{ needs.deploy-target.outputs.value == 'automated-preview' && 'aarch64-pc-windows-msvc' }}
- settings:
target: ${{ needs.deploy-target.outputs.value == 'automated-preview' && 'aarch64-unknown-linux-gnu' }}
- settings:
target: ${{ needs.deploy-target.outputs.value == 'automated-preview' && 'aarch64-unknown-linux-musl' }}
- settings:
target: ${{ needs.deploy-target.outputs.value == 'automated-preview' && 'x86_64-pc-windows-msvc' }}
- settings:
target: ${{ needs.deploy-target.outputs.value == 'automated-preview' && 'x86_64-unknown-linux-musl' }}
- settings:
target: ${{ needs.deploy-target.outputs.value == 'automated-preview' && 'x86_64-apple-darwin' }}
settings:
- host:
- 'self-hosted'
- 'macos'
- 'arm64'
target: 'x86_64-apple-darwin'
# --env-mode loose is a breaking change required with turbo 2.x since Strict mode is now the default
# TODO: we should add the relevant envs later to to switch to strict mode
build: |
npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" && corepack enable
pnpm dlx turbo@${TURBO_VERSION} run build-native-release -vvv --env-mode loose --remote-cache-timeout 90 --summarize -- --target x86_64-apple-darwin
strip -x packages/next-swc/native/next-swc.*.node
- host:
- 'self-hosted'
- 'macos'
- 'arm64'
target: 'aarch64-apple-darwin'
# --env-mode loose is a breaking change required with turbo 2.x since Strict mode is now the default
# TODO: we should add the relevant envs later to to switch to strict mode
build: |
npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" && corepack enable
pnpm dlx turbo@${TURBO_VERSION} run build-native-release -vvv --env-mode loose --remote-cache-timeout 90 --summarize -- --target aarch64-apple-darwin
strip -x packages/next-swc/native/next-swc.*.node
- host:
- 'self-hosted'
- 'windows'
- 'x64'
# --env-mode loose is a breaking change required with turbo 2.x since Strict mode is now the default
# TODO: we should add the relevant envs later to to switch to strict mode
build: |
corepack enable
npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}"
pnpm dlx turbo@${TURBO_VERSION} run build-native-release -vvv --env-mode loose --remote-cache-timeout 90 --summarize -- --target x86_64-pc-windows-msvc
target: 'x86_64-pc-windows-msvc'
- host:
- 'self-hosted'
- 'windows'
- 'x64'
target: 'aarch64-pc-windows-msvc'
# --env-mode loose is a breaking change required with turbo 2.x since Strict mode is now the default
# TODO: we should add the relevant envs later to to switch to strict mode
build: |
corepack enable
npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}"
pnpm dlx turbo@${TURBO_VERSION} run build-native-no-plugin-release -vvv --env-mode loose --remote-cache-timeout 90 --summarize -- --target aarch64-pc-windows-msvc
- host:
- 'self-hosted'
- 'linux'
- 'x64'
- 'metal'
target: 'x86_64-unknown-linux-gnu'
# [NOTE] If you want to update / modify build steps, check these things:
# - We use docker images to pin the glibc version to link against,
# even if host target is identical to the container image (i.e host: x64-linux, image: x64-linux)
# - After build `objdump -T` prints out the glibc version next-swc is linked against,
# to ensure it did not change unexpectedly if docker image, or other dependency changed
# - zig linker with portable glibc is avoided as it has known issues with static tls + node.js + multi threaded
# environment.
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:stable-2023-09-17-x64
build: |
apt update
apt install -y pkg-config xz-utils dav1d libdav1d-dev
rustup show
rustup target add x86_64-unknown-linux-gnu
npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}"
unset CC_x86_64_unknown_linux_gnu && unset CC
cd packages/next-swc
npm run build-native-release -- --target x86_64-unknown-linux-gnu
strip native/next-swc.*.node
objdump -T native/next-swc.*.node | grep GLIBC_
- host:
- 'self-hosted'
- 'linux'
- 'x64'
- 'metal'
target: 'x86_64-unknown-linux-musl'
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:stable-2023-09-17-alpine
build: |
apk update
apk del llvm
apk add --no-cache libc6-compat pkgconfig dav1d libdav1d dav1d-dev clang20-static llvm20 llvm20-dev
export PATH="/usr/lib/llvm20/bin:$PATH"
rustup show
rustup target add x86_64-unknown-linux-musl
npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}"
export RUSTFLAGS='--cfg tokio_unstable -Zshare-generics=y -Zthreads=8 -Csymbol-mangling-version=v0 -Ctarget-feature=-crt-static'
cd packages/next-swc
npm run build-native-release -- --target x86_64-unknown-linux-musl
strip native/next-swc.*.node
- host:
- 'self-hosted'
- 'linux'
- 'x64'
- 'metal'
target: 'aarch64-unknown-linux-gnu'
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:stable-2023-09-17-aarch64
build: |
apt update
apt install -y pkg-config xz-utils dav1d libdav1d-dev
export JEMALLOC_SYS_WITH_LG_PAGE=16
rustup show
rustup target add aarch64-unknown-linux-gnu
npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}"
export CC_aarch64_unknown_linux_gnu=/usr/bin/clang
export CFLAGS_aarch64_unknown_linux_gnu="--target=aarch64-unknown-linux-gnu --sysroot=/usr/aarch64-unknown-linux-gnu"
cd packages/next-swc
npm run build-native-release -- --target aarch64-unknown-linux-gnu
llvm-strip -x native/next-swc.*.node
objdump -T native/next-swc.*.node | grep GLIBC_
- host:
- 'self-hosted'
- 'linux'
- 'x64'
- 'metal'
target: 'aarch64-unknown-linux-musl'
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:stable-2023-09-17-alpine
build: |
apk update
apk del llvm
apk add --no-cache libc6-compat pkgconfig dav1d libdav1d dav1d-dev clang20-static llvm20 llvm20-dev
export PATH="/usr/lib/llvm20/bin:$PATH"
export JEMALLOC_SYS_WITH_LG_PAGE=16
npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}"
rustup show
rustup target add aarch64-unknown-linux-musl
export RUSTFLAGS='--cfg tokio_unstable -Zshare-generics=y -Zthreads=8 -Zunstable-options -Csymbol-mangling-version=v0 -Clinker-flavor=gnu-lld-cc -Clink-self-contained=+linker'
cd packages/next-swc
npm run build-native-release -- --target aarch64-unknown-linux-musl
llvm-strip -x native/next-swc.*.node
name: stable - ${{ matrix.settings.target }} - node@16
runs-on: ${{ matrix.settings.host }}
timeout-minutes: 45
steps:
# https://github.com/actions/virtual-environments/issues/1187
- name: tune linux network
run: sudo ethtool -K eth0 tx off rx off
if: ${{ matrix.settings.host == 'ubuntu-latest' }}
- name: tune linux network
run: sudo ethtool -K eth0 tx off rx off
if: ${{ matrix.settings.host == 'ubuntu-latest' }}
- name: tune windows network
run: Disable-NetAdapterChecksumOffload -Name * -TcpIPv4 -UdpIPv4 -TcpIPv6 -UdpIPv6
if: ${{ matrix.settings.host == 'windows-latest' }}
- name: tune mac network
run: sudo sysctl -w net.link.generic.system.hwcksum_tx=0 && sudo sysctl -w net.link.generic.system.hwcksum_rx=0
if: ${{ matrix.settings.host == 'macos-latest' }}
# we use checkout here instead of the build cache since
# it can fail to restore in different OS'
- uses: actions/checkout@v4
with:
# crates/next-napi-bindings/build.rs uses git-describe to find the most recent git tag. It's okay if
# this fails, but fetch with enough depth that we're likely to find a recent tag.
fetch-depth: 100
- name: Setup node
uses: actions/setup-node@v4
if: ${{ !matrix.settings.docker }}
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
# we always want to run this to set environment variables
- name: Install Rust
uses: ./.github/actions/setup-rust
with:
targets: ${{ matrix.settings.target }}
- name: normalize versions
run: node scripts/normalize-version-bump.js
- name: Setup toolchain
run: ${{ matrix.settings.setup }}
if: ${{ matrix.settings.setup }}
- name: Cache on ${{ github.ref_name }}
uses: ijjk/rust-cache@turbo-cache-v1.0.9
with:
save-if: 'true'
cache-provider: 'turbo'
shared-key: build-${{ matrix.settings.target }}-${{ hashFiles('.cargo/config.toml') }}
- name: Clear native build
run: rm -rf packages/next-swc/native
# we only need custom caching for docker builds
# as they are on an older Node.js version and have
# issues with turbo caching
- name: pull build cache
if: ${{ matrix.settings.docker }}
run: TURBO_VERSION=${TURBO_VERSION} node ./scripts/pull-turbo-cache.js ${{ matrix.settings.target }}
- name: check build exists
if: ${{ matrix.settings.docker }}
run: if [ -f packages/next-swc/native/next-swc.*.node ]; then echo "BUILD_EXISTS=yes" >> $GITHUB_OUTPUT; else echo "BUILD_EXISTS=no" >> $GITHUB_OUTPUT; fi
id: build-exists
- name: Build in docker
if: ${{ matrix.settings.docker && steps.build-exists.outputs.BUILD_EXISTS == 'no' }}
env:
# put the command in an environment variable to avoid escaping issues
DOCKER_CMD: ${{ matrix.settings.build }}
run: |
docker run -v "/var/run/docker.sock":"/var/run/docker.sock" \
-e CI -e RUST_BACKTRACE -e NAPI_CLI_VERSION -e CARGO_TERM_COLOR -e CARGO_INCREMENTAL \
-e CARGO_PROFILE_RELEASE_LTO -e CARGO_REGISTRIES_CRATES_IO_PROTOCOL -e TURBO_API \
-e TURBO_TEAM -e TURBO_TOKEN -e TURBO_VERSION -e TURBO_CACHE="remote:rw" \
-v ${{ env.HOME }}/.cargo/git:/root/.cargo/git \
-v ${{ env.HOME }}/.cargo/registry:/root/.cargo/registry \
-v ${{ github.workspace }}:/build \
-w /build \
--entrypoint=bash \
${{ matrix.settings.docker }} \
-xeo pipefail -c "$DOCKER_CMD" # these args are passed to the entrypoint (bash)
- name: cache build
if: ${{ matrix.settings.docker && steps.build-exists.outputs.BUILD_EXISTS == 'no' }}
run: pnpm dlx turbo@${TURBO_VERSION} run cache-build-native --force -- ${{ matrix.settings.target }}
- name: 'Build'
run: ${{ matrix.settings.build }}
if: ${{ !matrix.settings.docker }}
- name: 'check build cache status'
id: check-did-build
run: if [[ ! -z $(ls packages/next-swc/native) ]]; then echo "DID_BUILD=true" >> $GITHUB_OUTPUT; fi
# Try to upload metrics for Turbopack to datadog's CI pipeline execution
- name: 'Collect turbopack build metrics'
id: check-turbopack-bytesize
if: ${{ steps.check-did-build.outputs.DID_BUILD == 'true' }}
continue-on-error: true
run: |
mkdir -p ./turbopack-bin-size
shopt -s nullglob
for filename in packages/next-swc/native/next-swc.*.node; do
# Strip out filename to extract target triple
export FILENAME=$(basename ${filename})
export FILENAME=${FILENAME#*.}
export FILENAME=${FILENAME%.node}
export BYTESIZE=$(wc -c < $filename | xargs)
echo "Reporting $FILENAME:$BYTESIZE for Turbopack bytesize"
echo "turbopack.bytesize.$FILENAME:$BYTESIZE" > ./turbopack-bin-size/${{ matrix.settings.target }}
done
- name: Upload turbopack bytesize artifact
if: ${{ steps.check-did-build.outputs.DID_BUILD == 'true' }}
uses: actions/upload-artifact@v4
with:
name: turbopack-bytesize-${{ matrix.settings.target }}
path: turbopack-bin-size/*
- name: Upload swc artifact
uses: actions/upload-artifact@v4
with:
name: next-swc-binaries-${{ matrix.settings.target }}
path: packages/next-swc/native/next-swc.*.node
- name: Upload turbo summary artifact
uses: actions/upload-artifact@v4
with:
name: turbo-run-summary-${{ matrix.settings.target }}
path: .turbo/runs
build-wasm:
if: ${{ needs.deploy-target.outputs.value != 'skipped' }}
needs:
- deploy-target
strategy:
matrix:
target: [web, nodejs]
runs-on:
- 'self-hosted'
- 'linux'
- 'x64'
- 'metal'
steps:
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- run: corepack enable
- name: Install Rust
uses: ./.github/actions/setup-rust
with:
targets: wasm32-unknown-unknown
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: normalize versions
run: node scripts/normalize-version-bump.js
- name: Build
# --env-mode loose is a breaking change required with turbo 2.x since Strict mode is now the default
# TODO: we should add the relevant envs later to to switch to strict mode
run: pnpm dlx turbo@${TURBO_VERSION} run build-wasm -vvv --env-mode loose --remote-cache-timeout 90 --summarize -- --target ${{ matrix.target }}
- name: Add target to folder name
run: '[[ -d "crates/wasm/pkg" ]] && mv crates/wasm/pkg crates/wasm/pkg-${{ matrix.target }} || ls crates/wasm'
- name: Upload turbo summary artifact
uses: actions/upload-artifact@v4
with:
name: turbo-run-summary-wasm-${{matrix.target}}
path: .turbo/runs
- name: Upload swc artifact
uses: actions/upload-artifact@v4
with:
name: wasm-binaries-${{matrix.target}}
path: crates/wasm/pkg-*
deploy-tarball:
if: ${{ needs.deploy-target.outputs.value != 'production' }}
name: Deploy preview tarball
runs-on: ubuntu-latest
needs:
- deploy-target
- build
- build-wasm
- build-native
steps:
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
# https://github.com/actions/virtual-environments/issues/1187
- name: tune linux network
run: sudo ethtool -K eth0 tx off rx off
- uses: actions/cache@v4
timeout-minutes: 5
id: restore-build
with:
path: ./*
# Cache includes repo checkout which is required for later scripts
fail-on-cache-miss: true
key: ${{ github.sha }}-${{ github.run_number }}-${{ github.run_attempt }}
restore-keys: |
${{ github.sha }}-${{ github.run_number }}
${{ github.sha }}-${{ github.run_number }}-${{ github.run_attempt}}
- uses: actions/download-artifact@v4
with:
pattern: next-swc-binaries-*
merge-multiple: true
path: packages/next-swc/native
- uses: actions/download-artifact@v4
with:
pattern: wasm-binaries-*
merge-multiple: true
path: crates/wasm
- name: Create tarballs
# github.event.after is available on push and pull_request#synchronize events.
# For workflow_dispatch events, github.sha is the head commit.
run: node scripts/create-preview-tarballs.js "${{ github.event.after || github.sha }}" "${{ runner.temp }}/preview-tarballs"
- name: Upload tarballs
uses: actions/upload-artifact@v4
with:
# Update all mentions of this name in vercel-packages when changing.
name: preview-tarballs
path: ${{ runner.temp }}/preview-tarballs/*
publishRelease:
if: ${{ needs.deploy-target.outputs.value == 'production' }}
name: Potentially publish release
runs-on: ubuntu-latest
needs:
- deploy-target
- build
- build-wasm
- build-native
permissions:
contents: write
id-token: write
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN_ELEVATED }}
steps:
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
# https://github.com/actions/virtual-environments/issues/1187
- name: tune linux network
run: sudo ethtool -K eth0 tx off rx off
- uses: actions/cache@v4
timeout-minutes: 5
id: restore-build
with:
path: ./*
# Cache includes repo checkout which is required for later scripts
fail-on-cache-miss: true
key: ${{ github.sha }}-${{ github.run_number }}-${{ github.run_attempt }}
restore-keys: |
${{ github.sha }}-${{ github.run_number }}
${{ github.sha }}-${{ github.run_number }}-${{ github.run_attempt}}
- uses: actions/download-artifact@v4
with:
pattern: next-swc-binaries-*
merge-multiple: true
path: packages/next-swc/native
- uses: actions/download-artifact@v4
with:
pattern: wasm-binaries-*
merge-multiple: true
path: crates/wasm
- run: npm i -g npm@10.4.0 # need latest version for provenance (pinning to avoid bugs)
- run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
- run: ./scripts/publish-native.js
- run: ./scripts/publish-release.js
env:
RELEASE_BOT_GITHUB_TOKEN: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}
publish-turbopack-npm-packages:
# Matches the commit message written by turbopack/xtask/src/publish.rs:377
if: "${{(github.ref == 'refs/heads/canary') && startsWith(github.event.head_commit.message, 'chore: release turbopack npm packages')}}"
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- uses: ./.github/actions/setup-rust
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
- run: pnpm install --frozen-lockfile
- name: Build packages
run: pnpx turbo@canary run build --only --filter='./turbopack/packages/*'
- name: Write NPM_TOKEN
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN_ELEVATED }}" > ~/.npmrc
- name: Publish
run: cargo xtask workspace --publish
deployExamples:
if: ${{ needs.deploy-target.outputs.value != 'automated-preview' }}
name: Deploy examples
runs-on: ubuntu-latest
needs: [build, deploy-target]
steps:
- run: echo '${{ needs.deploy-target.outputs.value }}'
- uses: actions/checkout@v4
with:
fetch-depth: 25
- name: Install Vercel CLI
run: npm i -g vercel@latest
- name: Deploy preview examples
if: ${{ needs.deploy-target.outputs.value != 'production' }}
run: ./scripts/deploy-examples.sh
env:
VERCEL_API_TOKEN: ${{ secrets.VERCEL_API_TOKEN }}
DEPLOY_ENVIRONMENT: preview
- name: Deploy production examples
if: ${{ needs.deploy-target.outputs.value == 'production' }}
run: ./scripts/deploy-examples.sh
env:
VERCEL_API_TOKEN: ${{ secrets.VERCEL_API_TOKEN }}
DEPLOY_ENVIRONMENT: production
buildPassed:
needs: ['deploy-target', 'build', 'build-wasm', 'build-native']
if: ${{ always() && needs.deploy-target.outputs.value != '' }}
# Coupled with retry logic in retry_test.yml
name: thank you, build
runs-on: ubuntu-latest
steps:
- run: exit 1
if: ${{ always() && (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) }}
upload_turbopack_bytesize:
if: ${{ needs.deploy-target.outputs.value != 'automated-preview'}}
name: Upload Turbopack Bytesize metrics to Datadog
runs-on: ubuntu-latest
needs: [build-native, deploy-target]
env:
DATADOG_API_KEY: ${{ secrets.DATA_DOG_API_KEY }}
steps:
- name: Collect bytesize metrics
uses: actions/download-artifact@v4
with:
pattern: turbopack-bytesize-*
merge-multiple: true
path: turbopack-bin-size
- name: Upload to Datadog
run: |
ls -al turbopack-bin-size
for filename in turbopack-bin-size/*; do
export BYTESIZE+=" --metrics $(cat $filename)"
done
echo "Reporting $BYTESIZE"
npx @datadog/datadog-ci@2.23.1 metric --no-fail --level pipeline $BYTESIZE

1204
.github/workflows/build_and_test.yml vendored Normal file

File diff suppressed because it is too large Load Diff

394
.github/workflows/build_reusable.yml vendored Normal file
View File

@@ -0,0 +1,394 @@
name: Build Reusable
on:
workflow_call:
inputs:
afterBuild:
required: false
description: 'additional steps to run'
type: string
# Toggles the mold linker. The default linker is much slower and can run into OOMs.
# However, custom linkers won't work for wasm.
mold:
required: false
description: 'whether to use the mold linker'
type: string
skipInstallBuild:
required: false
description: 'whether to skip pnpm install && pnpm build'
type: string
skipNativeBuild:
required: false
description: 'whether to skip building native modules'
type: string
skipNativeInstall:
required: false
description: 'whether to skip native postinstall script'
type: string
default: 'yes'
uploadAnalyzerArtifacts:
required: false
description: 'whether to upload analyzer artifacts'
type: string
nodeVersion:
required: false
description: 'version of Node.js to use'
type: string
needsRust:
required: false
description: 'if rust is needed'
type: string
needsNextest:
required: false
description: 'if nextest rust dep is needed'
type: string
rustBuildProfile:
required: false
description: 'The profile to use for the build, default is `release-with-assertions`, also supports `` for debug and `release` for normal release'
type: string
default: 'release-with-assertions'
uploadSwcArtifact:
required: false
description: 'if swc artifact needs uploading'
type: string
rustCacheKey:
required: false
description: 'rustCacheKey to cache shared target assets'
type: string
stepName:
required: true
description: 'name of the step, to be used for the upload artifact unique key '
type: string
timeout_minutes:
description: 'Timeout in minutes'
required: false
type: number
default: 30
runs_on_labels:
description: 'List of runner labels'
required: false
type: string
default: '["self-hosted", "linux", "x64", "metal"]'
buildNativeTarget:
description: 'Target for build-native step'
required: false
type: string
default: 'x86_64-unknown-linux-gnu'
overrideProxyAddress:
description: Override the proxy address to use for the test
required: false
type: string
default: ''
testTimingsArtifact:
description: 'Name of an uploaded artifact containing test-timings.json. When set, download it instead of fetching via turbo.'
required: false
type: string
default: ''
browser:
description: 'Browser to use for tests'
required: false
type: string
default: 'chromium'
env:
NAPI_CLI_VERSION: 2.18.4
TURBO_VERSION: 2.8.11
NODE_LTS_VERSION: 20.9.0
# run-tests.js reads `TEST_CONCURRENCY` if no explicit `--concurrency` or `-c`
# argument is provided
TEST_CONCURRENCY: 8
# disable backtrace for test snapshots
RUST_BACKTRACE: 0
TURBO_TEAM: 'vtest314-next-e2e-tests'
TURBO_CACHE: 'remote:rw'
TURBO_TOKEN: ${{ secrets.TURBO_REMOTE_CACHE_TOKEN }}
NEXT_TELEMETRY_DISABLED: 1
# allow not skipping install-native postinstall script if we don't have a binary available already
NEXT_SKIP_NATIVE_POSTINSTALL: ${{ inputs.skipNativeInstall == 'yes' && '1' || '' }}
DATADOG_API_KEY: ${{ secrets.DATA_DOG_API_KEY }}
NEXT_JUNIT_TEST_REPORT: 'true'
DD_ENV: 'ci'
# Vercel KV Store for test timings
KV_REST_API_URL: ${{ secrets.KV_REST_API_URL }}
KV_REST_API_TOKEN: ${{ secrets.KV_REST_API_TOKEN }}
NEXT_TEST_JOB: 1
VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
VERCEL_TEST_TEAM: vtest314-next-e2e-tests
VERCEL_ADAPTER_TEST_TOKEN: ${{ secrets.VERCEL_ADAPTER_TEST_TOKEN }}
VERCEL_ADAPTER_TEST_TEAM: vtest314-next-adapter-e2e-tests
VERCEL_TURBOPACK_TEST_TOKEN: ${{ secrets.VERCEL_TURBOPACK_TEST_TOKEN }}
VERCEL_TURBOPACK_TEST_TEAM: vtest314-next-turbo-e2e-tests
NEXT_TEST_PREFER_OFFLINE: 1
NEXT_CI_RUNNER: ${{ inputs.runs_on_labels }}
NEXT_TEST_PROXY_ADDRESS: ${{ inputs.overrideProxyAddress || '' }}
# defaults to 256, but we run a lot of tests in parallel, so the limit should be lower
NEXT_TURBOPACK_IO_CONCURRENCY: 64
# Disable warnings from baseline-browser-mapping
# https://github.com/web-platform-dx/baseline-browser-mapping/blob/ec8136ae9e034b332fab991d63a340d2e13b8afc/README.md?plain=1#L34
BASELINE_BROWSER_MAPPING_IGNORE_OLD_DATA: 1
jobs:
build:
timeout-minutes: ${{ inputs.timeout_minutes }}
runs-on: ${{ fromJson(inputs.runs_on_labels) }}
defaults:
run:
shell: bash -leo pipefail {0}
outputs:
input_step_key: ${{ steps.var.outputs.input_step_key }}
steps:
# enforce consistent line endings for git on windows
- name: Configure git to use LF endings
if: ${{ contains(fromJson(inputs.runs_on_labels), 'windows') }}
run: |
git config --global core.autocrlf false
git config --global core.eol lf
shell: bash
- name: Check if fnm is installed
id: check-fnm
run: |
if [ -x "$(command -v fnm)" ]; then
echo "fnm found."
echo "found=true" >> $GITHUB_OUTPUT
else
echo "fnm not found."
echo "found=false" >> $GITHUB_OUTPUT
fi
- name: Install fnm
if: steps.check-fnm.outputs.found != 'true'
run: |
curl -fsSL https://fnm.vercel.app/install | bash
export PATH="/home/runner/.local/share/fnm:$PATH"
echo "/home/runner/.local/share/fnm" >> $GITHUB_PATH
fnm env --json | jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' | xargs -I {} echo "{}" >> $GITHUB_ENV
- name: Normalize input step names into path key
uses: actions/github-script@v7
id: var
with:
script: |
core.setOutput('input_step_key', '${{ inputs.stepName }}'.toLowerCase().replaceAll(/[/.]/g, '-').trim('-'));
- name: Use Node.js ${{ inputs.nodeVersion || env.NODE_LTS_VERSION }} for default shell
run: |
node --version || true
which node || true
# TODO: May be sufficient to just set `$FNM_MULTISHELL_PATH/bin` from `fnm env --json` into GITHUB_PATH
fnm_env=$(fnm env)
# Debug what we're about to eval
echo "$fnm_env"
eval "$fnm_env"
fnm use --install-if-missing ${{ inputs.nodeVersion || env.NODE_LTS_VERSION }}
fnm default ${{ inputs.nodeVersion || env.NODE_LTS_VERSION }}
node --version
which node
NODE_SHELL_PATH=$(dirname "$(which node)")
echo "Adding '$NODE_SHELL_PATH' to GITHUB_PATH"
echo "$NODE_SHELL_PATH" >> "$GITHUB_PATH"
# Debug used Node.js version in a separate step to ensure
# the Node.js version is set for the entire job
- name: Verify Node.js version
run: |
which node
node --version
- name: Prepare corepack
if: ${{ contains(fromJson(inputs.runs_on_labels), 'ubuntu-latest') }}
run: |
npm i -g corepack@0.31
- run: corepack enable
- run: pwd
- run: rm -rf .git
- uses: actions/checkout@v4
with:
fetch-depth: 25
# Cache pnpm store on GitHub-hosted runners (self-hosted runners have their own persistent storage)
- name: Get pnpm store directory
if: ${{ runner.environment == 'github-hosted' }}
id: get-store-path
run: echo STORE_PATH=$(pnpm store path) >> $GITHUB_OUTPUT
- name: Cache pnpm store
if: ${{ runner.environment == 'github-hosted' }}
uses: actions/cache@v4
timeout-minutes: 5
id: cache-pnpm-store
with:
path: ${{ steps.get-store-path.outputs.STORE_PATH }}
key: pnpm-store-v2-${{ hashFiles('pnpm-lock.yaml') }}
# Do not use restore-keys since it leads to indefinite growth of the cache.
# local action -> needs to run after checkout
- name: Install Rust
uses: ./.github/actions/setup-rust
if: ${{ inputs.skipNativeBuild != 'yes' || inputs.needsNextest == 'yes' || inputs.needsRust == 'yes' }}
- name: 'Install mold linker'
if: ${{ inputs.mold == 'yes' }}
run: |
sudo apt update
sudo apt install -y mold
echo RUSTFLAGS=${RUSTFLAGS}\ -C\ link-arg=-fuse-ld=mold >> $GITHUB_ENV
- name: Install nextest
if: ${{ inputs.needsNextest == 'yes' }}
uses: taiki-e/install-action@nextest
- run: rustc --version
if: ${{ inputs.skipNativeBuild != 'yes' || inputs.needsNextest == 'yes' || inputs.needsRust == 'yes' }}
- run: corepack prepare --activate yarn@1.22.19 && npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}"
- name: Cache on ${{ github.ref_name }}
uses: ijjk/rust-cache@turbo-cache-v1.0.9
if: ${{ inputs.rustCacheKey }}
with:
cache-provider: 'turbo'
save-if: ${{ github.ref_name == 'canary' }}
shared-key: ${{ inputs.rustCacheKey }}-${{ inputs.buildNativeTarget }}-build-${{ inputs.rustBuildProfile }}-${{ hashFiles('.cargo/config.toml') }}
# clean up any previous artifacts to avoid hitting disk space limits
- run: git clean -xdf && rm -rf /tmp/next-repo-*; rm -rf /tmp/next-install-* /tmp/yarn-* /tmp/ncc-cache target
# Configure a git user so that Create Next App can initialize git repos during integration tests.
- name: Set CI git user
run: |
git config --global user.name "vercel-ci-bot"
git config --global user.email "infra+ci@vercel.com"
- run: cargo clean
if: ${{ inputs.skipNativeBuild != 'yes' || inputs.needsNextest == 'yes' || inputs.needsRust == 'yes' }}
# normalize versions before build-native for better cache hits
- run: node scripts/normalize-version-bump.js
name: normalize versions
- run: pnpm dlx turbo@${TURBO_VERSION} run build-native-${{ inputs.rustBuildProfile }} -v --env-mode loose --remote-cache-timeout 90 --summarize -- --target ${{ inputs.buildNativeTarget }}
if: ${{ inputs.skipNativeBuild != 'yes' }}
- name: Upload next-swc artifact
if: ${{ inputs.uploadSwcArtifact == 'yes' }}
uses: actions/upload-artifact@v4
with:
name: next-swc-binary
path: packages/next-swc/native/next-swc.linux-x64-gnu.node
# undo normalize version changes for install/build
- run: git checkout .
if: ${{ inputs.skipInstallBuild != 'yes' }}
- run: pnpm install
if: ${{ inputs.skipInstallBuild != 'yes' }}
- name: Install node-file-trace test dependencies
if: ${{ inputs.needsNextest == 'yes' }}
working-directory: turbopack/crates/turbopack-tracing/tests/node-file-trace
run: pnpm install -r --side-effects-cache false
- run: ANALYZE=1 pnpm build
if: ${{ inputs.skipInstallBuild != 'yes' }}
# Some packages e.g. `devlow-bench` depend on `pnpm build` to generate
# their `dist` directory. The first run of `pnpm install` will generate
# warnings because these don't exist yet.
#
# We need to run `pnpm install` a _second_ time to fix this. Fortunately,
# this second run is very fast and cheap.
- name: Re-run pnpm install to link built packages into node_modules/.bin
run: pnpm install
if: ${{ inputs.skipInstallBuild != 'yes' }}
- run: pnpm playwright install --with-deps ${{ inputs.browser }}
if: ${{ inputs.skipInstallBuild != 'yes' }}
- name: Download pre-built test timings
if: ${{ inputs.testTimingsArtifact != '' }}
uses: actions/download-artifact@v4
with:
name: ${{ inputs.testTimingsArtifact }}
- name: Verify test timings
if: ${{ inputs.testTimingsArtifact != '' }}
run: |
if [ ! -f test-timings.json ]; then
echo "::error::test-timings.json not found"
exit 1
fi
echo "Test timings loaded ($(wc -c < test-timings.json) bytes)"
- name: Fetch test timings via turbo
if: ${{ inputs.testTimingsArtifact == '' }}
run: pnpm dlx turbo@${TURBO_VERSION} run get-test-timings -- --build ${{ github.sha }}
- run: ${{ inputs.afterBuild }}
# defaults.run.shell sets a stronger options (`-leo pipefail`)
# Set this back to github action's weaker defaults:
# https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell
#
# We must use a login shell: fnm installation may modify the `.profile`
shell: bash -le {0}
timeout-minutes: ${{ inputs.timeout_minutes }}
# This file messes up the tests because it influences the build root autodetection.
# Jest has a global cache, so PRs that poison the cache can bring down CI
- name: Clean up stray files
if: ${{ always() }}
run: rm -f /tmp/package-lock.json
- name: Upload Turborepo summary
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: turbo-run-summary-${{ steps.var.outputs.input_step_key }}
path: .turbo/runs
if-no-files-found: ignore
- name: Upload bundle analyzer artifacts
uses: actions/upload-artifact@v4
if: ${{ inputs.uploadAnalyzerArtifacts == 'yes' }}
with:
name: webpack bundle analysis stats-${{ steps.var.outputs.input_step_key }}
path: packages/next/dist/compiled/next-server/report.*.html
- name: Upload test report to datadog
if: ${{ inputs.afterBuild && always() && !github.event.pull_request.head.repo.fork }}
run: |
# Add a `test.type` tag to distinguish between turbopack and next.js runs
# Add a `nextjs.test_session.name` tag to help identify the job
if [ -d ./test/test-junit-report ]; then
pnpm dlx @datadog/datadog-ci@2.45.1 junit upload \
--service nextjs \
--tags test.type:nextjs \
--tags test_session.name:"${{ inputs.stepName }}" \
--tags runner.name:"${{ runner.name }}" \
./test/test-junit-report
fi
if [ -d ./test/turbopack-test-junit-report ]; then
pnpm dlx @datadog/datadog-ci@2.45.1 junit upload \
--service nextjs \
--tags test.type:turbopack \
--tags test_session.name:"${{ inputs.stepName }}" \
--tags runner.name:"${{ runner.name }}" \
./test/turbopack-test-junit-report
fi
- name: Upload Playwright Snapshots
uses: actions/upload-artifact@v4
if: ${{ inputs.afterBuild && always() }}
with:
name: test-playwright-snapshots-${{ steps.var.outputs.input_step_key }}
path: |
test/traces
if-no-files-found: ignore

47
.github/workflows/code_freeze.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
on:
workflow_dispatch:
inputs:
type:
description: Enable/disable code freeze
required: true
type: choice
options:
- enable
- disable
secrets:
CODE_FREEZE_TOKEN:
required: true
name: Code Freeze
env:
NAPI_CLI_VERSION: 2.18.4
TURBO_VERSION: 2.8.11
NODE_LTS_VERSION: 20
jobs:
start:
runs-on: ubuntu-latest
environment: release-${{ github.event.inputs.releaseType }}
steps:
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- run: git clone https://github.com/vercel/next.js.git --depth=1 .
# https://github.com/actions/virtual-environments/issues/1187
- name: tune linux network
run: sudo ethtool -K eth0 tx off rx off
- run: node ./scripts/code-freeze.js --type ${{ github.event.inputs.type }}
env:
CODE_FREEZE_TOKEN: ${{ secrets.CODE_FREEZE_TOKEN }}

View File

@@ -0,0 +1,75 @@
on:
workflow_dispatch:
inputs:
branchName:
description: name of branch to create (next-15-4)
required: true
type: string
tagName:
description: Tag to start the branch from (v15.4.1)
type: string
required: true
secrets:
RELEASE_BOT_GITHUB_TOKEN:
required: true
name: Create Release Branch
env:
NAPI_CLI_VERSION: 2.18.4
TURBO_VERSION: 2.8.11
NODE_LTS_VERSION: 20
jobs:
start:
if: github.repository_owner == 'vercel'
runs-on: ubuntu-latest
env:
NEXT_TELEMETRY_DISABLED: 1
# we build a dev binary for use in CI so skip downloading
# canary next-swc binaries in the monorepo
NEXT_SKIP_NATIVE_POSTINSTALL: 1
steps:
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20
check-latest: true
- name: Clone Next.js repository
run: git clone https://github.com/vercel/next.js.git --depth=25 --single-branch --branch ${GITHUB_REF_NAME:-canary} .
- name: Check token
run: gh auth status
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}
# https://github.com/actions/virtual-environments/issues/1187
- name: tune linux network
run: sudo ethtool -K eth0 tx off rx off
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
pnpm --version
- id: get-store-path
run: echo STORE_PATH=$(pnpm store path) >> $GITHUB_OUTPUT
- uses: actions/cache@v4
timeout-minutes: 5
id: cache-pnpm-store
with:
path: ${{ steps.get-store-path.outputs.STORE_PATH }}
key: pnpm-store-v2-${{ hashFiles('pnpm-lock.yaml') }}
# Do not use restore-keys since it leads to indefinite growth of the cache.
- run: pnpm install
- run: node ./scripts/create-release-branch.js --branch-name ${{ github.event.inputs.branchName }} --tag-name ${{ github.event.inputs.tagName }}
env:
RELEASE_BOT_GITHUB_TOKEN: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}

54
.github/workflows/deploy_docs.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: docs-deploy
on:
pull_request:
paths:
- 'apps/docs/**'
types: [opened, synchronize]
permissions:
contents: read
pull-requests: write
env:
NODE_LTS_VERSION: 20
jobs:
deploy:
name: Deploy docs to Vercel
runs-on: ubuntu-latest
env:
VERCEL_API_TOKEN: ${{ secrets.VERCEL_API_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.sha }}
fetch-depth: 25
- name: Install Vercel CLI
run: npm i -g vercel@latest
- name: Deploy docs
id: deploy
run: |
URL=$(bash scripts/deploy-docs.sh)
echo "url=$URL" >> $GITHUB_OUTPUT
echo "Deployed to $URL"
env:
DEPLOY_ENVIRONMENT: preview
# - name: Comment on PR with deployment URL
# if: ${{ github.event_name == 'pull_request' }}
# uses: actions/github-script@v7
# with:
# script: |
# const pr = github.context.payload.pull_request?.number
# const url = '${{ steps.deploy.outputs.url }}'
# if (!pr || !url) return
# await github.rest.issues.createComment({
# owner: context.repo.owner,
# repo: context.repo.repo,
# issue_number: pr,
# body: `Docs deployed: ${url}`
# })

View File

@@ -0,0 +1,51 @@
# Avoid running the full CI on mid-stack PRs: https://graphite.dev/docs/stacking-and-ci
#
# We still run some high-signal low-cost jobs (e.g. lint, unit tests) on these mid-stack PRs, just
# not anything slow (e.g. integration tests).
#
# Because we don't use Graphite's CI batching, full CI will still run on every PR individually
# before it merges. The goal is just to avoid wasting CI capacity when frequently rebasing large
# stacks.
#
# This can by bypassed by labeling a PR with 'CI Bypass Graphite Optimization', and manually
# re-running CI.
name: Graphite CI Optimizer
on:
workflow_call:
outputs:
skip:
description: "'true' if expensive CI checks should be skipped, 'false' otherwise."
value: ${{ jobs.optimize-ci.outputs.skip }}
secrets:
GRAPHITE_TOKEN:
description: 'The Graphite CI optimization secret'
# secrets are not available in forks, check-skip will just fail-open with a warning
required: false
env:
# FYI, if you add this label, you must *push* to the repository again to trigger a new event. Just
# re-running in the GitHub actions UI won't work, as it will re-use the old event with the old
# labels.
HAS_BYPASS_LABEL: |-
${{
github.event_name == 'pull_request' &&
contains(github.event.pull_request.labels.*.name, 'CI Bypass Graphite Optimization')
}}
jobs:
optimize-ci:
name: Graphite CI Optimizer
runs-on: ubuntu-latest
outputs:
skip: ${{ env.HAS_BYPASS_LABEL == 'false' && steps.check-skip.outputs.skip == 'true' }}
steps:
- name: Optimize CI
id: check-skip
uses: withgraphite/graphite-ci-action@main
with:
graphite_token: ${{ secrets.GRAPHITE_TOKEN }}
- name: Debug Output
run: |
echo 'github.event_name: ${{ github.event_name }}'
echo "secrets.GRAPHITE_TOKEN != '': ${{ secrets.GRAPHITE_TOKEN != '' }}"
echo 'env.HAS_BYPASS_LABEL: ${{ env.HAS_BYPASS_LABEL }}'
echo 'steps.check-skip.outputs.skip: ${{ steps.check-skip.outputs.skip }}'

View File

@@ -0,0 +1,170 @@
name: Integration Tests Reusable
on:
workflow_call:
inputs:
name:
description: A unique identifer used for uploaded assets
type: string
test_type:
description: '"development" or "production"'
required: true
type: string
run_before_test:
description: >
Bash code to run before executing the test (e.g. setting environment
variables). Runs in the same step as the test.
type: string
default: ''
e2e_groups:
description: >
Size of the matrix used for running e2e tests (controls parallelism)
type: number
default: 6
integration_groups:
description: >
Size of the matrix used for running legacy integration tests (controls
parallelism)
type: number
default: 6
e2e_timeout_minutes:
type: number
default: 30
integration_timeout_minutes:
type: number
default: 30
num_retries:
type: number
default: 2
jobs:
# First, build Next.js to execute across tests.
build-next:
name: build-next
uses: ./.github/workflows/build_reusable.yml
with:
skipNativeBuild: yes
stepName: build-next
secrets: inherit
build-native:
name: build-native
uses: ./.github/workflows/build_reusable.yml
with:
skipInstallBuild: yes
stepName: build-native
secrets: inherit
generate-matrices:
runs-on: [self-hosted, linux, x64, metal]
steps:
- id: out
run: |
printf 'e2e=[%s]\n' \
"$(seq -s, 1 ${{ inputs.e2e_groups }})" | \
tee -a "$GITHUB_OUTPUT"
printf 'integration=[%s]\n' \
"$(seq -s, 1 ${{ inputs.integration_groups }})" | \
tee -a "$GITHUB_OUTPUT"
outputs:
e2e: ${{ steps.out.outputs.e2e }}
integration: ${{ steps.out.outputs.integration }}
# Actual test scheduling. These jobs mimic the normal test jobs.
# Refer build_and_test.yml for more details.
#
# We run tests in two parts. Legacy integration tests are run separately:
# https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#test-types-in-nextjs
test-e2e:
# Name must match `integrationTestJobs` in
# `./.github/actions/next-integration-stat`
name: >-
Next.js integration test (E2E and ${{ inputs.test_type }})
(${{ matrix.group }}/${{ inputs.e2e_groups }})
needs: [build-next, build-native, generate-matrices]
strategy:
fail-fast: false
matrix:
group: ${{ fromJSON(needs.generate-matrices.outputs.e2e) }}
uses: ./.github/workflows/build_reusable.yml
with:
afterBuild: |
# e2e and ${{ inputs.test_type }} tests with `node run-tests.js`
export NEXT_TEST_MODE=${{
inputs.test_type == 'development' && 'dev' || 'start'
}}
export NEXT_TEST_EMIT_ALL_OUTPUT=1
${{ inputs.run_before_test }}
node run-tests.js \
--group ${{ matrix.group }}/${{ inputs.e2e_groups }} \
--retries ${{ inputs.num_retries }} \
--type ${{ inputs.test_type }}
stepName: test-${{ inputs.name }}-${{ matrix.group }}
timeout_minutes: ${{ inputs.e2e_timeout_minutes }}
secrets: inherit
test-integration:
# Name must match `integrationTestJobs` in
# `./.github/actions/next-integration-stat`
name: >-
Next.js integration test (Integration)
(${{ matrix.group }}/${{ inputs.e2e_groups }})
needs: [build-next, build-native, generate-matrices]
strategy:
fail-fast: false
matrix:
group: ${{ fromJSON(needs.generate-matrices.outputs.integration) }}
uses: ./.github/workflows/build_reusable.yml
with:
nodeVersion: 20.9.0
afterBuild: |
# legacy integration tests with `node run-tests.js`
# HACK: Despite the name, these environment variables are just used to
# gate tests, so they're applicable to both turbopack and rspack tests
export ${{
inputs.test_type == 'development' &&
'TURBOPACK_DEV=1' ||
'TURBOPACK_BUILD=1'
}}
export NEXT_TEST_EMIT_ALL_OUTPUT=1
${{ inputs.run_before_test }}
node run-tests.js \
--group ${{ matrix.group }}/${{ inputs.integration_groups }} \
--retries ${{ inputs.num_retries }} \
--type integration
stepName: test-${{ inputs.name }}-integration-${{ matrix.group }}
timeout_minutes: ${{ inputs.integration_timeout_minutes }}
secrets: inherit
# Collect integration test results from execute_tests,
# Store it as github artifact for next step to consume.
collect_nextjs_development_integration_stat:
needs: [test-e2e, test-integration]
name: Next.js integration test development status report
runs-on: [self-hosted, linux, x64, metal]
if: always()
permissions:
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Collect integration test stat
uses: ./.github/actions/next-integration-stat
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Store artifacts
uses: actions/upload-artifact@v4
with:
name: test-results-${{ inputs.name }}
path: |
nextjs-test-results.json
failed-test-path-list.json
passed-test-path-list.json

29
.github/workflows/issue_lock.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: 'Lock Threads'
on:
schedule:
# This runs twice a day: https://crontab.guru/#0_0,12_*_*_*
- cron: '0 0,12 * * *'
workflow_dispatch:
permissions:
issues: write
pull-requests: write
concurrency:
group: lock
jobs:
action:
runs-on: ubuntu-latest
if: github.repository_owner == 'vercel'
steps:
- uses: dessant/lock-threads@v5
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
add-issue-labels: 'locked'
add-pr-labels: 'locked'
issue-inactive-days: 14
issue-comment: 'This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.'
pr-inactive-days: 14
log-output: true

73
.github/workflows/issue_stale.yml vendored Normal file
View File

@@ -0,0 +1,73 @@
name: 'Stale issue handler'
on:
workflow_dispatch:
schedule:
# This runs every day 20 minutes before midnight: https://crontab.guru/#40_23_*_*_*
- cron: '40 23 * * *'
jobs:
stale:
runs-on: ubuntu-latest
if: github.repository_owner == 'vercel'
steps:
- uses: actions/stale@v9
id: issue-stale
name: 'Mark stale issues, close stale issues'
with:
repo-token: ${{ secrets.STALE_TOKEN }}
ascending: true
days-before-issue-close: 7
days-before-issue-stale: 545 # issues with no activity in over ~1.5 years
days-before-pr-close: -1
days-before-pr-stale: -1
remove-issue-stale-when-updated: true
stale-issue-label: 'stale'
labels-to-add-when-unstale: 'not stale'
stale-issue-message: 'This issue has been automatically marked as stale due to inactivity. It will be closed in 7 days unless theres further input. If you believe this issue is still relevant, please leave a comment or provide updated details. Thank you.'
close-issue-message: 'This issue has been automatically closed due to inactivity. If youre still experiencing a similar problem or have additional details to share, please open a new issue following our current issue template. Your updated report helps us investigate and address concerns more efficiently. Thank you for your understanding!'
operations-per-run: 300 # 1 operation per 100 issues, the rest is to label/comment/close
- uses: actions/stale@v9
id: stale-no-repro
name: 'Close stale issues with no reproduction'
with:
repo-token: ${{ secrets.STALE_TOKEN }}
any-of-issue-labels: 'please add a complete reproduction'
close-issue-message: 'This issue has been automatically closed due to 2 days of inactivity and the absence of a complete reproduction. If you believe this was done in error, please leave a comment. If you are experiencing a similar issue, consider opening a new issue with a complete reproduction. Thank you.'
days-before-issue-close: 2
days-before-issue-stale: 1
days-before-pr-close: -1
days-before-pr-stale: -1
remove-issue-stale-when-updated: true
stale-issue-label: 'stale'
labels-to-add-when-unstale: 'not stale'
operations-per-run: 300 # 1 operation per 100 issues, the rest is to label/comment/close
- uses: actions/stale@v9
id: stale-simple-repro
name: 'Close issues with no simple repro'
with:
repo-token: ${{ secrets.STALE_TOKEN }}
any-of-issue-labels: 'please simplify reproduction'
close-issue-message: 'This issue has been automatically closed due to 14 days of inactivity and the absence of a simple reproduction for investigation. If you believe this was done in error, please leave a comment. If you are experiencing a similar issue, consider opening a new issue with a simple reproduction. Thank you.'
days-before-issue-close: 14
days-before-issue-stale: 1
days-before-pr-close: -1
days-before-pr-stale: -1
remove-issue-stale-when-updated: true
stale-issue-label: 'stale'
labels-to-add-when-unstale: 'not stale'
operations-per-run: 300 # 1 operation per 100 issues, the rest is to label/comment/close
- uses: actions/stale@v9
id: stale-no-canary
name: 'Close issues not verified on canary'
with:
repo-token: ${{ secrets.STALE_TOKEN }}
any-of-issue-labels: 'please verify canary'
close-issue-message: 'This issue has been automatically closed due to 14 days of inactivity and the absence of testing against next@canary. If you believe this was done in error, please leave a comment. If you are experiencing a similar issue, consider opening a new issue with a reproduction. Thank you.'
days-before-issue-close: 14
days-before-issue-stale: 1
days-before-pr-close: -1
days-before-pr-stale: -1
remove-issue-stale-when-updated: true
stale-issue-label: 'stale'
labels-to-add-when-unstale: 'not stale'
operations-per-run: 300 # 1 operation per 100 issues, the rest is to label/comment/close

View File

@@ -0,0 +1,21 @@
name: 'Close issues using the wrong issue template'
on:
issues:
types: [labeled]
jobs:
close:
if: github.event.label.name == 'please use the correct issue template'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- name: 'Close issues using the wrong issue template'
run: node ./.github/actions/next-repo-actions/dist/wrong-issue-template/index.js
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

30
.github/workflows/popular.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: Notify about the top 15 issues/PRs/feature requests (most reacted) in the last 90 days
on:
schedule:
- cron: '0 10 * * 1' # Every Monday at 10AM UTC (6AM EST)
workflow_dispatch:
jobs:
run:
if: github.repository_owner == 'vercel'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- name: 'Issues: Send notification to Slack'
run: node ./.github/actions/next-repo-actions/dist/issues/index.mjs
continue-on-error: true
- name: 'PRs: Send notification to Slack'
run: node ./.github/actions/next-repo-actions/dist/prs/index.js
continue-on-error: true
- name: 'Feature requests: Send notification to Slack'
run: node ./.github/actions/next-repo-actions/dist/feature-requests/index.mjs
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}

131
.github/workflows/pull_request_stats.yml vendored Normal file
View File

@@ -0,0 +1,131 @@
on:
pull_request:
types: [opened, synchronize]
push:
branches:
- canary
name: Generate Stats
concurrency:
# Keep cancel-on-update behavior for PRs, but allow canary pushes to run independently.
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
NAPI_CLI_VERSION: 2.18.4
TURBO_VERSION: 2.8.11
NODE_LTS_VERSION: 20
TEST_CONCURRENCY: 6
TURBO_TEAM: 'vercel'
TURBO_CACHE: 'remote:rw'
NEXT_TELEMETRY_DISABLED: 1
# we build a dev binary for use in CI so skip downloading
# canary next-swc binaries in the monorepo
NEXT_SKIP_NATIVE_POSTINSTALL: 1
# Vercel KV Store for test timings
KV_REST_API_URL: ${{ secrets.KV_REST_API_URL }}
KV_REST_API_TOKEN: ${{ secrets.KV_REST_API_TOKEN }}
NEXT_TEST_JOB: 1
NEXT_DISABLE_SWC_WASM: 1
jobs:
build:
uses: ./.github/workflows/build_reusable.yml
secrets: inherit
with:
stepName: 'generate-pull-request-stats'
uploadSwcArtifact: 'yes'
uploadAnalyzerArtifacts: 'yes'
stats:
name: Stats (${{ matrix.bundler }})
needs: build
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
bundler: [webpack, turbopack]
runs-on:
- 'self-hosted'
- 'linux'
- 'x64'
- 'metal'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 25
- name: Check non-docs only change
run: echo "DOCS_CHANGE<<EOF" >> $GITHUB_OUTPUT; echo "$(node scripts/run-for-change.mjs --not --type docs --exec echo 'nope')" >> $GITHUB_OUTPUT; echo 'EOF' >> $GITHUB_OUTPUT
id: docs-change
- uses: actions/download-artifact@v4
if: ${{ steps.docs-change.outputs.DOCS_CHANGE == 'nope' }}
with:
name: next-swc-binary
path: packages/next-swc/native
- run: cp -r packages/next-swc/native .github/actions/next-stats-action/native
if: ${{ steps.docs-change.outputs.DOCS_CHANGE == 'nope' }}
- uses: ./.github/actions/next-stats-action
if: ${{ steps.docs-change.outputs.DOCS_CHANGE == 'nope' }}
with:
bundler: ${{ matrix.bundler }}
env:
PR_STATS_COMMENT_TOKEN: ${{ secrets.PR_STATS_COMMENT_TOKEN }}
TURBO_TEAM: ${{ env.TURBO_TEAM }}
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_CACHE: ${{ env.TURBO_CACHE }}
- name: Upload stats results
if: ${{ steps.docs-change.outputs.DOCS_CHANGE == 'nope' }}
uses: actions/upload-artifact@v4
with:
name: pr-stats-${{ matrix.bundler }}
path: pr-stats-${{ matrix.bundler }}.json
retention-days: 1
stats-aggregate:
name: Aggregate Stats
needs: stats
if: always() && needs.stats.result != 'cancelled'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 25
- name: Check non-docs only change
run: echo "DOCS_CHANGE<<EOF" >> $GITHUB_OUTPUT; echo "$(node scripts/run-for-change.mjs --not --type docs --exec echo 'nope')" >> $GITHUB_OUTPUT; echo 'EOF' >> $GITHUB_OUTPUT
id: docs-change
- name: Download all stats artifacts
if: ${{ steps.docs-change.outputs.DOCS_CHANGE == 'nope' }}
uses: actions/download-artifact@v4
with:
pattern: pr-stats-*
path: stats-results
merge-multiple: true
- name: Setup Node.js
if: ${{ steps.docs-change.outputs.DOCS_CHANGE == 'nope' }}
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
- name: Install dependencies
if: ${{ steps.docs-change.outputs.DOCS_CHANGE == 'nope' }}
working-directory: .github/actions/next-stats-action
run: npm install
- name: Aggregate and post results
if: ${{ steps.docs-change.outputs.DOCS_CHANGE == 'nope' }}
working-directory: .github/actions/next-stats-action
run: node src/aggregate-results.js ${{ github.workspace }}/stats-results
env:
PR_STATS_COMMENT_TOKEN: ${{ secrets.PR_STATS_COMMENT_TOKEN }}
KV_REST_API_URL: ${{ secrets.KV_REST_API_URL }}
KV_REST_API_TOKEN: ${{ secrets.KV_REST_API_TOKEN }}

View File

@@ -0,0 +1,132 @@
name: Release next-rspack bindings
on:
workflow_dispatch:
inputs:
dry-run:
description: 'Run in dry-run mode (no actual publishing)'
required: false
default: false
type: boolean
npm-name:
description: 'NPM package name to publish'
required: false
default: '@next/rspack-core'
type: string
npm-tag:
description: 'NPM tag for publishing'
required: false
default: 'latest'
type: choice
options:
- latest
- alpha
- beta
- canary
env:
DEBUG: napi:*
jobs:
build:
name: Build
uses: rspack-contrib/rspack-toolchain/.github/workflows/build.yml@f69dc04fcae6b38d97b87acef448ed7a285b01cc
with:
package-json-path: rspack/crates/binding/package.json
napi-build-command: pnpm build --release
working-directory: rspack
release:
runs-on: ubuntu-latest
environment: npm
name: Release
permissions:
contents: write
id-token: write
needs: [build]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Display release mode
run: |
echo "🚀 Release Configuration:"
echo " - Dry-run mode: ${{ inputs.dry-run }}"
echo " - NPM name: ${{ inputs.npm-name || '@next/rspack-core' }}"
echo " - NPM tag: ${{ inputs.npm-tag || 'latest' }}"
if [ "${{ inputs.dry-run }}" == "true" ]; then
echo " - ⚠️ This is a DRY RUN - no packages will be published"
else
echo " - 📦 This will PUBLISH packages to npm"
fi
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Enable corepack
run: corepack enable
- name: Setup pnpm
run: corepack prepare
- name: Change npm name
run: pnpm run change-npm-name "${{ inputs.npm-name }}"
working-directory: ./rspack
- name: Cache pnpm dependencies
uses: actions/cache@v3
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-${{ runner.arch }}-pnpm-v2-${{ hashFiles('**/pnpm-lock.yaml') }}
# Do not use restore-keys since it leads to indefinite growth of the cache.
- name: Install dependencies
run: pnpm install
working-directory: ./rspack
- name: Get NAPI info
id: napi-info
uses: rspack-contrib/rspack-toolchain/get-napi-info@f69dc04fcae6b38d97b87acef448ed7a285b01cc
with:
package-json-path: rspack/crates/binding/package.json
- name: Download rspack binding
uses: rspack-contrib/rspack-toolchain/download-rspack-binding@f69dc04fcae6b38d97b87acef448ed7a285b01cc
with:
path: ${{ steps.napi-info.outputs.binding-directory }}/artifacts
- name: List artifacts
run: ls -R artifacts
working-directory: ${{ steps.napi-info.outputs.binding-directory }}
- name: Create npm dirs
run: pnpm napi create-npm-dirs
working-directory: ${{ steps.napi-info.outputs.binding-directory }}
- name: Move artifacts
run: pnpm napi artifacts
working-directory: ${{ steps.napi-info.outputs.binding-directory }}
- name: List npm dirs
run: ls -R npm
working-directory: ${{ steps.napi-info.outputs.binding-directory }}
- name: Create npm token
run: |
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN_ELEVATED }}
- name: Release npm binding packages
run: |
npm config set access public
npm config set provenance true
pnpm napi pre-publish --no-gh-release -t npm ${{ inputs.dry-run && '--dry-run' || '' }}
working-directory: ${{ steps.napi-info.outputs.binding-directory }}
- name: Release npm packages
run: |
pnpm publish -r --tag ${{ inputs.npm-tag }} --no-git-checks --provenance --access public ${{ inputs.dry-run && '--dry-run' || '' }}
working-directory: ./rspack

67
.github/workflows/retry_deploy_test.yml vendored Normal file
View File

@@ -0,0 +1,67 @@
name: retry-deploy-tests
on:
workflow_run:
workflows: ['test-e2e-deploy-release']
types:
- completed
env:
SLACK_WEBHOOK_URL: ${{ secrets.BROKEN_DEPLOY_SLACK_WEBHOOK_URL }}
permissions:
actions: write
jobs:
retry-on-failure:
name: retry failed jobs
# Retry the test-e2e-deploy-release workflow once
if: >-
${{
(
github.event.workflow_run.event == 'release' ||
github.event.workflow_run.display_title == 'test-e2e-deploy canary'
) &&
github.event.workflow_run.conclusion == 'failure' &&
github.repository == 'vercel/next.js' &&
github.event.workflow_run.run_attempt < 2
}}
runs-on: ubuntu-latest
steps:
- name: send retry request to GitHub API
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}/rerun-failed-jobs
report-failure:
name: report failure to slack
# Report the failure to Slack if the test-e2e-deploy-release workflow has failed 2 times
if: >-
${{
(
github.event.workflow_run.event == 'release' ||
github.event.workflow_run.display_title == 'test-e2e-deploy canary'
) &&
github.event.workflow_run.conclusion == 'failure' &&
github.event.workflow_run.run_attempt >= 2 &&
!github.event.workflow_run.head_repository.fork
}}
runs-on: ubuntu-latest
steps:
- name: send webhook
uses: slackapi/slack-github-action@v1.25.0
with:
payload: |
{
"commit_title": ${{ toJSON(github.event.workflow_run.display_title) }},
"commit_url": "github.com/${{ github.repository }}/commit/${{ github.event.workflow_run.head_sha }}",
"workflow_run_url": "github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}/attempts/${{ github.event.workflow_run.run_attempt }}",
"workflow_branch": ${{ toJSON(github.event.workflow_run.head_branch) }}
}
env:
SLACK_WEBHOOK_URL: ${{ env.SLACK_WEBHOOK_URL }}

153
.github/workflows/retry_test.yml vendored Normal file
View File

@@ -0,0 +1,153 @@
name: retry-tests
on:
workflow_run:
# Make sure that required_job_conclusion knows what the name of the required
# job is in each workflow.
workflows: ['build-and-test', 'build-and-deploy']
branches: [canary]
types:
- completed
env:
SLACK_WEBHOOK_URL: ${{ secrets.BROKEN_CANARY_SLACK_WEBHOOK_URL }}
permissions:
actions: write
jobs:
retry-on-failure:
name: retry failed jobs
# Retry the build-and-test workflow up to 2 times
if: >-
${{
github.event.workflow_run.conclusion == 'failure' &&
github.repository == 'vercel/next.js' &&
github.event.workflow_run.run_attempt < 3
}}
runs-on: ubuntu-latest
steps:
- name: Check conclusion of required job
id: required_job_conclusion
uses: actions/github-script@v7
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
script: |
// See build-and-test.yml and build-and-deploy.yml for the required job names
const requiredJobName = {
'build-and-test': 'thank you, next',
'build-and-deploy': 'thank you, build',
}[context.payload.workflow_run.name]
async function rerunIfRequiredNotSuccessful() {
const result = await github.paginate.iterator(
'GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs',
{
attempt_number: context.payload.workflow_run.run_attempt,
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
}
)
for await (const { data: jobs } of result) {
for (const job of jobs) {
if (job.name === requiredJobName) {
console.log(
"Using conclusion '%s' from %s",
job.conclusion,
job.html_url
)
return job.conclusion
}
}
}
console.log("Couldn't find job with name '%s'", requiredJobName)
return null
}
return await rerunIfRequiredNotSuccessful()
- name: send retry request to GitHub API
if: ${{ steps.required_job_conclusion.outputs.result != '"success"' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}/rerun-failed-jobs
report-failure:
name: report failure to slack
# Report the failure to Slack if the build-and-test workflow has failed 3 times
# build-and-deploy is not retried so we always report it
if: >-
${{
github.event.workflow_run.conclusion == 'failure' &&
github.event.workflow_run.run_attempt >= 3 &&
!github.event.workflow_run.head_repository.fork
}}
runs-on: ubuntu-latest
steps:
- name: Check conclusion of required job
id: required_job_conclusion
uses: actions/github-script@v7
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
script: |
// See build-and-test.yml and build-and-deploy.yml for the required job names
const requiredJobName = {
'build-and-test': 'thank you, next',
'build-and-deploy': 'thank you, build',
}[context.payload.workflow_run.name]
async function rerunIfRequiredNotSuccessful() {
const result = await github.paginate.iterator(
'GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs',
{
attempt_number: context.payload.workflow_run.run_attempt,
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
}
)
for await (const { data: jobs } of result) {
for (const job of jobs) {
if (job.name === requiredJobName) {
console.log(
"Using conclusion '%s' from %s",
job.conclusion,
job.html_url
)
return job.conclusion
}
}
}
console.log("Couldn't find job with name '%s'", requiredJobName)
return null
}
return await rerunIfRequiredNotSuccessful()
- name: send webhook
if: ${{ steps.required_job_conclusion.outputs.result != '"success"' }}
uses: slackapi/slack-github-action@v1.25.0
with:
# These urls are intentionally missing the protocol,
# allowing them to be transformed into actual links in the Slack workflow
# (through slightly hacky means).
payload: |
{
"commit_title": ${{ toJSON(github.event.workflow_run.display_title) }},
"commit_url": "github.com/${{ github.repository }}/commit/${{ github.event.workflow_run.head_sha }}",
"workflow_run_url": "github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}/attempts/${{ github.event.workflow_run.run_attempt }}"
}
env:
SLACK_WEBHOOK_URL: ${{ env.SLACK_WEBHOOK_URL }}

View File

@@ -0,0 +1,25 @@
name: Rspack Next.js production integration tests
on:
schedule:
# Run an hour earlier than the turbopack tests, so we don't overwhelm the CI
- cron: '0 5 * * *'
workflow_dispatch: {}
jobs:
test-dev:
name: Rspack integration tests
uses: ./.github/workflows/integration_tests_reusable.yml
with:
name: rspack-production
test_type: production
run_before_test: |
export NEXT_RSPACK=1 NEXT_TEST_USE_RSPACK=1 \
# Failing tests take longer (due to timeouts and retries). Since we have
# many failing tests, we need smaller groups and longer timeouts, in case
# a group gets stuck with a cluster of failing tests.
e2e_groups: 12
integration_groups: 12
e2e_timeout_minutes: 90
integration_timeout_minutes: 90
secrets: inherit

View File

@@ -0,0 +1,25 @@
name: Rspack Next.js development integration tests
on:
schedule:
# Run an hour earlier than the turbopack tests, so we don't overwhelm the CI
- cron: '0 5 * * *'
workflow_dispatch: {}
jobs:
test-dev:
name: Rspack integration tests
uses: ./.github/workflows/integration_tests_reusable.yml
with:
name: rspack-development
test_type: development
run_before_test: |
export NEXT_RSPACK=1 NEXT_TEST_USE_RSPACK=1
# Failing tests take longer (due to timeouts and retries). Since we have
# many failing tests, we need smaller groups and longer timeouts, in case
# a group gets stuck with a cluster of failing tests.
e2e_groups: 16
integration_groups: 16
e2e_timeout_minutes: 90
integration_timeout_minutes: 90
secrets: inherit

View File

@@ -0,0 +1,86 @@
# A recurring workflow which updates the passing/failing/skipped integration tests for Turbopack.
name: Update Rspack test manifest
on:
schedule:
# Every day at 7AM https://crontab.guru/#0_7_*_*_*
- cron: '0 7 * * *'
workflow_dispatch:
jobs:
update_dev_manifest:
name: Update and upload Rspack development test manifest
if: github.repository_owner == 'vercel'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Commits made with the default `GITHUB_TOKEN` won't trigger workflows.
# See: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#using-the-github_token-in-a-workflow
token: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- name: Install dependencies
shell: bash
run: pnpm i
- name: Create Pull Request
shell: bash
run: node scripts/automated-update-workflow.js
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN_PULL_REQUESTS }}
BRANCH_NAME: rspack-manifest
# We need to use `--override` for rspack (but not for turbopack).
# We don't currently have any CI running on every PR, so it's quite
# possible for us to regress on tests. We need to skip the
# only-promote-to-passing merge logic.
SCRIPT: test/update-bundler-manifest.js --bundler rspack --test-suite dev --override
PR_TITLE: Update Rspack development test manifest
PR_BODY: This auto-generated PR updates the development integration test manifest used when testing Rspack.
update_build_manifest:
name: Update and upload Rspack production test manifest
if: github.repository_owner == 'vercel'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Commits made with the default `GITHUB_TOKEN` won't trigger workflows.
# See: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#using-the-github_token-in-a-workflow
token: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- name: Install dependencies
shell: bash
run: pnpm i
- name: Create Pull Request
shell: bash
run: node scripts/automated-update-workflow.js
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN_PULL_REQUESTS }}
BRANCH_NAME: rspack-manifest
SCRIPT: test/update-bundler-manifest.js --bundler rspack --test-suite build --override
PR_TITLE: Update Rspack production test manifest
PR_BODY: This auto-generated PR updates the production integration test manifest used when testing Rspack.

125
.github/workflows/setup-nextjs-build.yml vendored Normal file
View File

@@ -0,0 +1,125 @@
# Reusable workflow to setup next.js integration test environment.
name: Setup Next.js
on:
workflow_call:
inputs:
# Allow to specify Next.js version to run integration test against.
# If not specified, will use latest release version including canary.
version:
type: string
nodeVersion:
required: false
description: 'version of Node.js to use'
type: string
jobs:
build_nextjs:
name: Build Next.js for the turbopack integration test
runs-on:
- 'self-hosted'
- 'linux'
- 'x64'
- 'metal'
outputs:
output1: ${{ steps.build-next-swc-turbopack-patch.outputs.success }}
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.nodeVersion || env.NODE_LTS_VERSION }}
check-latest: true
- name: Get number of CPU cores
uses: SimenB/github-actions-cpu-cores@v2
id: cpu-cores
- name: 'Setup Rust toolchain'
uses: dtolnay/rust-toolchain@stable
- name: Display runner information
run: echo runner cpu count ${{ steps.cpu-cores.outputs.count }}
- name: Find Next.js latest release version
env:
GH_TOKEN: ${{ github.token }}
run: |
# Grab the latest release version from next.js repo, including prelease. `/releases/latest` will only return latest stable release.
echo NEXJS_LATEST_VERSION=$(gh release --repo vercel/next.js --limit 1 list | sed -n 1p | awk '{print $1}') >> $GITHUB_ENV
- name: Set Next.js release version
run: |
echo "NEXTJS_VERSION=${{ inputs.version != '' && inputs.version || env.NEXJS_LATEST_VERSION }}" >> $GITHUB_ENV
- name: Print Next.js release version to checkout
run: echo "Checking out Next.js ${{ env.NEXTJS_VERSION }}"
- name: Checkout Next.js
uses: actions/checkout@v4
with:
repository: vercel/next.js
ref: ${{ env.NEXTJS_VERSION }}
- name: Checkout failed test lists
uses: actions/checkout@v4
with:
repository: vercel/turbo
ref: nextjs-integration-test-data
path: integration-test-data
- name: Download binary
uses: actions/download-artifact@v4
with:
path: artifacts
- uses: actions/cache/restore@v3
id: restore-build
with:
path: |
./*
key: ${{ inputs.version }}-${{ github.sha }}
- name: Install dependencies
run: |
wget https://github.com/sharkdp/hyperfine/releases/download/v1.16.1/hyperfine_1.16.1_amd64.deb
sudo dpkg -i hyperfine_1.16.1_amd64.deb
npm i -g corepack@0.31
corepack enable
pnpm install --loglevel error
- name: Build next-swc
run: |
hyperfine --min-runs 1 --show-output 'pnpm run --filter=@next/swc build-native --features plugin --release'
echo "Successfully built next-swc with published turbopack"
- name: Build next.js
run: |
pnpm run build
strip packages/next-swc/native/next-swc.*.node
ls -al packages/next-swc/native
# Reduce the size of the cache bit
cd packages/next-swc && cargo clean && cd ../../
echo NEXT_SWC_FILESIZE: $(stat -c %s packages/next-swc/native/next-swc.linux-x64-gnu.node)
node -e "console.log('Host', require('os').arch(), require('os').platform())"
# If input version is published release, detect version by running next.js build.
- name: Detects Next.js build version
run: |
# This is being used in github action to collect test results. Do not change it, or should update ./.github/actions/next-integration-test to match.
docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.28.1-jammy /bin/bash -c 'curl https://install-node.vercel.app/v16 | FORCE=1 bash && cd /work && echo RUNNING NEXTJS VERSION: $(packages/next/dist/bin/next --version) && ls -al packages/next-swc/native && node -e "console.log(\"Container\", require(\"os\").arch(), require(\"os\").platform())"'
- name: Temporary test skip
run: |
rm -rf test/integration/jsconfig-paths/test/index.test.js
# Once build completes, creates a cache of the build output
# so subsequent job to actually execute tests can reuse it.
# Note that we do not use upload / download artifacts for this -
# it is too heavyweight for the purpose since we do not need to persist
# the cache across multiple runs.
- name: Store next.js build cache with next-swc
uses: actions/cache/save@v3
id: cache-build
with:
path: |
./*
key: ${{ inputs.version }}-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt}}-${{ github.run_number }}

View File

@@ -0,0 +1,69 @@
name: Turbopack Rust testing benchmarks
on:
workflow_call:
inputs:
runner:
type: string
default: '["self-hosted", "linux", "x64", "metal"]'
os:
type: string
default: 'linux'
all:
type: boolean
default: false
env:
TURBOPACK_BENCH_COUNTS: '100'
TURBOPACK_BENCH_PROGRESS: '1'
NODE_LTS_VERSION: 20
jobs:
test:
name: Test
runs-on: ${{ fromJSON(inputs.runner) }}
steps:
- name: Set git to use LF
run: |
git config --global core.autocrlf false
git config --global core.eol lf
if: inputs.os == 'windows'
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust
uses: ./.github/actions/setup-rust
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- run: corepack enable
# We need to install the dependencies for the benchmark apps
- run: pnpm install
working-directory: turbopack/benchmark-apps
- name: Build benchmarks for tests
timeout-minutes: 120
run: |
cargo test --benches --workspace --release --no-fail-fast --exclude turbopack-bench --exclude next-napi-bindings --no-run
- name: Run cargo test on benchmarks
timeout-minutes: 120
run: |
cargo test --benches --workspace --release --no-fail-fast --exclude turbopack-bench --exclude next-napi-bindings
- name: Build benchmarks for tests for other bundlers
if: inputs.all
timeout-minutes: 120
run: |
cargo test --benches --release -p turbopack-bench --no-run
- name: Run cargo test on benchmarks for other bundlers
if: inputs.all
timeout-minutes: 120
run: |
cargo test --benches --release -p turbopack-bench

View File

@@ -0,0 +1,404 @@
name: test-e2e-deploy-release
on:
# run on every release/prerelease
release:
types: [published]
# allow triggering manually as well
workflow_dispatch:
inputs:
nextVersion:
description: canary or custom tarball URL
default: canary
type: string
vercelCliVersion:
description: Version of Vercel CLI to use
default: 'vercel@latest'
type: string
overrideProxyAddress:
description: Override the proxy address to use for the test
default: ''
type: string
deployScriptPath:
description: Custom deploy script path (NEXT_TEST_DEPLOY_SCRIPT_PATH)
default: ''
type: string
deployLogsScriptPath:
description: Custom deploy logs script path (NEXT_TEST_DEPLOY_LOGS_SCRIPT_PATH)
default: ''
type: string
cleanupScriptPath:
description: Custom cleanup script path (NEXT_TEST_CLEANUP_SCRIPT_PATH)
default: ''
type: string
env:
DD_ENV: 'ci'
DATADOG_API_KEY: ${{ secrets.DATA_DOG_API_KEY }}
VERCEL_TEST_TEAM: vtest314-next-e2e-tests
VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
VERCEL_ADAPTER_TEST_TEAM: vtest314-next-adapter-e2e-tests
VERCEL_ADAPTER_TEST_TOKEN: ${{ secrets.VERCEL_ADAPTER_TEST_TOKEN }}
VERCEL_TURBOPACK_TEST_TEAM: vtest314-next-turbo-e2e-tests
VERCEL_TURBOPACK_TEST_TOKEN: ${{ secrets.VERCEL_TURBOPACK_TEST_TOKEN }}
run-name: test-e2e-deploy ${{ inputs.nextVersion || (github.event_name == 'release' && github.event.release.tag_name) || 'canary' }}
jobs:
setup:
runs-on: ubuntu-latest
if: github.repository_owner == 'vercel'
outputs:
next-version: ${{ steps.version.outputs.value }}
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup pnpm
run: |
npm i -g corepack@0.31
corepack enable
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 25
- id: nextPackageInfo
name: Get `next` package info
run: |
cd packages/next
{
echo 'value<<EOF'
cat package.json
echo EOF
} >> "$GITHUB_OUTPUT"
- id: version
name: Extract `next` version
run: echo 'value=${{ fromJson(steps.nextPackageInfo.outputs.value).version }}' >> "$GITHUB_OUTPUT"
- name: Install dependencies
run: pnpm install
- name: Fetch test timings
run: node run-tests.js --timings --write-timings -g 1/1
continue-on-error: true
env:
KV_REST_API_URL: ${{ secrets.KV_REST_API_URL }}
KV_REST_API_TOKEN: ${{ secrets.KV_REST_API_TOKEN }}
- name: Ensure test timings file exists
run: |
if [ ! -f test-timings.json ]; then
echo "No timings fetched, creating empty timings file"
echo '{}' > test-timings.json
fi
- name: Upload test timings
uses: actions/upload-artifact@v4
with:
name: test-timings
path: test-timings.json
retention-days: 1
if-no-files-found: error
test-deploy-webpack:
name: Run Deploy Tests (Webpack)
needs: setup
if: ${{ github.event.inputs.deployScriptPath == '' }}
uses: ./.github/workflows/build_reusable.yml
secrets: inherit
strategy:
fail-fast: false
matrix:
group: [1/8, 2/8, 3/8, 4/8, 5/8, 6/8, 7/8, 8/8]
with:
afterBuild: |
npm i -g vercel@latest && \
NEXT_E2E_TEST_TIMEOUT=240000 \
NEXT_TEST_MODE=deploy \
IS_WEBPACK_TEST=1 \
NEXT_EXTERNAL_TESTS_FILTERS="test/deploy-tests-manifest.json" \
NEXT_TEST_VERSION="${{ github.event.inputs.nextVersion || needs.setup.outputs.next-version || 'canary' }}" \
VERCEL_CLI_VERSION="${{ github.event.inputs.vercelCliVersion || 'vercel@latest' }}" \
NEXT_TEST_DEPLOY_SCRIPT_PATH="${{ github.event.inputs.deployScriptPath || '' }}" \
NEXT_TEST_DEPLOY_LOGS_SCRIPT_PATH="${{ github.event.inputs.deployLogsScriptPath || '' }}" \
NEXT_TEST_CLEANUP_SCRIPT_PATH="${{ github.event.inputs.cleanupScriptPath || '' }}" \
node run-tests.js --timings --require-timings -g ${{ matrix.group }} -c 2 --type e2e
testTimingsArtifact: 'test-timings'
skipNativeBuild: 'yes'
skipNativeInstall: 'no'
stepName: 'test-deploy-webpack-${{ matrix.group }}'
timeout_minutes: 180
runs_on_labels: '["ubuntu-latest"]'
overrideProxyAddress: ${{ inputs.overrideProxyAddress || '' }}
test-deploy-turbopack:
name: Run Deploy Tests (Turbopack)
needs: [setup]
uses: ./.github/workflows/build_reusable.yml
secrets: inherit
strategy:
fail-fast: false
matrix:
group:
[
1/12,
2/12,
3/12,
4/12,
5/12,
6/12,
7/12,
8/12,
9/12,
10/12,
11/12,
12/12,
]
with:
afterBuild: |
npm i -g vercel@latest && \
NEXT_E2E_TEST_TIMEOUT=240000 \
NEXT_TEST_MODE=deploy \
IS_TURBOPACK_TEST=1 \
NEXT_TEST_CONTINUE_ON_ERROR="${{ github.event.inputs.continueOnError || false }}" \
NEXT_EXTERNAL_TESTS_FILTERS="test/deploy-tests-manifest.json" \
NEXT_TEST_VERSION="${{ github.event.inputs.nextVersion || needs.setup.outputs.next-version || 'canary' }}" \
VERCEL_CLI_VERSION="${{ github.event.inputs.vercelCliVersion || 'vercel@latest' }}" \
NEXT_TEST_DEPLOY_SCRIPT_PATH="${{ github.event.inputs.deployScriptPath || '' }}" \
NEXT_TEST_DEPLOY_LOGS_SCRIPT_PATH="${{ github.event.inputs.deployLogsScriptPath || '' }}" \
NEXT_TEST_CLEANUP_SCRIPT_PATH="${{ github.event.inputs.cleanupScriptPath || '' }}" \
node run-tests.js --timings --require-timings -g ${{ matrix.group }} -c 2 --type e2e
testTimingsArtifact: 'test-timings'
skipNativeBuild: 'yes'
skipNativeInstall: 'no'
stepName: 'test-deploy-turbopack-${{ matrix.group }}'
timeout_minutes: 180
runs_on_labels: '["ubuntu-latest"]'
overrideProxyAddress: ${{ inputs.overrideProxyAddress || '' }}
test-deploy-adapter:
name: Run Deploy Adapter Tests (Turbopack)
needs: setup
if: ${{ github.event.inputs.deployScriptPath == '' }}
uses: ./.github/workflows/build_reusable.yml
secrets: inherit
strategy:
fail-fast: false
matrix:
group:
[
1/12,
2/12,
3/12,
4/12,
5/12,
6/12,
7/12,
8/12,
9/12,
10/12,
11/12,
12/12,
]
with:
afterBuild: |
npm i -g vercel@latest && \
NEXT_E2E_TEST_TIMEOUT=240000 \
NEXT_TEST_MODE=deploy \
IS_TURBOPACK_TEST=1 \
NEXT_ENABLE_ADAPTER=1 \
NEXT_EXTERNAL_TESTS_FILTERS="test/deploy-tests-manifest.json" \
NEXT_TEST_VERSION="${{ github.event.inputs.nextVersion || needs.setup.outputs.next-version || 'canary' }}" \
VERCEL_CLI_VERSION="${{ github.event.inputs.vercelCliVersion || 'vercel@latest' }}" \
node run-tests.js --timings --require-timings -g ${{ matrix.group }} -c 2 --type e2e
testTimingsArtifact: 'test-timings'
skipNativeBuild: 'yes'
skipNativeInstall: 'no'
stepName: 'test-deploy-deploy-${{ matrix.group }}'
timeout_minutes: 180
runs_on_labels: '["ubuntu-latest"]'
overrideProxyAddress: ${{ inputs.overrideProxyAddress || '' }}
report-test-results-to-datadog:
needs: [test-deploy-turbopack, test-deploy-webpack]
if: ${{ always() && github.event.inputs.deployScriptPath == '' }}
runs-on: ubuntu-latest
name: Report test results to datadog
steps:
- name: Download test report artifacts
id: download-test-reports
uses: actions/download-artifact@v4
with:
pattern: test-reports-*
path: test
merge-multiple: true
- name: Upload test report to datadog
run: |
if [ -d ./test/test-junit-report ]; then
DD_ENV=ci npx @datadog/datadog-ci@2.23.1 junit upload --tags test.type:deploy --service nextjs ./test/test-junit-report
fi
create-draft-prs:
name: Immediately open draft prs
needs: setup
if: ${{ github.repository_owner == 'vercel' && github.event_name == 'release' }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- repo: front
workflow_id: cron-update-next.yml
- repo: v0
workflow_id: update-next.yaml
steps:
- name: Check token
run: gh auth status
# This sometimes fails for unknown reasons.
# Ignoring failures for now to check if a failure actually blocks subsequent steps
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GH_UPDATE_NEXT_WORKFLOW_TRIGGER }}
- uses: actions/github-script@v7
name: Check if target workflow is enabled
id: check-workflow-enabled
with:
retries: 3
retry-exempt-status-codes: 400,401,403,404,422
github-token: ${{ secrets.GH_UPDATE_NEXT_WORKFLOW_TRIGGER }}
result-encoding: string
script: |
const response = await github.request(
"GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}",
{
owner: "vercel",
repo: "${{ matrix.repo }}",
workflow_id: "${{ matrix.workflow_id }}",
}
);
const isEnabled = response.data.state === 'active';
console.info(`Target workflow state: ${response.data.state}`);
console.info(`Target workflow enabled: ${isEnabled}`);
return isEnabled ? 'true' : 'false';
- uses: actions/github-script@v7
name: Create draft PR for vercel/${{ matrix.repo }}
id: create-draft-pr
if: steps.check-workflow-enabled.outputs.result == 'true'
with:
retries: 3
retry-exempt-status-codes: 400,401,404
github-token: ${{ secrets.GH_UPDATE_NEXT_WORKFLOW_TRIGGER }}
result-encoding: string
script: |
const inputs = {
version: "${{ needs.setup.outputs.next-version }}"
};
await github.request(
"POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches",
{
owner: "vercel",
repo: "${{ matrix.repo }}",
workflow_id: "${{ matrix.workflow_id }}",
ref: "main",
inputs: inputs,
}
);
console.info(`Draft PR creation triggered for ${{ matrix.repo }}`);
console.info(`Workflow will create draft PR by default`);
update-prs:
name: Update prs as ready for review
needs: [test-deploy-turbopack, test-deploy-webpack, create-draft-prs]
if: ${{ (needs.test-deploy-webpack.result == 'success' || needs.test-deploy-webpack.result == 'skipped') && needs.test-deploy-turbopack.result == 'success' && github.repository_owner == 'vercel' && github.event_name == 'release' }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- repo: front
workflow_id: cron-update-next.yml
workflow_url: https://github.com/vercel/front/actions/workflows/cron-update-next.yml?query=event%3Aworkflow_dispatch
- repo: v0
workflow_id: update-next.yaml
workflow_url: https://github.com/vercel/v0/actions/workflows/update-next.yaml?query=event%3Aworkflow_dispatch
steps:
- name: Check token
run: gh auth status
# This sometimes fails for unknown reasons.
# Ignoring failures for now to check if a failure actually blocks subsequent steps
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GH_UPDATE_NEXT_WORKFLOW_TRIGGER }}
- uses: actions/github-script@v7
name: Check if target workflow is enabled
id: check-workflow-enabled
with:
retries: 3
retry-exempt-status-codes: 400,401,404
github-token: ${{ secrets.GH_UPDATE_NEXT_WORKFLOW_TRIGGER }}
result-encoding: string
script: |
try {
const response = await github.request(
"GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}",
{
owner: "vercel",
repo: "${{ matrix.repo }}",
workflow_id: "${{ matrix.workflow_id }}",
}
);
const isEnabled = response.data.state === 'active';
console.info(`Target workflow state: ${response.data.state}`);
console.info(`Target workflow enabled: ${isEnabled}`);
return isEnabled ? 'true' : 'false';
} catch (error) {
console.error('Error checking workflow status:', error);
return 'false';
}
- uses: actions/github-script@v7
name: Mark PR ready for review in vercel/${{ matrix.repo }}
id: mark-pr-ready
if: steps.check-workflow-enabled.outputs.result == 'true'
with:
retries: 3
retry-exempt-status-codes: 400,401,404
# Default github token cannot dispatch events to the remote repo, it should be
# a PAT with Actions write access (https://docs.github.com/en/rest/actions/workflows?apiVersion=2022-11-28#create-a-workflow-dispatch-event)
github-token: ${{ secrets.GH_UPDATE_NEXT_WORKFLOW_TRIGGER }}
# Note `workflow_id` and `inputs` are contract between vercel/${{ matrix.repo }},
# if these need to be changed both side should be updated accordingly.
script: |
const inputs = {
version: "${{ needs.setup.outputs.next-version }}",
'make-ready-for-review': 'true',
force: 'true'
};
await github.request(
"POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches",
{
owner: "vercel",
repo: "${{ matrix.repo }}",
workflow_id: "${{ matrix.workflow_id }}",
ref: "main",
inputs: inputs,
}
);
console.info("Tests passed - PR will be marked ready for review");
console.info(
"PR ready-for-review triggered in ${{ matrix.workflow_url }}"
);

View File

@@ -0,0 +1,46 @@
name: test-e2e-project-reset-cron
on:
# Run every Sunday at 5AM UTC
schedule:
- cron: '0 5 * * 0'
# Allow manual triggering for emergency resets
workflow_dispatch:
env:
VERCEL_TEST_TEAM: vtest314-next-e2e-tests
VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
VERCEL_ADAPTER_TEST_TEAM: vtest314-next-adapter-e2e-tests
VERCEL_ADAPTER_TEST_TOKEN: ${{ secrets.VERCEL_ADAPTER_TEST_TOKEN }}
NODE_LTS_VERSION: 20
TURBO_TEAM: 'vercel'
TURBO_CACHE: 'remote:rw'
run-name: test-e2e-project-reset (scheduled)
jobs:
reset-test-project:
runs-on: ubuntu-latest
if: github.repository_owner == 'vercel'
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup pnpm
run: |
npm i -g corepack@0.31
corepack enable
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 25
- name: Install dependencies
run: pnpm install
- name: Reset test project
run: node scripts/run-e2e-test-project-reset.mjs

51
.github/workflows/test_examples.yml vendored Normal file
View File

@@ -0,0 +1,51 @@
# This file duplicates bunch of things from build_test_deploy
on:
workflow_dispatch:
inputs:
is_dispatched:
description: 'Leave this option enabled'
required: true
default: true
type: boolean
schedule:
- cron: '0 */4 * * *'
name: Test examples
jobs:
testExamples:
# Don't execute using cron on forks
if: (github.repository == 'vercel/next.js') || (inputs.is_dispatched == true)
name: Test Examples
runs-on: ubuntu-latest
timeout-minutes: 120
env:
NEXT_TELEMETRY_DISABLED: 1
strategy:
fail-fast: false
matrix:
node: [20, 22]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 25
# https://github.com/actions/virtual-environments/issues/1187
- name: tune linux network
run: sudo ethtool -K eth0 tx off rx off
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- run: pnpm install
- run: pnpm build
- run: docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.35.1-focal /bin/bash -c "cd /work && curl -s https://install-node.vercel.app/v${{ matrix.node }} | FORCE=1 bash && node -v && corepack enable > /dev/null && NEXT_TEST_JOB=1 NEXT_TEST_MODE=start xvfb-run node run-tests.js --type examples >> /proc/1/fd/1"
name: Run test/examples

47
.github/workflows/triage.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: Triage issues
on:
issues:
types: [opened, labeled]
issue_comment:
types: [created]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
issues: write
jobs:
triage:
name: Nissuer
runs-on: ubuntu-latest
if: >-
${{
(github.event_name != 'issue_comment' ||
(github.event_name == 'issue_comment' && !contains(github.event.issue.labels.*.name, 'stale'))) &&
github.event.issue.type.name != 'Documentation'
}}
steps:
- uses: balazsorban44/nissuer@1.10.0
with:
label-area-prefix: ''
label-area-match: 'name'
label-area-section: 'Which area\(s\) are affected\? \(Select all that apply\)(.*)### Additional context'
label-comments: |
{
"good first issue": ".github/comments/good-first-issue.md",
"please add a complete reproduction": ".github/comments/invalid-reproduction.md",
"please simplify reproduction": ".github/comments/simplify-reproduction.md",
"please verify canary": ".github/comments/verify-canary.md",
"resolved": ".github/comments/resolved.md"
}
reproduction-comment: '.github/comments/invalid-link.md'
reproduction-hosts: 'github.com,bitbucket.org,gitlab.com,codesandbox.io,stackblitz.com'
reproduction-blocklist: 'github.com/vercel/next.js.*,github.com/\\w*/?$,github.com$'
reproduction-link-section: '### Link to the code that reproduces this issue(.*)### To Reproduce'
reproduction-invalid-label: 'invalid link'
reproduction-issue-labels: 'bug,'
comment-unhelpful-weight: 0.5
webhook-url: ${{ secrets.NISSUER_WEBHOOK_URL }}
webhook-secret: ${{ secrets.NISSUER_WEBHOOK_SECRET }}

106
.github/workflows/trigger_release.yml vendored Normal file
View File

@@ -0,0 +1,106 @@
on:
schedule:
# run every day at 23:15
- cron: '15 23 * * *'
workflow_dispatch:
inputs:
releaseType:
description: stable, canary, beta, or release candidate?
required: true
type: choice
options:
- canary
- stable
- release-candidate
- beta
semverType:
description: semver type?
type: choice
options:
- patch
- minor
- major
force:
description: create a new release even if there are no new commits
default: false
type: boolean
name: Trigger Release
env:
NAPI_CLI_VERSION: 2.18.4
TURBO_VERSION: 2.8.11
NODE_LTS_VERSION: 20
jobs:
start:
if: github.repository_owner == 'vercel'
runs-on: ubuntu-latest
env:
NEXT_TELEMETRY_DISABLED: 1
# we build a dev binary for use in CI so skip downloading
# canary next-swc binaries in the monorepo
NEXT_SKIP_NATIVE_POSTINSTALL: 1
environment: release-${{ github.event.inputs.releaseType || 'canary' }}
steps:
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20
check-latest: true
- name: Clone Next.js repository
run: git clone https://github.com/vercel/next.js.git --depth=25 --single-branch --branch ${GITHUB_REF_NAME:-canary} .
- name: Check token
run: gh auth status
# This sometimes fails for unknown reasons.
# Ignoring failures for now to check if a failure truly implies a failed publish.
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}
- name: Get commit of the latest tag
run: echo "LATEST_TAG_COMMIT=$(git rev-list -n 1 $(git describe --tags --abbrev=0))" >> $GITHUB_ENV
- name: Get latest commit
run: echo "LATEST_COMMIT=$(git rev-parse HEAD)" >> $GITHUB_ENV
- name: Check if new commits since last tag
if: ${{ github.event.inputs.releaseType != 'stable' && github.event.inputs.force != true }}
run: |
if [ "$LATEST_TAG_COMMIT" = "$LATEST_COMMIT" ]; then
echo "No new commits. Exiting..."
exit 1
fi
# https://github.com/actions/virtual-environments/issues/1187
- name: tune linux network
run: sudo ethtool -K eth0 tx off rx off
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
pnpm --version
- id: get-store-path
run: echo STORE_PATH=$(pnpm store path) >> $GITHUB_OUTPUT
- uses: actions/cache@v4
timeout-minutes: 5
id: cache-pnpm-store
with:
path: ${{ steps.get-store-path.outputs.STORE_PATH }}
key: pnpm-store-v2-${{ hashFiles('pnpm-lock.yaml') }}
# Do not use restore-keys since it leads to indefinite growth of the cache.
- run: pnpm install
- run: node ./scripts/start-release.js --release-type ${{ github.event.inputs.releaseType || 'canary' }} --semver-type ${{ github.event.inputs.semverType }}
env:
RELEASE_BOT_GITHUB_TOKEN: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}

View File

@@ -0,0 +1,134 @@
name: Turbopack Benchmark
on:
workflow_dispatch:
push:
branches:
- canary
pull_request:
types: ['opened', 'reopened', 'synchronize', 'labeled']
paths:
- '**/crates/**'
- '**/Cargo.toml'
- '**/Cargo.lock'
concurrency:
# Limit concurrent runs to 1 per PR, but allow concurrent runs on canary branch
group: ${{ github.event_name == 'pull_request' && format('{0}-{1}', github.workflow, github.event.pull_request.number) || format('{0}-{1}-{2}', github.workflow, github.ref_name, github.run_id) }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
CI: 1
CARGO_INCREMENTAL: 0
# For faster CI
RUST_LOG: 'off'
TURBO_TEAM: 'vercel'
TURBO_CACHE: 'remote:rw'
jobs:
benchmark-small-apps:
name: Benchmark Rust Crates (small apps)
runs-on: ['self-hosted', 'linux', 'x64', 'metal']
steps:
- uses: actions/checkout@v4
- name: Setup Rust toolchain
uses: ./.github/actions/setup-rust
- name: Install cargo-codspeed
uses: taiki-e/install-action@v2
with:
tool: cargo-codspeed@3.0.5
- name: Cache on ${{ github.ref_name }}
uses: ijjk/rust-cache@turbo-cache-v1.0.9
with:
save-if: 'true'
cache-provider: 'turbo'
shared-key: build-turbopack-benchmark-small-apps-${{ hashFiles('.cargo/config.toml') }}
- name: Install pnpm dependencies
working-directory: turbopack/benchmark-apps
run: |
npm i -g corepack@0.31
corepack enable
pnpm install --loglevel error
- name: Build app build benchmarks
env:
CODSPEED_RUNNER_MODE: instrumentation
run: cargo codspeed build -p turbopack-cli small_apps
- name: Run the benchmarks
uses: CodSpeedHQ/action@v4
with:
mode: instrumentation
run: cargo codspeed run -p turbopack-cli small_apps
token: ${{ secrets.CODSPEED_TOKEN }}
benchmark-analyzer:
name: Benchmark Rust Crates (analyzer)
runs-on: ['self-hosted', 'linux', 'x64', 'metal']
steps:
- uses: actions/checkout@v4
- name: Setup Rust toolchain
uses: ./.github/actions/setup-rust
- name: Install cargo-codspeed
uses: taiki-e/install-action@v2
with:
tool: cargo-codspeed@3.0.5
- name: Cache on ${{ github.ref_name }}
uses: ijjk/rust-cache@turbo-cache-v1.0.9
with:
save-if: 'true'
cache-provider: 'turbo'
shared-key: build-turbopack-benchmark-analyzer-${{ hashFiles('.cargo/config.toml') }}
- name: Install pnpm dependencies
working-directory: turbopack/benchmark-apps
run: |
npm i -g corepack@0.31
corepack enable
pnpm install --loglevel error
- name: Build app build benchmarks
env:
CODSPEED_RUNNER_MODE: instrumentation
run: cargo codspeed build -p turbopack-ecmascript references
- name: Run the benchmarks
uses: CodSpeedHQ/action@v4
with:
mode: instrumentation
run: cargo codspeed run -p turbopack-ecmascript references
token: ${{ secrets.CODSPEED_TOKEN }}
benchmark-large:
name: Benchmark Rust Crates (large)
if: ${{ github.event.label.name == 'benchmark' || github.event_name == 'workflow_dispatch' }}
runs-on: ['self-hosted', 'linux', 'x64', 'metal']
steps:
- uses: actions/checkout@v4
- name: Setup Rust toolchain
uses: ./.github/actions/setup-rust
- name: Install cargo-codspeed
uses: taiki-e/install-action@v2
with:
tool: cargo-codspeed@3.0.5
- name: Build the benchmark target(s)
env:
CODSPEED_RUNNER_MODE: instrumentation
run: cargo codspeed build -p turbopack -p turbopack-bench
- name: Run the benchmarks
uses: CodSpeedHQ/action@v4
with:
mode: instrumentation
run: cargo codspeed run
token: ${{ secrets.CODSPEED_TOKEN }}

View File

@@ -0,0 +1,24 @@
name: Turbopack Next.js production integration tests
on:
schedule:
- cron: '0 6 * * *'
workflow_dispatch: {}
jobs:
test-dev:
name: Next.js integration tests
uses: ./.github/workflows/integration_tests_reusable.yml
with:
name: turbopack-production
test_type: production
run_before_test: |
export IS_TURBOPACK_TEST=1 TURBOPACK_BUILD=1 RUST_BACKTRACE=1
# Failing tests take longer (due to timeouts and retries). Since we have
# many failing tests, we need smaller groups and longer timeouts, in case
# a group gets stuck with a cluster of failing tests.
e2e_groups: 12
integration_groups: 12
e2e_timeout_minutes: 60
integration_timeout_minutes: 60
secrets: inherit

View File

@@ -0,0 +1,17 @@
name: Turbopack Next.js development integration tests
on:
schedule:
- cron: '0 6 * * *'
workflow_dispatch: {}
jobs:
test-dev:
name: Next.js integration tests
uses: ./.github/workflows/integration_tests_reusable.yml
with:
name: turbopack-development
test_type: development
run_before_test: |
export IS_TURBOPACK_TEST=1 TURBOPACK_DEV=1 RUST_BACKTRACE=1
secrets: inherit

View File

@@ -0,0 +1,82 @@
# A recurring workflow which updates the passing/failing/skipped integration tests for Turbopack.
name: Update Turbopack test manifest
on:
# schedule:
# Every day at 7AM UTC https://crontab.guru/#0_7_*_*_*
# - cron: '0 7 * * *'
workflow_dispatch:
jobs:
update_dev_manifest:
name: Update and upload Turbopack development test manifest
if: github.repository_owner == 'vercel'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Commits made with the default `GITHUB_TOKEN` won't trigger workflows.
# See: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#using-the-github_token-in-a-workflow
token: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- name: Install dependencies
shell: bash
run: pnpm i
- name: Create Pull Request
shell: bash
run: node scripts/automated-update-workflow.js
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN_PULL_REQUESTS }}
BRANCH_NAME: turbopack-manifest
SCRIPT: test/update-bundler-manifest.js --bundler turbopack --test-suite dev
PR_TITLE: Update Turbopack development test manifest
PR_BODY: This auto-generated PR updates the development integration test manifest used when testing Turbopack.
update_build_manifest:
name: Update and upload Turbopack production test manifest
if: github.repository_owner == 'vercel'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Commits made with the default `GITHUB_TOKEN` won't trigger workflows.
# See: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#using-the-github_token-in-a-workflow
token: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- name: Install dependencies
shell: bash
run: pnpm i
- name: Create Pull Request
shell: bash
run: node scripts/automated-update-workflow.js
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN_PULL_REQUESTS }}
BRANCH_NAME: turbopack-manifest
SCRIPT: test/update-bundler-manifest.js --bundler turbopack --test-suite build
PR_TITLE: Update Turbopack production test manifest
PR_BODY: This auto-generated PR updates the production integration test manifest used when testing Turbopack.

48
.github/workflows/update_fonts_data.yml vendored Normal file
View File

@@ -0,0 +1,48 @@
name: Update Font Data
on:
# Run every every day at midnight https://crontab.guru/#0_0_*_*_*/1
schedule:
- cron: '0 0 * * */1'
# Allow manual runs
workflow_dispatch:
env:
NODE_LTS_VERSION: 20
jobs:
create-pull-request:
runs-on: ubuntu-latest
if: github.repository_owner == 'vercel'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Commits made with the default `GITHUB_TOKEN` won't trigger workflows.
# See: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#using-the-github_token-in-a-workflow
token: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- name: Install dependencies
shell: bash
run: pnpm i
- name: Create Pull Request
shell: bash
run: node scripts/automated-update-workflow.js
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN_PULL_REQUESTS }}
BRANCH_NAME: fonts-data
SCRIPT: scripts/update-google-fonts.js
PR_TITLE: Update font data
PR_BODY: This auto-generated PR updates font data with latest available

56
.github/workflows/update_react.yml vendored Normal file
View File

@@ -0,0 +1,56 @@
name: Update React
on:
schedule:
# At 40 minutes past 16:00 on Mon, Tue, Wed, Thu, and Fri
# i.e. 30min past React nightlies: https://github.com/facebook/react/blob/941e1b4a0a81ca3d5f2ac6ef35682e2f8e96dae1/.github/workflows/runtime_prereleases_nightly.yml#L6
# TODO: automatically trigger on React release
- cron: 40 16 * * 1,2,3,4,5
# Allow manual runs
workflow_dispatch:
inputs:
version:
description: 'The version to update to. Uses latest Canary if omitted.'
required: false
env:
NODE_LTS_VERSION: 20
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
jobs:
create-pull-request:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Commits made with the default `GITHUB_TOKEN` won't trigger workflows.
# See: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#using-the-github_token-in-a-workflow
token: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}
- name: Set Git author
run: |
git config user.name "nextjs-bot"
git config user.email "it+nextjs-bot@vercel.com"
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- name: Install dependencies
shell: bash
# Just need scripts/ but those dependencies are listed in the workspace root.
run: pnpm install --filter .
- name: Create Pull Request
shell: bash
run: pnpm sync-react --actor "${{ github.actor }}" --commit --create-pull --version "${{ inputs.version }}"
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}

View File

@@ -0,0 +1,44 @@
# Workflow to upload next.js integration test results to KV for https://areweturboyet.com/
# This workflow assumes the `next-integration-test` workflow has been executed
# and test reports have been uploaded to the `test-results` artifact.
name: Upload bundler test manifests to areweturboyet.com
on:
schedule:
- cron: '0 8 * * *'
workflow_dispatch: {}
push:
branches:
- canary
paths:
- 'test/*-manifest.json'
jobs:
upload_test_results:
name: Upload test results
runs-on: ubuntu-latest
steps:
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_LTS_VERSION }}
check-latest: true
- name: Checkout
uses: actions/checkout@v4
- name: Setup corepack
run: |
npm i -g corepack@0.31
corepack enable
- name: Install dependencies
shell: bash
run: pnpm i
- name: 'Upload results to "Are We Turbo Yet" KV'
env:
TURBOYET_KV_REST_API_URL: ${{ secrets.TURBOYET_KV_REST_API_URL }}
TURBOYET_KV_REST_API_TOKEN: ${{ secrets.TURBOYET_KV_REST_API_TOKEN }}
TURBOYET_TOKEN: ${{ secrets.TURBOYET_TOKEN }}
uses: ./.github/actions/upload-turboyet-data