Skip to content

Commit edb92a3

Browse files
authored
test: speed up isolated next instance test setup (#56525)
1 parent 3c326ea commit edb92a3

File tree

6 files changed

+115
-79
lines changed

6 files changed

+115
-79
lines changed

.github/actions/next-stats-action/src/prepare/repo-setup.js

Lines changed: 104 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
const path = require('path')
2-
const fs = require('fs-extra')
2+
const fse = require('fs-extra')
3+
const fs = require('fs')
4+
const fsp = require('fs/promises')
35
const exec = require('../util/exec')
46
const { remove } = require('fs-extra')
57
const logger = require('../util/logger')
@@ -54,11 +56,23 @@ module.exports = (actionInfo) => {
5456
},
5557
async linkPackages({ repoDir, nextSwcVersion }) {
5658
const pkgPaths = new Map()
59+
60+
/**
61+
* @typedef {Object} PkgData
62+
* @property {string} pkgDataPath Where the package.json file is located
63+
* @property {string} pkg The folder name of the package
64+
* @property {string} pkgPath The path to the package folder
65+
* @property {any} pkgData The content of package.json
66+
* @property {string} packedPkgPath The npm pack output .tgz file path
67+
*/
68+
69+
/** @type {Map<string, PkgData>} */
5770
const pkgDatas = new Map()
71+
5872
let pkgs
5973

6074
try {
61-
pkgs = await fs.readdir(path.join(repoDir, 'packages'))
75+
pkgs = await fsp.readdir(path.join(repoDir, 'packages'))
6276
} catch (err) {
6377
if (err.code === 'ENOENT') {
6478
require('console').log('no packages to link')
@@ -67,69 +81,81 @@ module.exports = (actionInfo) => {
6781
throw err
6882
}
6983

70-
for (const pkg of pkgs) {
71-
const pkgPath = path.join(repoDir, 'packages', pkg)
72-
const packedPkgPath = path.join(pkgPath, `${pkg}-packed.tgz`)
73-
74-
const pkgDataPath = path.join(pkgPath, 'package.json')
75-
if (!fs.existsSync(pkgDataPath)) {
76-
require('console').log(`Skipping ${pkgDataPath}`)
77-
continue
78-
}
79-
const pkgData = require(pkgDataPath)
80-
const { name } = pkgData
81-
82-
pkgDatas.set(name, {
83-
pkgDataPath,
84-
pkg,
85-
pkgPath,
86-
pkgData,
87-
packedPkgPath,
84+
await Promise.all(
85+
pkgs.map(async (pkg) => {
86+
const pkgPath = path.join(repoDir, 'packages', pkg)
87+
const packedPkgPath = path.join(pkgPath, `${pkg}-packed.tgz`)
88+
89+
const pkgDataPath = path.join(pkgPath, 'package.json')
90+
if (fs.existsSync(pkgDataPath)) {
91+
const pkgData = JSON.parse(await fsp.readFile(pkgDataPath))
92+
const { name } = pkgData
93+
94+
pkgDatas.set(name, {
95+
pkgDataPath,
96+
pkg,
97+
pkgPath,
98+
pkgData,
99+
packedPkgPath,
100+
})
101+
pkgPaths.set(name, packedPkgPath)
102+
} else {
103+
require('console').log(`Skipping ${pkgDataPath}`)
104+
}
88105
})
89-
pkgPaths.set(name, packedPkgPath)
90-
}
91-
92-
for (const pkg of pkgDatas.keys()) {
93-
const { pkgDataPath, pkgData } = pkgDatas.get(pkg)
106+
)
94107

95-
for (const pkg of pkgDatas.keys()) {
96-
const { packedPkgPath } = pkgDatas.get(pkg)
108+
for (const [
109+
pkg,
110+
{ pkgDataPath, pkgData, pkgPath },
111+
] of pkgDatas.entries()) {
112+
// update the current package dependencies to point to packed tgz path
113+
for (const [pkg, { packedPkgPath }] of pkgDatas.entries()) {
97114
if (!pkgData.dependencies || !pkgData.dependencies[pkg]) continue
98115
pkgData.dependencies[pkg] = packedPkgPath
99116
}
100117

101118
// make sure native binaries are included in local linking
102119
if (pkg === '@next/swc') {
103-
if (!pkgData.files) {
104-
pkgData.files = []
105-
}
120+
pkgData.files ||= []
121+
106122
pkgData.files.push('native')
107-
require('console').log(
108-
'using swc binaries: ',
109-
await exec(`ls ${path.join(path.dirname(pkgDataPath), 'native')}`)
110-
)
111-
}
112123

113-
if (pkg === 'next') {
124+
try {
125+
const swcBinariesDirContents = await fsp.readdir(
126+
path.join(pkgPath, 'native')
127+
)
128+
require('console').log(
129+
'using swc binaries: ',
130+
swcBinariesDirContents.join(', ')
131+
)
132+
} catch (err) {
133+
if (err.code === 'ENOENT') {
134+
require('console').log('swc binaries dir is missing!')
135+
}
136+
throw err
137+
}
138+
} else if (pkg === 'next') {
139+
const nextSwcPkg = pkgDatas.get('@next/swc')
140+
114141
console.log('using swc dep', {
115142
nextSwcVersion,
116-
nextSwcPkg: pkgDatas.get('@next/swc'),
143+
nextSwcPkg,
117144
})
118145
if (nextSwcVersion) {
119146
Object.assign(pkgData.dependencies, {
120147
'@next/swc-linux-x64-gnu': nextSwcVersion,
121148
})
122149
} else {
123-
if (pkgDatas.get('@next/swc')) {
124-
pkgData.dependencies['@next/swc'] =
125-
pkgDatas.get('@next/swc').packedPkgPath
150+
if (nextSwcPkg) {
151+
pkgData.dependencies['@next/swc'] = nextSwcPkg.packedPkgPath
126152
} else {
127153
pkgData.files.push('native')
128154
}
129155
}
130156
}
131157

132-
await fs.writeFile(
158+
await fsp.writeFile(
133159
pkgDataPath,
134160
JSON.stringify(pkgData, null, 2),
135161
'utf8'
@@ -139,41 +165,47 @@ module.exports = (actionInfo) => {
139165
// wait to pack packages until after dependency paths have been updated
140166
// to the correct versions
141167
await Promise.all(
142-
Array.from(pkgDatas.keys()).map(async (pkgName) => {
143-
const { pkgPath, packedPkgPath } = pkgDatas.get(pkgName)
144-
145-
let cleanup = null
146-
147-
if (pkgName === '@next/swc') {
148-
// next-swc uses a gitignore to prevent the committing of native builds but it doesn't
149-
// use files in package.json because it publishes to individual packages based on architecture.
150-
// When we used yarn to pack these packages the gitignore was ignored so the native builds were packed
151-
// however npm does respect gitignore when packing so we need to remove it in this specific case
152-
// to ensure the native builds are packed for use in gh actions and related scripts
153-
await fs.rename(
154-
path.join(pkgPath, 'native/.gitignore'),
155-
path.join(pkgPath, 'disabled-native-gitignore')
156-
)
157-
cleanup = async () => {
158-
await fs.rename(
159-
path.join(pkgPath, 'disabled-native-gitignore'),
160-
path.join(pkgPath, 'native/.gitignore')
168+
Array.from(pkgDatas.entries()).map(
169+
async ([pkgName, { pkgPath, packedPkgPath }]) => {
170+
/** @type {null | () => Promise<void>} */
171+
let cleanup = null
172+
173+
if (pkgName === '@next/swc') {
174+
// next-swc uses a gitignore to prevent the committing of native builds but it doesn't
175+
// use files in package.json because it publishes to individual packages based on architecture.
176+
// When we used yarn to pack these packages the gitignore was ignored so the native builds were packed
177+
// however npm does respect gitignore when packing so we need to remove it in this specific case
178+
// to ensure the native builds are packed for use in gh actions and related scripts
179+
180+
const nativeGitignorePath = path.join(
181+
pkgPath,
182+
'native/.gitignore'
183+
)
184+
const renamedGitignorePath = path.join(
185+
pkgPath,
186+
'disabled-native-gitignore'
161187
)
188+
189+
await fsp.rename(nativeGitignorePath, renamedGitignorePath)
190+
cleanup = async () => {
191+
await fsp.rename(renamedGitignorePath, nativeGitignorePath)
192+
}
162193
}
163-
}
164194

165-
const { stdout } = await execa('npm', ['pack'], {
166-
cwd: pkgPath,
167-
env: {
168-
...process.env,
169-
COREPACK_ENABLE_STRICT: '0',
170-
},
171-
})
172-
await fs.rename(path.resolve(pkgPath, stdout.trim()), packedPkgPath)
173-
if (cleanup) {
174-
await cleanup()
195+
const { stdout } = await execa('pnpm', ['pack'], {
196+
cwd: pkgPath,
197+
env: {
198+
...process.env,
199+
COREPACK_ENABLE_STRICT: '0',
200+
},
201+
})
202+
203+
return Promise.all([
204+
fsp.rename(path.resolve(pkgPath, stdout.trim()), packedPkgPath),
205+
cleanup?.(),
206+
])
175207
}
176-
})
208+
)
177209
)
178210
return pkgPaths
179211
},

.github/workflows/build_and_deploy.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ jobs:
254254
with:
255255
node-version: ${{ env.NODE_LTS_VERSION }}
256256
check-latest: true
257+
- run: corepack enable
257258

258259
- name: Install Rust
259260
uses: ./.github/actions/setup-rust

.github/workflows/build_and_test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ jobs:
5858
- uses: actions/setup-node@v3
5959
with:
6060
node-version: 18
61+
- run: corepack enable
6162
- name: 'Run link checker'
6263
run: node ./.github/actions/validate-docs-links/lib
6364
env:

.github/workflows/code_freeze.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ jobs:
3232
with:
3333
node-version: 18
3434
check-latest: true
35+
- run: corepack enable
3536

3637
- run: git clone https://github.com/vercel/next.js.git --depth=1 .
3738

.github/workflows/pull_request_approved.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ jobs:
1414
- uses: actions/setup-node@v3
1515
with:
1616
node-version: 18
17+
- run: corepack enable
1718
- name: 'Send notification to Slack'
1819
run: node ./.github/actions/pr-approved-open/index.mjs
1920
env:

test/lib/create-next-install.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ const { linkPackages } =
1616
* @param {string} cwd - The project directory where pnpm configuration is set.
1717
* @returns {Promise<void>}
1818
*/
19-
async function setPnpmResolutionMode(cwd) {
20-
await execa(
19+
function setPnpmResolutionMode(cwd) {
20+
return execa(
2121
'pnpm',
2222
['config', 'set', '--location=project', 'resolution-mode', 'highest'],
2323
{
@@ -99,8 +99,8 @@ async function createNextInstall({
9999
for (const item of ['package.json', 'packages']) {
100100
await rootSpan
101101
.traceChild(`copy ${item} to temp dir`)
102-
.traceAsyncFn(async () => {
103-
await fs.copy(
102+
.traceAsyncFn(() =>
103+
fs.copy(
104104
path.join(origRepoDir, item),
105105
path.join(tmpRepoDir, item),
106106
{
@@ -116,7 +116,7 @@ async function createNextInstall({
116116
},
117117
}
118118
)
119-
})
119+
)
120120
}
121121

122122
pkgPaths = await rootSpan.traceChild('linkPackages').traceAsyncFn(() =>
@@ -177,7 +177,7 @@ async function createNextInstall({
177177
} else {
178178
await rootSpan
179179
.traceChild('run generic install command')
180-
.traceAsyncFn(async () => {
180+
.traceAsyncFn(() => {
181181
const args = [
182182
'install',
183183
'--strict-peer-dependencies=false',
@@ -188,7 +188,7 @@ async function createNextInstall({
188188
args.push('--prefer-offline')
189189
}
190190

191-
await execa('pnpm', args, {
191+
return execa('pnpm', args, {
192192
cwd: installDir,
193193
stdio: ['ignore', 'inherit', 'inherit'],
194194
env: process.env,

0 commit comments

Comments
 (0)