From d8193ca947b4bfdd2863698bcaaa428d0899699b Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Mon, 12 May 2025 19:22:14 -0700 Subject: [PATCH] devops: consolidate build.js files (#35935) --- packages/playwright-client/build.js | 51 -------- .../playwright-core/bundles/utils/build.js | 67 ---------- .../bundles/utils/package.json | 6 - packages/playwright-core/bundles/zip/build.js | 51 -------- .../playwright-core/bundles/zip/package.json | 6 - packages/playwright/bundles/babel/build.js | 52 -------- .../playwright/bundles/babel/package.json | 6 - packages/playwright/bundles/expect/build.js | 51 -------- .../playwright/bundles/expect/package.json | 6 - packages/playwright/bundles/utils/build.js | 52 -------- .../playwright/bundles/utils/package.json | 6 - utils/build/build.js | 117 ++++++++++++++---- 12 files changed, 92 insertions(+), 379 deletions(-) delete mode 100644 packages/playwright-client/build.js delete mode 100644 packages/playwright-core/bundles/utils/build.js delete mode 100644 packages/playwright-core/bundles/zip/build.js delete mode 100644 packages/playwright/bundles/babel/build.js delete mode 100644 packages/playwright/bundles/expect/build.js delete mode 100644 packages/playwright/bundles/utils/build.js diff --git a/packages/playwright-client/build.js b/packages/playwright-client/build.js deleted file mode 100644 index 0b7213708d2d3..0000000000000 --- a/packages/playwright-client/build.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// @ts-check -const path = require('path'); -const esbuild = require('esbuild'); - - -/** - * @param {boolean} watchMode - * @returns {import('esbuild').BuildOptions} - */ -function esbuildOptions(watchMode) { - return { - entryPoints: [path.join(__dirname, 'src/index.ts')], - bundle: true, - outdir: path.join(__dirname, 'lib'), - format: 'cjs', - platform: 'node', - target: 'ES2019', - sourcemap: watchMode, - }; -} - -async function main() { - const watchMode = process.argv.includes('--watch'); - const ctx = await esbuild.context(esbuildOptions(watchMode)); - await ctx.rebuild(); - if (watchMode) - await ctx.watch(); - else - await ctx.dispose(); -} - -module.exports = { esbuildOptions }; - -if (require.main === module) - main(); diff --git a/packages/playwright-core/bundles/utils/build.js b/packages/playwright-core/bundles/utils/build.js deleted file mode 100644 index fbd276deb56f7..0000000000000 --- a/packages/playwright-core/bundles/utils/build.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// @ts-check -const path = require('path'); -const esbuild = require('esbuild'); -const fs = require('fs'); - -const outdir = path.join(__dirname, '../../lib/utilsBundleImpl'); - -function copyXdgOpen() { - if (!fs.existsSync(outdir)) - fs.mkdirSync(outdir, { recursive: true }); - - // 'open' package requires 'xdg-open' binary to be present, which does not get bundled by esbuild. - fs.copyFileSync(path.join(__dirname, 'node_modules/open/xdg-open'), path.join(outdir, 'xdg-open')); - console.log('==== Copied xdg-open to', path.join(outdir, 'xdg-open')); -} - -/** - * @param {boolean} watchMode - * @returns {import('esbuild').BuildOptions} - */ -function esbuildOptions(watchMode) { - return { - entryPoints: [path.join(__dirname, 'src/utilsBundleImpl.ts')], - bundle: true, - outfile: path.join(outdir, 'index.js'), - format: 'cjs', - platform: 'node', - target: 'ES2019', - sourcemap: watchMode, - minify: !watchMode, - }; -} - -async function main() { - copyXdgOpen(); - const watchMode = process.argv.includes('--watch'); - const ctx = await esbuild.context(esbuildOptions(watchMode)); - await ctx.rebuild(); - if (watchMode) - await ctx.watch(); - else - await ctx.dispose(); -} - -module.exports = { - beforeEsbuild: copyXdgOpen, - esbuildOptions, -}; - -if (require.main === module) - main(); diff --git a/packages/playwright-core/bundles/utils/package.json b/packages/playwright-core/bundles/utils/package.json index 4944b7b078462..7e7ff502ba7bc 100644 --- a/packages/playwright-core/bundles/utils/package.json +++ b/packages/playwright-core/bundles/utils/package.json @@ -2,12 +2,6 @@ "name": "utils-bundle", "version": "0.0.1", "private": true, - "scripts": { - "esbuild": "node build.js", - "build": "npm run esbuild", - "watch": "npm run esbuild -- --watch", - "generate-license": "node ../../../../utils/generate_third_party_notice.js" - }, "dependencies": { "colors": "1.4.0", "commander": "8.3.0", diff --git a/packages/playwright-core/bundles/zip/build.js b/packages/playwright-core/bundles/zip/build.js deleted file mode 100644 index 5eb79c66d81c0..0000000000000 --- a/packages/playwright-core/bundles/zip/build.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// @ts-check -const path = require('path'); -const esbuild = require('esbuild'); - -/** - * @param {boolean} watchMode - * @returns {import('esbuild').BuildOptions} - */ -function esbuildOptions(watchMode) { - return { - entryPoints: [path.join(__dirname, 'src/zipBundleImpl.ts')], - bundle: true, - outdir: path.join(__dirname, '../../lib'), - format: 'cjs', - platform: 'node', - target: 'ES2019', - sourcemap: watchMode, - minify: !watchMode, - }; -} - -async function main() { - const watchMode = process.argv.includes('--watch'); - const ctx = await esbuild.context(esbuildOptions(watchMode)); - await ctx.rebuild(); - if (watchMode) - await ctx.watch(); - else - await ctx.dispose(); -} - -module.exports = { esbuildOptions }; - -if (require.main === module) - main(); diff --git a/packages/playwright-core/bundles/zip/package.json b/packages/playwright-core/bundles/zip/package.json index 3e0124035bcca..a9b4976072900 100644 --- a/packages/playwright-core/bundles/zip/package.json +++ b/packages/playwright-core/bundles/zip/package.json @@ -2,12 +2,6 @@ "name": "zip-bundle", "version": "0.0.1", "private": true, - "scripts": { - "esbuild": "node build.js", - "build": "npm run esbuild", - "watch": "npm run esbuild -- --watch", - "generate-license": "node ../../../../utils/generate_third_party_notice.js" - }, "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", diff --git a/packages/playwright/bundles/babel/build.js b/packages/playwright/bundles/babel/build.js deleted file mode 100644 index c5cffa4baab92..0000000000000 --- a/packages/playwright/bundles/babel/build.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// @ts-check -const path = require('path'); -const esbuild = require('esbuild'); - -/** - * @param {boolean} watchMode - * @returns {import('esbuild').BuildOptions} - */ -function esbuildOptions(watchMode) { - return { - entryPoints: [path.join(__dirname, 'src/babelBundleImpl.ts')], - external: ['playwright'], - bundle: true, - outdir: path.join(__dirname, '../../lib/transform'), - format: 'cjs', - platform: 'node', - target: 'ES2019', - sourcemap: watchMode, - minify: !watchMode, - }; -} - -async function main() { - const watchMode = process.argv.includes('--watch'); - const ctx = await esbuild.context(esbuildOptions(watchMode)); - await ctx.rebuild(); - if (watchMode) - await ctx.watch(); - else - await ctx.dispose(); -} - -module.exports = { esbuildOptions }; - -if (require.main === module) - main(); diff --git a/packages/playwright/bundles/babel/package.json b/packages/playwright/bundles/babel/package.json index 969026a81a249..7193fe56623bd 100644 --- a/packages/playwright/bundles/babel/package.json +++ b/packages/playwright/bundles/babel/package.json @@ -2,12 +2,6 @@ "name": "babel-bundle", "version": "0.0.1", "private": true, - "scripts": { - "esbuild": "node build.js", - "build": "npm run esbuild", - "watch": "npm run esbuild -- --watch", - "generate-license": "node ../../../../utils/generate_third_party_notice.js" - }, "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/core": "^7.26.10", diff --git a/packages/playwright/bundles/expect/build.js b/packages/playwright/bundles/expect/build.js deleted file mode 100644 index 18a37f60c81dc..0000000000000 --- a/packages/playwright/bundles/expect/build.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// @ts-check -const path = require('path'); -const esbuild = require('esbuild'); - -/** - * @param {boolean} watchMode - * @returns {import('esbuild').BuildOptions} - */ -function esbuildOptions(watchMode) { - return { - entryPoints: [path.join(__dirname, 'src/expectBundleImpl.ts')], - bundle: true, - outdir: path.join(__dirname, '../../lib/common'), - format: 'cjs', - platform: 'node', - target: 'ES2019', - sourcemap: watchMode, - minify: !watchMode, - }; -} - -async function main() { - const watchMode = process.argv.includes('--watch'); - const ctx = await esbuild.context(esbuildOptions(watchMode)); - await ctx.rebuild(); - if (watchMode) - await ctx.watch(); - else - await ctx.dispose(); -} - -module.exports = { esbuildOptions }; - -if (require.main === module) - main(); diff --git a/packages/playwright/bundles/expect/package.json b/packages/playwright/bundles/expect/package.json index 3ce2d05ecc845..4597f9e4d908e 100644 --- a/packages/playwright/bundles/expect/package.json +++ b/packages/playwright/bundles/expect/package.json @@ -2,12 +2,6 @@ "name": "expect-bundle", "version": "0.0.1", "private": true, - "scripts": { - "esbuild": "node build.js", - "build": "npm run esbuild", - "watch": "npm run esbuild -- --watch", - "generate-license": "node ../../../../utils/generate_third_party_notice.js" - }, "dependencies": { "@jest/expect-utils": "29.7.0", "jest-get-type": "29.6.3", diff --git a/packages/playwright/bundles/utils/build.js b/packages/playwright/bundles/utils/build.js deleted file mode 100644 index 8bd29d74f7c56..0000000000000 --- a/packages/playwright/bundles/utils/build.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// @ts-check -const path = require('path'); -const esbuild = require('esbuild'); - -/** - * @param {boolean} watchMode - * @returns {import('esbuild').BuildOptions} - */ -function esbuildOptions(watchMode) { - return { - entryPoints: [path.join(__dirname, 'src/utilsBundleImpl.ts')], - external: ['fsevents'], - bundle: true, - outdir: path.join(__dirname, '../../lib'), - format: 'cjs', - platform: 'node', - target: 'ES2019', - sourcemap: watchMode, - minify: !watchMode, - }; -} - -async function main() { - const watchMode = process.argv.includes('--watch'); - const ctx = await esbuild.context(esbuildOptions(watchMode)); - await ctx.rebuild(); - if (watchMode) - await ctx.watch(); - else - await ctx.dispose(); -} - -module.exports = { esbuildOptions }; - -if (require.main === module) - main(); diff --git a/packages/playwright/bundles/utils/package.json b/packages/playwright/bundles/utils/package.json index 63ee4858bba7e..08dd4267c6253 100644 --- a/packages/playwright/bundles/utils/package.json +++ b/packages/playwright/bundles/utils/package.json @@ -2,12 +2,6 @@ "name": "utils-bundle", "version": "0.0.1", "private": true, - "scripts": { - "esbuild": "node build.js", - "build": "npm run esbuild", - "watch": "npm run esbuild -- --watch", - "generate-license": "node ../../../../utils/generate_third_party_notice.js" - }, "dependencies": { "chokidar": "3.6.0", "enquirer": "2.3.6", diff --git a/utils/build/build.js b/utils/build/build.js index 54ce03b857fcf..8c966d185da33 100644 --- a/utils/build/build.js +++ b/utils/build/build.js @@ -228,16 +228,60 @@ function copyFile(file, from, to) { fs.copyFileSync(file, destination); } +/** + * @typedef {{ + * modulePath: string, + * entryPoints: string[], + * external?: string[], + * outdir?: string, + * outfile?: string, + * minify?: boolean, + * }} BundleOptions + */ + +/** @type {BundleOptions[]} */ const bundles = []; -for (const pkg of workspace.packages()) { - const bundlesDir = path.join(pkg.path, 'bundles'); - if (!fs.existsSync(bundlesDir)) - continue; - for (const bundle of fs.readdirSync(bundlesDir)) { - if (fs.existsSync(path.join(bundlesDir, bundle, 'package.json'))) - bundles.push(path.join(bundlesDir, bundle)); - } -} + +bundles.push({ + modulePath: 'packages/playwright/bundles/babel', + outdir: 'packages/playwright/lib/transform', + entryPoints: ['src/babelBundleImpl.ts'], + external: ['playwright'], +}); + +bundles.push({ + modulePath: 'packages/playwright/bundles/expect', + outdir: 'packages/playwright/lib/common', + entryPoints: ['src/expectBundleImpl.ts'], +}); + +bundles.push({ + modulePath: 'packages/playwright/bundles/utils', + outdir: 'packages/playwright/lib', + entryPoints: ['src/utilsBundleImpl.ts'], + external: ['fsevents'], +}); + +bundles.push({ + modulePath: 'packages/playwright-core/bundles/utils', + outfile: 'packages/playwright-core/lib/utilsBundleImpl/index.js', + entryPoints: ['src/utilsBundleImpl.ts'], +}); + +bundles.push({ + modulePath: 'packages/playwright-core/bundles/zip', + outdir: 'packages/playwright-core/lib', + entryPoints: ['src/zipBundleImpl.ts'], +}); + + +// @playwright/client +bundles.push({ + modulePath: 'packages/playwright-client', + outdir: 'packages/playwright-client/lib', + entryPoints: ['src/index.ts'], + minify: false, +}); class GroupStep extends Step { /** @param {Step[]} steps */ @@ -269,11 +313,18 @@ updateSteps.push(new ProgramStep({ // Update bundles. for (const bundle of bundles) { + // Do not update @playwright/client, it has not its own deps. + if (bundle.modulePath === 'packages/playwright-client') + continue; + + const packageJson = path.join(filePath(bundle.modulePath), 'package.json'); + if (!fs.existsSync(packageJson)) + throw new Error(`${packageJson} does not exist`); updateSteps.push(new ProgramStep({ command: 'npm', args: ['ci', '--save=false', '--fund=false', '--audit=false', '--omit=optional'], shell: true, - cwd: bundle, + cwd: filePath(bundle.modulePath), concurrent: true, })); } @@ -375,11 +426,9 @@ class CustomCallbackStep extends Step { for (const pkg of workspace.packages()) { if (!fs.existsSync(path.join(pkg.path, 'src'))) continue; - // playwright-client has its own build step. - if (['@playwright/client'].includes(pkg.name)) { - loadBundleEsbuildStep(pkg.path); + // playwright-client is built as a bundle. + if (['@playwright/client'].includes(pkg.name)) continue; - } steps.push(new EsbuildStep({ entryPoints: [path.join(pkg.path, 'src/**/*.ts')], @@ -390,18 +439,36 @@ for (const pkg of workspace.packages()) { })); } +function copyXdgOpen() { + const outdir = filePath('packages/playwright-core/lib/utilsBundleImpl'); + if (!fs.existsSync(outdir)) + fs.mkdirSync(outdir, { recursive: true }); + + // 'open' package requires 'xdg-open' binary to be present, which does not get bundled by esbuild. + fs.copyFileSync(filePath('packages/playwright-core/bundles/utils/node_modules/open/xdg-open'), path.join(outdir, 'xdg-open')); + console.log('==== Copied xdg-open to', path.join(outdir, 'xdg-open')); +} + +// Copy xdg-open after bundles 'npm ci' has finished. +steps.push(new CustomCallbackStep(copyXdgOpen)); + // Build/watch bundles. -for (const bundle of bundles) - loadBundleEsbuildStep(bundle); - -function loadBundleEsbuildStep(bundle) { - const buildFile = path.join(bundle, 'build.js'); - if (!fs.existsSync(buildFile)) - throw new Error(`Build file ${buildFile} does not exist`); - const { esbuildOptions, beforeEsbuild } = require(buildFile); - if (beforeEsbuild) - steps.push(new CustomCallbackStep(beforeEsbuild)); - const options = esbuildOptions(watchMode); +for (const bundle of bundles) { + /** @type {import('esbuild').BuildOptions} */ + const options = { + bundle: true, + format: 'cjs', + platform: 'node', + target: 'ES2019', + sourcemap: watchMode, + minify: !watchMode, + + entryPoints: bundle.entryPoints.map(e => path.join(filePath(bundle.modulePath), e)), + ...(bundle.outdir ? { outdir: filePath(bundle.outdir) } : {}), + ...(bundle.outfile ? { outfile: filePath(bundle.outfile) } : {}), + ...(bundle.external ? { external: bundle.external } : {}), + ...(bundle.minify !== undefined ? { minify: bundle.minify } : {}), + }; steps.push(new EsbuildStep(options)); }