Skip to content

Commit 7875f73

Browse files
authored
Merge branch 'main' into release-please--branches--main--components--plugin-nextjs
2 parents afac137 + 63bedeb commit 7875f73

File tree

6 files changed

+149
-51
lines changed

6 files changed

+149
-51
lines changed

.github/workflows/run-tests.yml

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,23 @@ jobs:
5252

5353
steps:
5454
- uses: actions/checkout@v5
55+
- name: Decide Node Version
56+
id: decide-node-version
57+
shell: bash
58+
run: |
59+
NODE_VERSION=18.x
60+
if [ "${{ matrix.version}}" = "canary" ]; then
61+
# this is not ideal, because we set node@20 just when explicitly using canary tag as target
62+
# but next@canary are still on 15 major, so we can't yet use major version of resolved next version
63+
# as condition
64+
NODE_VERSION=20.x
65+
fi
66+
echo "version=$NODE_VERSION" >> $GITHUB_OUTPUT
67+
echo "Node version for 'next@${{ matrix.version }}' is '$NODE_VERSION'"
5568
- name: 'Install Node'
5669
uses: actions/setup-node@v4
5770
with:
58-
node-version: '20.x'
71+
node-version: ${{ steps.decide-node-version.outputs.version }}
5972
cache: 'npm'
6073
cache-dependency-path: '**/package-lock.json'
6174
- uses: oven-sh/setup-bun@v2
@@ -118,7 +131,7 @@ jobs:
118131
fail-fast: false
119132
matrix:
120133
shard: [1, 2, 3, 4, 5, 6, 7, 8]
121-
os: [ubuntu-latest, windows-2025]
134+
os: [ubuntu-latest]
122135
version: ${{ fromJson(needs.setup.outputs.matrix) }}
123136
exclude:
124137
- os: windows-2025
@@ -128,10 +141,23 @@ jobs:
128141
runs-on: ${{ matrix.os }}
129142
steps:
130143
- uses: actions/checkout@v5
144+
- name: Decide Node Version
145+
id: decide-node-version
146+
shell: bash
147+
run: |
148+
NODE_VERSION=18.x
149+
if [ "${{ matrix.version}}" = "canary" ]; then
150+
# this is not ideal, because we set node@20 just when explicitly using canary tag as target
151+
# but next@canary are still on 15 major, so we can't yet use major version of resolved next version
152+
# as condition
153+
NODE_VERSION=20.x
154+
fi
155+
echo "version=$NODE_VERSION" >> $GITHUB_OUTPUT
156+
echo "Node version for 'next@${{ matrix.version }}' is '$NODE_VERSION'"
131157
- name: 'Install Node'
132158
uses: actions/setup-node@v4
133159
with:
134-
node-version: '20.x'
160+
node-version: ${{ steps.decide-node-version.outputs.version }}
135161
cache: 'npm'
136162
cache-dependency-path: '**/package-lock.json'
137163
- name: Prefer npm global on windows
@@ -205,10 +231,23 @@ jobs:
205231
version: ${{ fromJson(needs.setup.outputs.matrix) }}
206232
steps:
207233
- uses: actions/checkout@v5
234+
- name: Decide Node Version
235+
id: decide-node-version
236+
shell: bash
237+
run: |
238+
NODE_VERSION=18.x
239+
if [ "${{ matrix.version}}" = "canary" ]; then
240+
# this is not ideal, because we set node@20 just when explicitly using canary tag as target
241+
# but next@canary are still on 15 major, so we can't yet use major version of resolved next version
242+
# as condition
243+
NODE_VERSION=20.x
244+
fi
245+
echo "version=$NODE_VERSION" >> $GITHUB_OUTPUT
246+
echo "Node version for 'next@${{ matrix.version }}' is '$NODE_VERSION'"
208247
- name: 'Install Node'
209248
uses: actions/setup-node@v4
210249
with:
211-
node-version: '20.x'
250+
node-version: ${{ steps.decide-node-version.outputs.version }}
212251
cache: 'npm'
213252
cache-dependency-path: '**/package-lock.json'
214253
- name: setup pnpm/yarn

.github/workflows/test-e2e.yml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ concurrency:
1919
cancel-in-progress: true
2020

2121
env:
22-
NODE_VERSION: 20.9.0
2322
PNPM_VERSION: 8.9.0
2423
NEXT_REPO: vercel/next.js
2524
NEXT_TEST_MODE: deploy
@@ -111,10 +110,24 @@ jobs:
111110
with:
112111
path: ${{ env.runtime-path }}
113112

113+
- name: Decide Node Version
114+
id: decide-node-version
115+
shell: bash
116+
run: |
117+
NODE_VERSION=18.x
118+
if [ "${{ matrix.version_spec.selector }}" = "canary" ]; then
119+
# this is not ideal, because we set node@20 just when explicitly using canary tag as target
120+
# but next@canary are still on 15 major, so we can't yet use major version of resolved next version
121+
# as condition
122+
NODE_VERSION=20.x
123+
fi
124+
echo "version=$NODE_VERSION" >> $GITHUB_OUTPUT
125+
echo "Node version for 'next@${{ matrix.version_spec.selector }}' is '$NODE_VERSION'"
126+
114127
- name: setup node
115128
uses: actions/setup-node@v4
116129
with:
117-
node-version: ${{ env.NODE_VERSION }}
130+
node-version: ${{ steps.decide-node-version.outputs.version }}
118131

