playwright/install-from-github.js
Andrey Lushnikov f5ecbff16e
devops: remake downloading logic (#1419)
This patch:
- removes `browserType.downloadBrowserIfNeeded()` method. The method
  turned out to be ill-behaving and cannot not be used as we'd like to (see #1085)
- adds a `browserType.setExecutablePath` method to set a browser
  exectuable.

With this patch, we take the following approach towards managing browser downloads:
- `playwright-core` doesn't download any browsers. In `playwright-core`, `playwright.chromium.executablePath()` returns `null` (same for firefox and webkit).
- clients of `playwright-core` (e.g. `playwright` and others) download browsers one way or another.
They can then configure `playwright` with executable paths and re-export the `playwright` object to their clients.
- `playwright`, `playwright-firefox`, `playwright-chromium` and `playwright-webkit` download 
browsers. Once browsers are downloaded, their executable paths are saved to a `.downloaded-browsers.json` file. This file is read in `playwright/index.js` to configure browser executable paths and re-export the API.
- special case is `install-from-github.js` that also cleans up old browsers.
2020-03-19 11:43:35 -07:00

93 lines
3.9 KiB
JavaScript

/**
* Copyright 2017 Google Inc. All rights reserved.
* Modifications 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.
*/
// This file is only run when someone installs via the github repo
try {
console.log('Building playwright...');
require('child_process').execSync('npm run build', {
stdio: 'ignore'
});
} catch (e) {
}
const path = require('path');
const fs = require('fs');
const util = require('util');
const rmAsync = util.promisify(require('rimraf'));
const existsAsync = path => fs.promises.access(path).then(() => true, e => false);
const {downloadBrowserWithProgressBar} = require('./download-browser');
const protocolGenerator = require('./utils/protocol-types-generator');
const packageJSON = require('./package.json');
const DOWNLOADED_BROWSERS_JSON_PATH = path.join(__dirname, '.downloaded-browsers.json');
const DOWNLOAD_PATHS = {
chromium: path.join(__dirname, '.local-browsers', `chromium-${packageJSON.playwright.chromium_revision}`),
firefox: path.join(__dirname, '.local-browsers', `firefox-${packageJSON.playwright.firefox_revision}`),
webkit: path.join(__dirname, '.local-browsers', `webkit-${packageJSON.playwright.webkit_revision}`),
};
(async function() {
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');
downloadedBrowsersJSON.crExecutablePath = crExecutablePath;
await protocolGenerator.generateChromiumProtocol(crExecutablePath);
await fs.promises.writeFile(DOWNLOADED_BROWSERS_JSON_PATH, JSON.stringify(downloadedBrowsersJSON));
}
} catch (e) {
console.warn(e.message);
}
try {
if (!(await existsAsync(DOWNLOAD_PATHS.firefox))) {
const ffExecutablePath = await downloadBrowserWithProgressBar(DOWNLOAD_PATHS.firefox, 'firefox');
downloadedBrowsersJSON.ffExecutablePath = ffExecutablePath;
await protocolGenerator.generateFirefoxProtocol(ffExecutablePath);
await fs.promises.writeFile(DOWNLOADED_BROWSERS_JSON_PATH, JSON.stringify(downloadedBrowsersJSON));
}
} catch (e) {
console.warn(e.message);
}
try {
if (!(await existsAsync(DOWNLOAD_PATHS.webkit))) {
const wkExecutablePath = await downloadBrowserWithProgressBar(DOWNLOAD_PATHS.webkit, 'webkit');
downloadedBrowsersJSON.wkExecutablePath = wkExecutablePath;
await protocolGenerator.generateWebKitProtocol(path.dirname(wkExecutablePath));
await fs.promises.writeFile(DOWNLOADED_BROWSERS_JSON_PATH, JSON.stringify(downloadedBrowsersJSON));
}
} catch (e) {
console.warn(e.message);
}
// Cleanup stale revisions.
const directories = new Set(await readdirAsync(path.join(__dirname, '.local-browsers')));
directories.delete(DOWNLOAD_PATHS.chromium);
directories.delete(DOWNLOAD_PATHS.firefox);
directories.delete(DOWNLOAD_PATHS.webkit);
// cleanup old browser directories.
directories.add(path.join(__dirname, '.local-chromium'));
directories.add(path.join(__dirname, '.local-firefox'));
directories.add(path.join(__dirname, '.local-webkit'));
await Promise.all([...directories].map(directory => rmAsync(directory)));
async function readdirAsync(dirpath) {
return fs.promises.readdir(dirpath).then(dirs => dirs.map(dir => path.join(dirpath, dir)));
}
})();