diff options
Diffstat (limited to 'remote/test/puppeteer/tools/update_chrome_revision.mjs')
-rw-r--r-- | remote/test/puppeteer/tools/update_chrome_revision.mjs | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/remote/test/puppeteer/tools/update_chrome_revision.mjs b/remote/test/puppeteer/tools/update_chrome_revision.mjs new file mode 100644 index 0000000000..64eeef74d5 --- /dev/null +++ b/remote/test/puppeteer/tools/update_chrome_revision.mjs @@ -0,0 +1,162 @@ +/** + * @license + * Copyright 2023 Google Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +import {execSync, exec} from 'child_process'; +import {writeFile, readFile} from 'fs/promises'; +import {promisify} from 'util'; + +import actions from '@actions/core'; +import {SemVer} from 'semver'; + +import packageJson from '../packages/puppeteer-core/package.json' assert {type: 'json'}; +import {versionsPerRelease, lastMaintainedChromeVersion} from '../versions.js'; + +import {PUPPETEER_REVISIONS} from 'puppeteer-core/internal/revisions.js'; + +const execAsync = promisify(exec); + +const CHROME_CURRENT_VERSION = PUPPETEER_REVISIONS.chrome; +const VERSIONS_PER_RELEASE_COMMENT = + '// In Chrome roll patches, use `NEXT` for the Puppeteer version.'; + +const touchedFiles = []; + +function checkIfNeedsUpdate(oldVersion, newVersion, newRevision) { + const oldSemVer = new SemVer(oldVersion, true); + const newSemVer = new SemVer(newVersion, true); + let message = `roll to Chrome ${newVersion} (r${newRevision})`; + + if (newSemVer.compare(oldSemVer) <= 0) { + // Exit the process without setting up version + console.warn( + `Version ${newVersion} is older or the same as the current ${oldVersion}` + ); + process.exit(0); + } else if (newSemVer.compareMain(oldSemVer) === 0) { + message = `fix: ${message}`; + } else { + message = `feat: ${message}`; + } + actions.setOutput('commit', message); +} + +/** + * We cant use `npm run format` as it's too slow + * so we only scope the files we updated + */ +async function formatUpdateFiles() { + await Promise.all( + touchedFiles.map(file => { + return execAsync(`npx eslint --ext js --ext ts --fix ${file}`); + }) + ); + await Promise.all( + touchedFiles.map(file => { + return execAsync(`npx prettier --write ${file}`); + }) + ); +} + +async function replaceInFile(filePath, search, replace) { + const buffer = await readFile(filePath); + const update = buffer.toString().replaceAll(search, replace); + + await writeFile(filePath, update); + + touchedFiles.push(filePath); +} + +async function getVersionAndRevisionForStable() { + const result = await fetch( + 'https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json' + ).then(response => { + return response.json(); + }); + + const {version, revision} = result.channels['Stable']; + + return { + version, + revision, + }; +} + +async function updateDevToolsProtocolVersion(revision) { + const currentProtocol = packageJson.dependencies['devtools-protocol']; + const command = `npm view "devtools-protocol@<=0.0.${revision}" version | tail -1`; + + const bestNewProtocol = execSync(command, { + encoding: 'utf8', + }) + .split(' ')[1] + .replace(/'|\n/g, ''); + + await replaceInFile( + './packages/puppeteer-core/package.json', + `"devtools-protocol": "${currentProtocol}"`, + `"devtools-protocol": "${bestNewProtocol}"` + ); +} + +async function updateVersionFileLastMaintained(oldVersion, newVersion) { + const versions = [...versionsPerRelease.keys()]; + if (versions.indexOf(newVersion) !== -1) { + return; + } + + // If we have manually rolled Chrome but not yet released + // We will have NEXT as value in the Map + if (versionsPerRelease.get(oldVersion) === 'NEXT') { + await replaceInFile('./versions.js', oldVersion, newVersion); + return; + } + + await replaceInFile( + './versions.js', + VERSIONS_PER_RELEASE_COMMENT, + `${VERSIONS_PER_RELEASE_COMMENT}\n ['${version}', 'NEXT'],` + ); + + const oldSemVer = new SemVer(oldVersion, true); + const newSemVer = new SemVer(newVersion, true); + + if (newSemVer.compareMain(oldSemVer) !== 0) { + const lastMaintainedSemVer = new SemVer(lastMaintainedChromeVersion, true); + const newLastMaintainedMajor = lastMaintainedSemVer.major + 1; + + const nextMaintainedVersion = versions.find(version => { + return new SemVer(version, true).major === newLastMaintainedMajor; + }); + + await replaceInFile( + './versions.js', + `const lastMaintainedChromeVersion = '${lastMaintainedChromeVersion}';`, + `const lastMaintainedChromeVersion = '${nextMaintainedVersion}';` + ); + } +} + +const {version, revision} = await getVersionAndRevisionForStable(); + +checkIfNeedsUpdate(CHROME_CURRENT_VERSION, version, revision); + +await replaceInFile( + './packages/puppeteer-core/src/revisions.ts', + CHROME_CURRENT_VERSION, + version +); + +await updateVersionFileLastMaintained(CHROME_CURRENT_VERSION, version); +await updateDevToolsProtocolVersion(revision); + +// Create new `package-lock.json` as we update devtools-protocol +execSync('npm install --ignore-scripts'); +// Make sure we pass CI formatter check by running all the new files though it +await formatUpdateFiles(); + +// Keep this as they can be used to debug GitHub Actions if needed +actions.setOutput('version', version); +actions.setOutput('revision', revision); |