diff --git a/.github/actions/next-stats-action/src/prepare/repo-setup.js b/.github/actions/next-stats-action/src/prepare/repo-setup.js index 660a6f4a0b012..74fd6ea1fc925 100644 --- a/.github/actions/next-stats-action/src/prepare/repo-setup.js +++ b/.github/actions/next-stats-action/src/prepare/repo-setup.js @@ -1,5 +1,7 @@ const path = require('path') -const fs = require('fs-extra') +const fse = require('fs-extra') +const fs = require('fs') +const fsp = require('fs/promises') const exec = require('../util/exec') const { remove } = require('fs-extra') const logger = require('../util/logger') @@ -54,11 +56,23 @@ module.exports = (actionInfo) => { }, async linkPackages({ repoDir, nextSwcVersion }) { const pkgPaths = new Map() + + /** + * @typedef {Object} PkgData + * @property {string} pkgDataPath Where the package.json file is located + * @property {string} pkg The folder name of the package + * @property {string} pkgPath The path to the package folder + * @property {any} pkgData The content of package.json + * @property {string} packedPkgPath The npm pack output .tgz file path + */ + + /** @type {Map} */ const pkgDatas = new Map() + let pkgs try { - pkgs = await fs.readdir(path.join(repoDir, 'packages')) + pkgs = await fsp.readdir(path.join(repoDir, 'packages')) } catch (err) { if (err.code === 'ENOENT') { require('console').log('no packages to link') @@ -67,69 +81,81 @@ module.exports = (actionInfo) => { throw err } - for (const pkg of pkgs) { - const pkgPath = path.join(repoDir, 'packages', pkg) - const packedPkgPath = path.join(pkgPath, `${pkg}-packed.tgz`) - - const pkgDataPath = path.join(pkgPath, 'package.json') - if (!fs.existsSync(pkgDataPath)) { - require('console').log(`Skipping ${pkgDataPath}`) - continue - } - const pkgData = require(pkgDataPath) - const { name } = pkgData - - pkgDatas.set(name, { - pkgDataPath, - pkg, - pkgPath, - pkgData, - packedPkgPath, + await Promise.all( + pkgs.map(async (pkg) => { + const pkgPath = path.join(repoDir, 'packages', pkg) + const packedPkgPath = path.join(pkgPath, `${pkg}-packed.tgz`) + + const pkgDataPath = path.join(pkgPath, 'package.json') + if (fs.existsSync(pkgDataPath)) { + const pkgData = JSON.parse(await fsp.readFile(pkgDataPath)) + const { name } = pkgData + + pkgDatas.set(name, { + pkgDataPath, + pkg, + pkgPath, + pkgData, + packedPkgPath, + }) + pkgPaths.set(name, packedPkgPath) + } else { + require('console').log(`Skipping ${pkgDataPath}`) + } }) - pkgPaths.set(name, packedPkgPath) - } - - for (const pkg of pkgDatas.keys()) { - const { pkgDataPath, pkgData } = pkgDatas.get(pkg) + ) - for (const pkg of pkgDatas.keys()) { - const { packedPkgPath } = pkgDatas.get(pkg) + for (const [ + pkg, + { pkgDataPath, pkgData, pkgPath }, + ] of pkgDatas.entries()) { + // update the current package dependencies to point to packed tgz path + for (const [pkg, { packedPkgPath }] of pkgDatas.entries()) { if (!pkgData.dependencies || !pkgData.dependencies[pkg]) continue pkgData.dependencies[pkg] = packedPkgPath } // make sure native binaries are included in local linking if (pkg === '@next/swc') { - if (!pkgData.files) { - pkgData.files = [] - } + pkgData.files ||= [] + pkgData.files.push('native') - require('console').log( - 'using swc binaries: ', - await exec(`ls ${path.join(path.dirname(pkgDataPath), 'native')}`) - ) - } - if (pkg === 'next') { + try { + const swcBinariesDirContents = await fsp.readdir( + path.join(pkgPath, 'native') + ) + require('console').log( + 'using swc binaries: ', + swcBinariesDirContents.join(', ') + ) + } catch (err) { + if (err.code === 'ENOENT') { + require('console').log('swc binaries dir is missing!') + } + throw err + } + } else if (pkg === 'next') { + const nextSwcPkg = pkgDatas.get('@next/swc') + console.log('using swc dep', { nextSwcVersion, - nextSwcPkg: pkgDatas.get('@next/swc'), + nextSwcPkg, }) if (nextSwcVersion) { Object.assign(pkgData.dependencies, { '@next/swc-linux-x64-gnu': nextSwcVersion, }) } else { - if (pkgDatas.get('@next/swc')) { - pkgData.dependencies['@next/swc'] = - pkgDatas.get('@next/swc').packedPkgPath + if (nextSwcPkg) { + pkgData.dependencies['@next/swc'] = nextSwcPkg.packedPkgPath } else { pkgData.files.push('native') } } } - await fs.writeFile( + await fsp.writeFile( pkgDataPath, JSON.stringify(pkgData, null, 2), 'utf8' @@ -139,41 +165,47 @@ module.exports = (actionInfo) => { // wait to pack packages until after dependency paths have been updated // to the correct versions await Promise.all( - Array.from(pkgDatas.keys()).map(async (pkgName) => { - const { pkgPath, packedPkgPath } = pkgDatas.get(pkgName) - - let cleanup = null - - if (pkgName === '@next/swc') { - // next-swc uses a gitignore to prevent the committing of native builds but it doesn't - // use files in package.json because it publishes to individual packages based on architecture. - // When we used yarn to pack these packages the gitignore was ignored so the native builds were packed - // however npm does respect gitignore when packing so we need to remove it in this specific case - // to ensure the native builds are packed for use in gh actions and related scripts - await fs.rename( - path.join(pkgPath, 'native/.gitignore'), - path.join(pkgPath, 'disabled-native-gitignore') - ) - cleanup = async () => { - await fs.rename( - path.join(pkgPath, 'disabled-native-gitignore'), - path.join(pkgPath, 'native/.gitignore') + Array.from(pkgDatas.entries()).map( + async ([pkgName, { pkgPath, packedPkgPath }]) => { + /** @type {null | () => Promise} */ + let cleanup = null + + if (pkgName === '@next/swc') { + // next-swc uses a gitignore to prevent the committing of native builds but it doesn't + // use files in package.json because it publishes to individual packages based on architecture. + // When we used yarn to pack these packages the gitignore was ignored so the native builds were packed + // however npm does respect gitignore when packing so we need to remove it in this specific case + // to ensure the native builds are packed for use in gh actions and related scripts + + const nativeGitignorePath = path.join( + pkgPath, + 'native/.gitignore' + ) + const renamedGitignorePath = path.join( + pkgPath, + 'disabled-native-gitignore' ) + + await fsp.rename(nativeGitignorePath, renamedGitignorePath) + cleanup = async () => { + await fsp.rename(renamedGitignorePath, nativeGitignorePath) + } } - } - const { stdout } = await execa('npm', ['pack'], { - cwd: pkgPath, - env: { - ...process.env, - COREPACK_ENABLE_STRICT: '0', - }, - }) - await fs.rename(path.resolve(pkgPath, stdout.trim()), packedPkgPath) - if (cleanup) { - await cleanup() + const { stdout } = await execa('pnpm', ['pack'], { + cwd: pkgPath, + env: { + ...process.env, + COREPACK_ENABLE_STRICT: '0', + }, + }) + + return Promise.all([ + fsp.rename(path.resolve(pkgPath, stdout.trim()), packedPkgPath), + cleanup?.(), + ]) } - }) + ) ) return pkgPaths }, diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml index 44798960f3a69..93648a7ae05c5 100644 --- a/.github/workflows/build_and_deploy.yml +++ b/.github/workflows/build_and_deploy.yml @@ -254,6 +254,7 @@ jobs: with: node-version: ${{ env.NODE_LTS_VERSION }} check-latest: true + - run: corepack enable - name: Install Rust uses: ./.github/actions/setup-rust diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 9b18c42aa0ec8..1f4d50d639ed3 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -58,6 +58,7 @@ jobs: - uses: actions/setup-node@v3 with: node-version: 18 + - run: corepack enable - name: 'Run link checker' run: node ./.github/actions/validate-docs-links/lib env: diff --git a/.github/workflows/code_freeze.yml b/.github/workflows/code_freeze.yml index 513390827cc88..3c4c8b23f6bf4 100644 --- a/.github/workflows/code_freeze.yml +++ b/.github/workflows/code_freeze.yml @@ -32,6 +32,7 @@ jobs: with: node-version: 18 check-latest: true + - run: corepack enable - run: git clone https://github.com/vercel/next.js.git --depth=1 . diff --git a/.github/workflows/pull_request_approved.yml b/.github/workflows/pull_request_approved.yml index 4dec0271a80d6..77519be02f1a6 100644 --- a/.github/workflows/pull_request_approved.yml +++ b/.github/workflows/pull_request_approved.yml @@ -14,6 +14,7 @@ jobs: - uses: actions/setup-node@v3 with: node-version: 18 + - run: corepack enable - name: 'Send notification to Slack' run: node ./.github/actions/pr-approved-open/index.mjs env: diff --git a/test/lib/create-next-install.js b/test/lib/create-next-install.js index 1674921389b43..6ebe3899f58fd 100644 --- a/test/lib/create-next-install.js +++ b/test/lib/create-next-install.js @@ -16,8 +16,8 @@ const { linkPackages } = * @param {string} cwd - The project directory where pnpm configuration is set. * @returns {Promise} */ -async function setPnpmResolutionMode(cwd) { - await execa( +function setPnpmResolutionMode(cwd) { + return execa( 'pnpm', ['config', 'set', '--location=project', 'resolution-mode', 'highest'], { @@ -99,8 +99,8 @@ async function createNextInstall({ for (const item of ['package.json', 'packages']) { await rootSpan .traceChild(`copy ${item} to temp dir`) - .traceAsyncFn(async () => { - await fs.copy( + .traceAsyncFn(() => + fs.copy( path.join(origRepoDir, item), path.join(tmpRepoDir, item), { @@ -116,7 +116,7 @@ async function createNextInstall({ }, } ) - }) + ) } pkgPaths = await rootSpan.traceChild('linkPackages').traceAsyncFn(() => @@ -177,7 +177,7 @@ async function createNextInstall({ } else { await rootSpan .traceChild('run generic install command') - .traceAsyncFn(async () => { + .traceAsyncFn(() => { const args = [ 'install', '--strict-peer-dependencies=false', @@ -188,7 +188,7 @@ async function createNextInstall({ args.push('--prefer-offline') } - await execa('pnpm', args, { + return execa('pnpm', args, { cwd: installDir, stdio: ['ignore', 'inherit', 'inherit'], env: process.env,