From a74e23a257227765c338b0a7b615f81dc7077054 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Mon, 23 Mar 2020 12:49:53 -0700 Subject: [PATCH] feat: support `PLAYWRIGHT_GLOBAL_INSTALL=1` env variable (#1470) You can install playwright with ``` PLAYWRIGHT_GLOBAL_INSTALL=1 npm i playwright ``` to make it use a single shared location for all browser downloads. Fixes #1102 --- docs/api.md | 4 ++++ download-browser.js | 13 +++++++++++-- install-from-github.js | 8 ++++---- package.json | 1 + packages/playwright-chromium/install.js | 2 +- packages/playwright-firefox/install.js | 2 +- packages/playwright-webkit/install.js | 2 +- packages/playwright/install.js | 6 +++--- 8 files changed, 26 insertions(+), 12 deletions(-) diff --git a/docs/api.md b/docs/api.md index e43cf159bf..64b7e695f0 100644 --- a/docs/api.md +++ b/docs/api.md @@ -3972,6 +3972,10 @@ Playwright looks for certain [environment variables](https://en.wikipedia.org/wi If Playwright doesn't find them in the environment, a lowercased variant of these variables will be used from the [npm config](https://docs.npmjs.com/cli/config). - `PLAYWRIGHT_DOWNLOAD_HOST` - overwrite URL prefix that is used to download browsers. Note: this includes protocol and might even include path prefix. By default, Playwright uses `https://storage.googleapis.com` to download Chromium and `https://playwright.azureedge.net` to download Webkit & Firefox. +- `PLAYWRIGHT_GLOBAL_INSTALL` - install Playwright browsers in a single global location. Locations are different on different platforms: + * MacOS: `$HOME/Library/Caches/playwright-nodejs` + * Linux: `$HOME/.cache/playwright-nodejs` + * Windows: `$HOME/AppData/Local/playwright-nodejs/Cache` ### Working with selectors diff --git a/download-browser.js b/download-browser.js index 05514579a9..5c4c79ac7a 100644 --- a/download-browser.js +++ b/download-browser.js @@ -14,10 +14,19 @@ * limitations under the License. */ const fs = require('fs'); +const path = require('path'); const browserFetcher = require('./lib/server/browserFetcher.js'); const packageJSON = require('./package.json'); -async function downloadBrowserWithProgressBar(downloadPath, browser, version = '') { +const FALSY_VALUES = ['0', 'false']; + +async function downloadBrowserWithProgressBar(downloadPath, browser, respectGlobalInstall = false) { + const PLAYWRIGHT_GLOBAL_INSTALL = respectGlobalInstall ? getFromENV('PLAYWRIGHT_GLOBAL_INSTALL') : false; + if (!!PLAYWRIGHT_GLOBAL_INSTALL && !FALSY_VALUES.includes(PLAYWRIGHT_GLOBAL_INSTALL.toLowerCase().trim())) { + const envPaths = require('env-paths'); + const appPaths = envPaths('playwright'); + downloadPath = path.join(appPaths.cache, `playwright-${packageJSON.version}-${browser}`); + } let progressBar = null; let lastDownloadedBytes = 0; const revision = packageJSON.playwright[`${browser}_revision`]; @@ -29,7 +38,6 @@ async function downloadBrowserWithProgressBar(downloadPath, browser, version = ' incomplete: ' ', width: 20, total: totalBytes, - host: getFromENV('PLAYWRIGHT_DOWNLOAD_HOST'), }); } const delta = downloadedBytes - lastDownloadedBytes; @@ -41,6 +49,7 @@ async function downloadBrowserWithProgressBar(downloadPath, browser, version = ' browser, revision, progress, + host: getFromENV('PLAYWRIGHT_DOWNLOAD_HOST'), }); logPolitely(`${browser} downloaded to ${downloadPath}`); return executablePath; diff --git a/install-from-github.js b/install-from-github.js index fecd657f20..0dc674faf4 100644 --- a/install-from-github.js +++ b/install-from-github.js @@ -47,7 +47,7 @@ const DOWNLOAD_PATHS = { const downloadedBrowsersJSON = await fs.promises.readFile(DOWNLOADED_BROWSERS_JSON_PATH, 'utf8').then(json => JSON.parse(json)).catch(() => ({})); try { if (!(await existsAsync(DOWNLOAD_PATHS.chromium))) { - const crExecutablePath = await downloadBrowserWithProgressBar(DOWNLOAD_PATHS.chromium, 'chromium'); + const crExecutablePath = await downloadBrowserWithProgressBar(DOWNLOAD_PATHS.chromium, 'chromium', false /* respectGlobalInstall */); downloadedBrowsersJSON.crExecutablePath = crExecutablePath; await protocolGenerator.generateChromiumProtocol(crExecutablePath); await fs.promises.writeFile(DOWNLOADED_BROWSERS_JSON_PATH, JSON.stringify(downloadedBrowsersJSON)); @@ -57,7 +57,7 @@ const DOWNLOAD_PATHS = { } try { if (!(await existsAsync(DOWNLOAD_PATHS.firefox))) { - const ffExecutablePath = await downloadBrowserWithProgressBar(DOWNLOAD_PATHS.firefox, 'firefox'); + const ffExecutablePath = await downloadBrowserWithProgressBar(DOWNLOAD_PATHS.firefox, 'firefox', false /* respectGlobalInstall */); downloadedBrowsersJSON.ffExecutablePath = ffExecutablePath; await protocolGenerator.generateFirefoxProtocol(ffExecutablePath); await fs.promises.writeFile(DOWNLOADED_BROWSERS_JSON_PATH, JSON.stringify(downloadedBrowsersJSON)); @@ -67,7 +67,7 @@ const DOWNLOAD_PATHS = { } try { if (!(await existsAsync(DOWNLOAD_PATHS.webkit))) { - const wkExecutablePath = await downloadBrowserWithProgressBar(DOWNLOAD_PATHS.webkit, 'webkit'); + const wkExecutablePath = await downloadBrowserWithProgressBar(DOWNLOAD_PATHS.webkit, 'webkit', false /* respectGlobalInstall */); downloadedBrowsersJSON.wkExecutablePath = wkExecutablePath; await protocolGenerator.generateWebKitProtocol(path.dirname(wkExecutablePath)); await fs.promises.writeFile(DOWNLOADED_BROWSERS_JSON_PATH, JSON.stringify(downloadedBrowsersJSON)); @@ -96,4 +96,4 @@ const DOWNLOAD_PATHS = { async function readdirAsync(dirpath) { return fs.promises.readdir(dirpath).then(dirs => dirs.map(dir => path.join(dirpath, dir))); } -})(); \ No newline at end of file +})(); diff --git a/package.json b/package.json index 9897b58043..2ebb1eba29 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "license": "Apache-2.0", "dependencies": { "debug": "^4.1.0", + "env-paths": "^2.2.0", "extract-zip": "^1.6.6", "https-proxy-agent": "^3.0.0", "jpeg-js": "^0.3.6", diff --git a/packages/playwright-chromium/install.js b/packages/playwright-chromium/install.js index 782cfb4598..cdfb0ede5f 100644 --- a/packages/playwright-chromium/install.js +++ b/packages/playwright-chromium/install.js @@ -17,6 +17,6 @@ const path = require('path'); const fs = require('fs'); const {downloadBrowserWithProgressBar} = require('playwright-core/download-browser'); (async function() { - const crExecutablePath = await downloadBrowserWithProgressBar(path.join(__dirname, '.local-browsers', 'chromium'), 'chromium'); + const crExecutablePath = await downloadBrowserWithProgressBar(path.join(__dirname, '.local-browsers', 'chromium'), 'chromium', true /* respectGlobalInstall */); await fs.promises.writeFile(path.join(__dirname, '.downloaded-browsers.json'), JSON.stringify({crExecutablePath})); })(); diff --git a/packages/playwright-firefox/install.js b/packages/playwright-firefox/install.js index 2c90c29437..c409726130 100644 --- a/packages/playwright-firefox/install.js +++ b/packages/playwright-firefox/install.js @@ -18,6 +18,6 @@ const fs = require('fs'); const {downloadBrowserWithProgressBar} = require('playwright-core/download-browser'); (async function() { - const ffExecutablePath = await downloadBrowserWithProgressBar(path.join(__dirname, '.local-browsers', 'firefox'), 'firefox'); + const ffExecutablePath = await downloadBrowserWithProgressBar(path.join(__dirname, '.local-browsers', 'firefox'), 'firefox', true /* respectGlobalInstall */); await fs.promises.writeFile(path.join(__dirname, '.downloaded-browsers.json'), JSON.stringify({ffExecutablePath, })); })(); diff --git a/packages/playwright-webkit/install.js b/packages/playwright-webkit/install.js index 14546c1361..0b8c812233 100644 --- a/packages/playwright-webkit/install.js +++ b/packages/playwright-webkit/install.js @@ -18,6 +18,6 @@ const fs = require('fs'); const {downloadBrowserWithProgressBar} = require('playwright-core/download-browser'); (async function() { - const wkExecutablePath = await downloadBrowserWithProgressBar(path.join(__dirname, '.local-browsers', 'webkit'), 'webkit'); + const wkExecutablePath = await downloadBrowserWithProgressBar(path.join(__dirname, '.local-browsers', 'webkit'), 'webkit', true /* respectGlobalInstall */); await fs.promises.writeFile(path.join(__dirname, '.downloaded-browsers.json'), JSON.stringify({wkExecutablePath, })); })(); diff --git a/packages/playwright/install.js b/packages/playwright/install.js index bf628efc9c..425202cfef 100644 --- a/packages/playwright/install.js +++ b/packages/playwright/install.js @@ -18,8 +18,8 @@ const fs = require('fs'); const {downloadBrowserWithProgressBar} = require('playwright-core/download-browser'); (async function() { - const crExecutablePath = await downloadBrowserWithProgressBar(path.join(__dirname, '.local-browsers', 'chromium'), 'chromium'); - const ffExecutablePath = await downloadBrowserWithProgressBar(path.join(__dirname, '.local-browsers', 'firefox'), 'firefox'); - const wkExecutablePath = await downloadBrowserWithProgressBar(path.join(__dirname, '.local-browsers', 'webkit'), 'webkit'); + const crExecutablePath = await downloadBrowserWithProgressBar(path.join(__dirname, '.local-browsers', 'chromium'), 'chromium', true /* respectGlobalInstall */); + const ffExecutablePath = await downloadBrowserWithProgressBar(path.join(__dirname, '.local-browsers', 'firefox'), 'firefox', true /* respectGlobalInstall */); + const wkExecutablePath = await downloadBrowserWithProgressBar(path.join(__dirname, '.local-browsers', 'webkit'), 'webkit', true /* respectGlobalInstall */); await fs.promises.writeFile(path.join(__dirname, '.downloaded-browsers.json'), JSON.stringify({crExecutablePath, ffExecutablePath, wkExecutablePath, })); })();