119132
- name: setup pnpm/yarn
120133
run: corepack enable

tests/prepare.mjs

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,12 @@ const promises = fixtures.map((fixture) =>
6060
})
6161
await Promise.all(publishDirectories.map((dir) => rm(dir, { recursive: true, force: true })))
6262

63-
if (NEXT_VERSION !== 'latest') {
64-
await setNextVersionInFixture(cwd, NEXT_VERSION, {
65-
logPrefix: `[${fixture}] `,
66-
})
63+
const fixtureNextVersionSatisfied = await setNextVersionInFixture(cwd, NEXT_VERSION, {
64+
logPrefix: `[${fixture}] `,
65+
})
66+
67+
if (!fixtureNextVersionSatisfied) {
68+
return
6769
}
6870

6971
let cmd = ``
@@ -79,19 +81,26 @@ const promises = fixtures.map((fixture) =>
7981
await rm(join(cwd, 'package-lock.json'), { force: true })
8082
}
8183

82-
const addPrefix = new Transform({
83-
transform(chunk, encoding, callback) {
84-
this.push(chunk.toString().replace(/\n/gm, `\n[${fixture}] `))
85-
callback()
86-
},
87-
flush(callback) {
88-
// final transform might create non-terminated line with a prefix
89-
// so this is just to make sure we end with a newline so further writes
90-
// to same destination stream start on a new line for better readability
91-
this.push('\n')
92-
callback()
93-
},
94-
})
84+
const addPrefix = () => {
85+
let isFirstChunk = true
86+
return new Transform({
87+
transform(chunk, encoding, callback) {
88+
if (isFirstChunk) {
89+
this.push(`[${fixture}] `)
90+
isFirstChunk = false
91+
}
92+
this.push(chunk.toString().replace(/\n/gm, `\n[${fixture}] `))
93+
callback()
94+
},
95+
flush(callback) {
96+
// final transform might create non-terminated line with a prefix
97+
// so this is just to make sure we end with a newline so further writes
98+
// to same destination stream start on a new line for better readability
99+
this.push('\n')
100+
callback()
101+
},
102+
})
103+
}
95104

96105
console.log(`[${fixture}] Running \`${cmd}\`...`)
97106
const output = execaCommand(cmd, {
@@ -100,16 +109,24 @@ const promises = fixtures.map((fixture) =>
100109
env: { ...process.env, FORCE_COLOR: '1' },
101110
})
102111
if (process.env.DEBUG) {
103-
output.stdout?.pipe(addPrefix).pipe(process.stdout)
112+
output.stdout?.pipe(addPrefix()).pipe(process.stdout)
104113
}
105-
output.stderr?.pipe(addPrefix).pipe(process.stderr)
114+
output.stderr?.pipe(addPrefix()).pipe(process.stderr)
106115
return output.finally(async () => {
107-
if (NEXT_VERSION !== 'latest') {
108-
await setNextVersionInFixture(cwd, 'latest', {
109-
logPrefix: `[${fixture}] `,
110-
operation: 'revert',
111-
})
116+
if (process.env.DEBUG) {
117+
const npmListPromise = execaCommand(
118+
packageManager?.startsWith('pnpm') ? 'pnpm list next' : 'npm list next',
119+
{ cwd, stdio: 'pipe', reject: false },
120+
)
121+
npmListPromise.stdout?.pipe(addPrefix()).pipe(process.stdout)
122+
npmListPromise.stderr?.pipe(addPrefix()).pipe(process.stderr)
123+
await npmListPromise
112124
}
125+
126+
await setNextVersionInFixture(cwd, 'latest', {
127+
logPrefix: `[${fixture}] `,
128+
operation: 'revert',
129+
})
113130
if (output.exitCode !== 0) {
114131
const errorMessage = `[${fixture}] 🚨 Failed to install dependencies or build a fixture`
115132
console.error(errorMessage)

tests/utils/create-e2e-fixture.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ export const createE2EFixture = async (fixture: string, config: E2EConfig = {})
7878
copyFixture(fixture, isolatedFixtureRoot, config),
7979
])
8080

81-
if (NEXT_VERSION !== 'latest') {
82-
await setNextVersionInFixture(isolatedFixtureRoot, NEXT_VERSION)
83-
}
81+
await setNextVersionInFixture(isolatedFixtureRoot, NEXT_VERSION)
8482
await installRuntime(packageName, isolatedFixtureRoot, config)
8583
await verifyFixture(isolatedFixtureRoot, config)
8684

tests/utils/fixture.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,27 @@ const eszipHelper = join(actualCwd, 'tools/deno/eszip.ts')
3939

4040
async function installDependencies(cwd: string) {
4141
const NEXT_VERSION = process.env.NEXT_VERSION ?? 'latest'
42-
if (NEXT_VERSION !== 'latest') {
43-
await setNextVersionInFixture(cwd, NEXT_VERSION, { silent: true })
44-
}
42+
await setNextVersionInFixture(cwd, NEXT_VERSION, { silent: true })
4543

4644
const { packageManager } = JSON.parse(await readFile(join(cwd, 'package.json'), 'utf8'))
4745
if (packageManager?.startsWith('pnpm')) {
48-
return execaCommand(`pnpm install --ignore-scripts --reporter=silent`, {
46+
await execaCommand(`pnpm install --ignore-scripts --reporter=silent`, {
4947
cwd,
5048
})
49+
} else {
50+
await execaCommand(
51+
`npm install --ignore-scripts --no-audit --progress=false --legacy-peer-deps`,
52+
{ cwd },
53+
)
54+
}
55+
56+
if (process.env.DEBUG) {
57+
await execaCommand(packageManager?.startsWith('pnpm') ? `pnpm list next` : 'npm list next', {
58+
cwd,
59+
stdio: 'inherit',
60+
reject: false,
61+
})
5162
}
52-
return execaCommand(
53-
`npm install --ignore-scripts --no-audit --progress=false --legacy-peer-deps`,
54-
{ cwd },
55-
)
5663
}
5764

5865
export const getFixtureSourceDirectory = (fixture: string) =>

tests/utils/next-version-helpers.mjs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export function nextVersionRequiresReact19(version) {
7070
* @param {'update' | 'revert'} [options.operation] This just informs log output wording, otherwise it has no effect
7171
* @param {boolean} [options.silent] Doesn't produce any logs if truthy
7272
* @param {boolean} [options.updateReact] Update React version to match Next version
73-
* @returns {Promise<void>}
73+
* @returns {Promise<boolean>} true if fixture's next version requirements are satisfied
7474
*/
7575
export async function setNextVersionInFixture(
7676
cwd,
@@ -87,20 +87,14 @@ export async function setNextVersionInFixture(
8787
// if resolved version is different from version, we add it to the log to provide additional details
8888
const nextVersionForLogs = `next@${version}${resolvedVersion !== version ? ` (${resolvedVersion})` : ``}`
8989

90-
if (!silent) {
91-
console.log(
92-
`${logPrefix}${operation === 'revert' ? 'Reverting' : 'Updating'} to ${nextVersionForLogs}...`,
93-
)
94-
}
95-
9690
const packageJsons = await fg.glob(['**/package.json', '!**/node_modules'], {
9791
cwd,
9892
absolute: true,
9993
})
10094

10195
const isSemverVersion = valid(resolvedVersion)
10296

103-
await Promise.all(
97+
const areNextVersionConstraintsSatisfied = await Promise.all(
10498
packageJsons.map(async (packageJsonPath) => {
10599
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'))
106100
if (packageJson.dependencies?.next) {
@@ -110,17 +104,45 @@ export async function setNextVersionInFixture(
110104
if (
111105
operation === 'update' &&
112106
versionConstraint &&
113-
!satisfies(checkVersion, versionConstraint, { includePrerelease: true }) &&
107+
!(versionConstraint === 'canary'
108+
? isNextCanary()
109+
: satisfies(checkVersion, versionConstraint, { includePrerelease: true })) &&
114110
version !== versionConstraint
115111
) {
116112
if (!silent) {
117113
console.log(
118114
`${logPrefix}⏩ Skipping '${packageJson.name}' because it requires next@${versionConstraint}`,
119115
)
120116
}
121-
return
117+
return false
122118
}
119+
}
120+
return true
121+
}),
122+
)
123+
124+
if (areNextVersionConstraintsSatisfied.some((isSatisfied) => !isSatisfied)) {
125+
// at least one next version constraint is not satisfied so we skip this fixture
126+
return false
127+
}
128+
129+
if ((process.env.NEXT_VERSION ?? 'latest') === 'latest') {
130+
// latest is default so we don't want to make any changes
131+
return true
132+
}
133+
134+
if (!silent) {
135+
console.log(
136+
`${logPrefix}${operation === 'revert' ? 'Reverting' : 'Updating'} to ${nextVersionForLogs}...`,
137+
)
138+
}
139+
140+
await Promise.all(
141+
packageJsons.map(async (packageJsonPath) => {
142+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'))
143+
if (packageJson.dependencies?.next) {
123144
packageJson.dependencies.next = version
145+
const checkVersion = isSemverVersion ? resolvedVersion : FUTURE_NEXT_PATCH_VERSION
124146

125147
const { stdout } = await execaCommand(
126148
`npm info next@${resolvedVersion} peerDependencies --json`,
@@ -172,4 +194,6 @@ export async function setNextVersionInFixture(
172194
`${logPrefix}${operation === 'revert' ? 'Reverted' : 'Updated'} to ${nextVersionForLogs}`,
173195
)
174196
}
197+
198+
return true
175199
}

0 commit comments

Comments
 (0)