chore: generate browser versions when doing release (#999)

This introduces a handful of new markdown preprocessor commands to
insert browser versions:
- `GEN:chromium-version-if-release` - inserts current Chromium version
  if we're doing release; noop otherwise.
- `GEN:firefox-version-if-release` - inserts current Firefox version
  if we're doing release; noop otherwise.

And to generate badge links:
- `GEN:chromium-version-badge-if-release` - inserts current Chromium version
  badge if we're doing release; noop otherwise.
- `GEN:firefox-version-badge-if-release` - inserts current Firefox version
  badge if we're doing release; noop otherwise.

This doesn't touch webkit at all - we're yet to figure what to do with
webkit version.

NOTE: versions will be updated only once we release. This way our
README.md always represents last released version.
This commit is contained in:
Andrey Lushnikov 2020-02-13 18:26:38 -08:00 committed by GitHub
parent 1eabd182e9
commit d29625c281
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 114 additions and 31 deletions

View file

@ -1,5 +1,5 @@
# Playwright # Playwright
[![npm version](https://img.shields.io/npm/v/playwright.svg?style=flat)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-81.0.4044-blue.svg)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-73.0b3-blue.svg)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-13.0.4-blue.svg)](https://webkit.org/) [![Join Slack](https://img.shields.io/badge/join-slack-infomational)](https://join.slack.com/t/playwright/shared_invite/enQtOTEyMTUxMzgxMjIwLThjMDUxZmIyNTRiMTJjNjIyMzdmZDA3MTQxZWUwZTFjZjQwNGYxZGM5MzRmNzZlMWI5ZWUyOTkzMjE5Njg1NDg) [![npm version](https://img.shields.io/npm/v/playwright.svg?style=flat)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge-if-release -->[![Chromium version](https://img.shields.io/badge/chromium-81.0.4044-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) <!-- GEN:stop --> <!-- GEN:firefox-version-badge-if-release --> [![Firefox version](https://img.shields.io/badge/firefox-73.0b3-blue.svg?logo=mozilla-firefox)](https://www.mozilla.org/en-US/firefox/new/) <!-- GEN:stop --> [![WebKit version](https://img.shields.io/badge/webkit-13.0.4-blue.svg?logo=safari)](https://webkit.org/) [![Join Slack](https://img.shields.io/badge/join-slack-infomational)](https://join.slack.com/t/playwright/shared_invite/enQtOTEyMTUxMzgxMjIwLThjMDUxZmIyNTRiMTJjNjIyMzdmZDA3MTQxZWUwZTFjZjQwNGYxZGM5MzRmNzZlMWI5ZWUyOTkzMjE5Njg1NDg)
###### [API](https://github.com/microsoft/playwright/blob/v0.10.0/docs/api.md) | [FAQ](#faq) | [Contributing](#contributing) ###### [API](https://github.com/microsoft/playwright/blob/v0.10.0/docs/api.md) | [FAQ](#faq) | [Contributing](#contributing)
@ -8,9 +8,9 @@ Playwright is a Node library to automate the [Chromium](https://www.chromium.org
| | ver | Linux | macOS | Win | | | ver | Linux | macOS | Win |
| ---: | :---: | :---: | :---: | :---: | | ---: | :---: | :---: | :---: | :---: |
| Chromium| 81.0.4044 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Chromium| <!-- GEN:chromium-version-if-release-->81.0.4044<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit | 13.0.4 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit | 13.0.4 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Firefox |73.0b3 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Firefox | <!-- GEN:firefox-version-if-release -->73.0b3<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
- Headless is supported for all the browsers on all platforms. - Headless is supported for all the browsers on all platforms.

View file

@ -15,10 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
const playwright = require('../../index.js').chromium; const playwright = require('../../index.js');
const path = require('path'); const path = require('path');
const Source = require('./Source'); const Source = require('./Source');
const {spawnSync} = require('child_process');
const PROJECT_DIR = path.join(__dirname, '..', '..'); const PROJECT_DIR = path.join(__dirname, '..', '..');
const VERSION = require(path.join(PROJECT_DIR, 'package.json')).version; const VERSION = require(path.join(PROJECT_DIR, 'package.json')).version;
@ -43,10 +45,15 @@ async function run() {
const mdSources = [readme, api, troubleshooting]; const mdSources = [readme, api, troubleshooting];
const preprocessor = require('./preprocessor'); const preprocessor = require('./preprocessor');
messages.push(...await preprocessor.runCommands(mdSources, VERSION)); const browserVersions = getBrowserVersions();
messages.push(...(await preprocessor.runCommands(mdSources, {
libversion: VERSION,
chromiumVersion: browserVersions.chromium,
firefoxVersion: browserVersions.firefox,
})));
messages.push(...await preprocessor.ensureReleasedAPILinks([readme], VERSION)); messages.push(...await preprocessor.ensureReleasedAPILinks([readme], VERSION));
const browser = await playwright.launch(); const browser = await playwright.chromium.launch();
const page = await browser.newPage(); const page = await browser.newPage();
const checkPublicAPI = require('./check_public_api'); const checkPublicAPI = require('./check_public_api');
const jsSources = await Source.readdir(path.join(PROJECT_DIR, 'src')); const jsSources = await Source.readdir(path.join(PROJECT_DIR, 'src'));
@ -60,7 +67,7 @@ async function run() {
await source.save(); await source.save();
changedFiles = true; changedFiles = true;
} }
await readme.saveAs(path.join(PROJECT_DIR, 'packages', 'playwright', 'README.md')); await readme.saveAs(path.join(PROJECT_DIR, 'packages', 'playwright', 'README.md'));
} }
@ -94,3 +101,12 @@ async function run() {
console.log(`DocLint Finished in ${runningTime / 1000} seconds`); console.log(`DocLint Finished in ${runningTime / 1000} seconds`);
process.exit(clearExit ? 0 : 1); process.exit(clearExit ? 0 : 1);
} }
function getBrowserVersions() {
const chromiumVersion = spawnSync(playwright.chromium.executablePath(), ['--version']).stdout.toString();
const firefoxVersion = spawnSync(playwright.firefox.executablePath(), ['--version']).stdout.toString();
return {
chromium: chromiumVersion.trim().split(' ').pop(),
firefox: firefoxVersion.trim().split(' ').pop(),
};
}

View file

@ -15,11 +15,12 @@
*/ */
const Message = require('../Message'); const Message = require('../Message');
const {firefox, webkit, chromium} = require('../../../');
module.exports.ensureReleasedAPILinks = function(sources, version) { module.exports.ensureReleasedAPILinks = function(sources, libversion) {
// Release version is everything that doesn't include "-". // Release version is everything that doesn't include "-".
const apiLinkRegex = /https:\/\/github.com\/microsoft\/playwright\/blob\/v[^/]*\/docs\/api.md/ig; const apiLinkRegex = /https:\/\/github.com\/microsoft\/playwright\/blob\/v[^/]*\/docs\/api.md/ig;
const lastReleasedAPI = `https://github.com/microsoft/playwright/blob/v${version.split('-')[0]}/docs/api.md`; const lastReleasedAPI = `https://github.com/microsoft/playwright/blob/v${libversion.split('-')[0]}/docs/api.md`;
const messages = []; const messages = [];
for (const source of sources) { for (const source of sources) {
@ -31,9 +32,9 @@ module.exports.ensureReleasedAPILinks = function(sources, version) {
return messages; return messages;
}; };
module.exports.runCommands = function(sources, version) { module.exports.runCommands = function(sources, {libversion, chromiumVersion, firefoxVersion}) {
// Release version is everything that doesn't include "-". // Release version is everything that doesn't include "-".
const isReleaseVersion = !version.includes('-'); const isReleaseVersion = !libversion.includes('-');
const messages = []; const messages = [];
const commands = []; const commands = [];
@ -65,9 +66,17 @@ module.exports.runCommands = function(sources, version) {
for (const command of commands) { for (const command of commands) {
let newText = null; let newText = null;
if (command.name === 'version') if (command.name === 'version')
newText = isReleaseVersion ? 'v' + version : 'Tip-Of-Tree'; newText = isReleaseVersion ? 'v' + libversion : 'Tip-Of-Tree';
else if (command.name === 'empty-if-release') else if (command.name === 'empty-if-release')
newText = isReleaseVersion ? '' : command.originalText; newText = isReleaseVersion ? '' : command.originalText;
else if (command.name === 'chromium-version-if-release')
newText = isReleaseVersion ? chromiumVersion : command.originalText;
else if (command.name === 'firefox-version-if-release')
newText = isReleaseVersion ? firefoxVersion : command.originalText;
else if (command.name === 'chromium-version-badge-if-release')
newText = isReleaseVersion ? `[![Chromium version](https://img.shields.io/badge/chromium-${chromiumVersion}-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)` : command.originalText;
else if (command.name === 'firefox-version-badge-if-release')
newText = isReleaseVersion ? `[![Firefox version](https://img.shields.io/badge/firefox-${firefoxVersion}-blue.svg?logo=mozilla-firefox)](https://www.mozilla.org/en-US/firefox/new/)` : command.originalText;
else if (command.name === 'toc') else if (command.name === 'toc')
newText = generateTableOfContents(command.source.text(), command.to, false /* topLevelOnly */); newText = generateTableOfContents(command.source.text(), command.to, false /* topLevelOnly */);
else if (command.name === 'toc-top-level') else if (command.name === 'toc-top-level')

View file

@ -63,11 +63,21 @@ describe('ensureReleasedAPILinks', function() {
}); });
describe('runCommands', function() { describe('runCommands', function() {
const OPTIONS_REL = {
libversion: '1.3.0',
chromiumVersion: '80.0.4004.0',
firefoxVersion: '73.0b3',
};
const OPTIONS_DEV = {
libversion: '1.3.0-post',
chromiumVersion: '<CRVERSION>',
firefoxVersion: '<FFVERSION>',
};
it('should throw for unknown command', function() { it('should throw for unknown command', function() {
const source = new Source('doc.md', ` const source = new Source('doc.md', `
<!-- gen:unknown-command -->something<!-- gen:stop --> <!-- gen:unknown-command -->something<!-- gen:stop -->
`); `);
const messages = runCommands([source], '1.1.1'); const messages = runCommands([source], OPTIONS_REL);
expect(source.hasUpdatedText()).toBe(false); expect(source.hasUpdatedText()).toBe(false);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('error'); expect(messages[0].type).toBe('error');
@ -78,19 +88,19 @@ describe('runCommands', function() {
const source = new Source('doc.md', ` const source = new Source('doc.md', `
Playwright <!-- gen:version -->XXX<!-- gen:stop --> Playwright <!-- gen:version -->XXX<!-- gen:stop -->
`); `);
const messages = runCommands([source], '1.2.0'); const messages = runCommands([source], OPTIONS_REL);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('warning'); expect(messages[0].type).toBe('warning');
expect(messages[0].text).toContain('doc.md'); expect(messages[0].text).toContain('doc.md');
expect(source.text()).toBe(` expect(source.text()).toBe(`
Playwright <!-- gen:version -->v1.2.0<!-- gen:stop --> Playwright <!-- gen:version -->v1.3.0<!-- gen:stop -->
`); `);
}); });
it('should work for *-post versions', function() { it('should work for *-post versions', function() {
const source = new Source('doc.md', ` const source = new Source('doc.md', `
Playwright <!-- gen:version -->XXX<!-- gen:stop --> Playwright <!-- gen:version -->XXX<!-- gen:stop -->
`); `);
const messages = runCommands([source], '1.2.0-post'); const messages = runCommands([source], OPTIONS_DEV);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('warning'); expect(messages[0].type).toBe('warning');
expect(messages[0].text).toContain('doc.md'); expect(messages[0].text).toContain('doc.md');
@ -101,12 +111,12 @@ describe('runCommands', function() {
it('should tolerate different writing', function() { it('should tolerate different writing', function() {
const source = new Source('doc.md', `Playwright v<!-- gEn:version -->WHAT const source = new Source('doc.md', `Playwright v<!-- gEn:version -->WHAT
<!-- GEN:stop -->`); <!-- GEN:stop -->`);
runCommands([source], '1.1.1'); runCommands([source], OPTIONS_REL);
expect(source.text()).toBe(`Playwright v<!-- gEn:version -->v1.1.1<!-- GEN:stop -->`); expect(source.text()).toBe(`Playwright v<!-- gEn:version -->v1.3.0<!-- GEN:stop -->`);
}); });
it('should not tolerate missing gen:stop', function() { it('should not tolerate missing gen:stop', function() {
const source = new Source('doc.md', `<!--GEN:version-->`); const source = new Source('doc.md', `<!--GEN:version-->`);
const messages = runCommands([source], '1.2.0'); const messages = runCommands([source], OPTIONS_REL);
expect(source.hasUpdatedText()).toBe(false); expect(source.hasUpdatedText()).toBe(false);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('error'); expect(messages[0].type).toBe('error');
@ -118,7 +128,7 @@ describe('runCommands', function() {
const source = new Source('doc.md', ` const source = new Source('doc.md', `
<!-- gen:empty-if-release -->XXX<!-- gen:stop --> <!-- gen:empty-if-release -->XXX<!-- gen:stop -->
`); `);
const messages = runCommands([source], '1.1.1'); const messages = runCommands([source], OPTIONS_REL);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('warning'); expect(messages[0].type).toBe('warning');
expect(messages[0].text).toContain('doc.md'); expect(messages[0].text).toContain('doc.md');
@ -130,7 +140,7 @@ describe('runCommands', function() {
const source = new Source('doc.md', ` const source = new Source('doc.md', `
<!-- gen:empty-if-release -->XXX<!-- gen:stop --> <!-- gen:empty-if-release -->XXX<!-- gen:stop -->
`); `);
const messages = runCommands([source], '1.1.1-post'); const messages = runCommands([source], OPTIONS_DEV);
expect(messages.length).toBe(0); expect(messages.length).toBe(0);
expect(source.text()).toBe(` expect(source.text()).toBe(`
<!-- gen:empty-if-release -->XXX<!-- gen:stop --> <!-- gen:empty-if-release -->XXX<!-- gen:stop -->
@ -143,7 +153,7 @@ describe('runCommands', function() {
### class: page ### class: page
#### page.$ #### page.$
#### page.$$`); #### page.$$`);
const messages = runCommands([source], '1.3.0'); const messages = runCommands([source], OPTIONS_REL);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('warning'); expect(messages[0].type).toBe('warning');
expect(messages[0].text).toContain('doc.md'); expect(messages[0].text).toContain('doc.md');
@ -164,7 +174,7 @@ describe('runCommands', function() {
# yo comment # yo comment
\`\`\` \`\`\`
`); `);
const messages = runCommands([source], '1.3.0'); const messages = runCommands([source], OPTIONS_REL);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('warning'); expect(messages[0].type).toBe('warning');
expect(messages[0].text).toContain('doc.md'); expect(messages[0].text).toContain('doc.md');
@ -182,7 +192,7 @@ describe('runCommands', function() {
const source = new Source('doc.md', `<!-- gen:toc -->XXX<!-- gen:stop --> const source = new Source('doc.md', `<!-- gen:toc -->XXX<!-- gen:stop -->
### some [link](#foobar) here ### some [link](#foobar) here
`); `);
const messages = runCommands([source], '1.3.0'); const messages = runCommands([source], OPTIONS_REL);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('warning'); expect(messages[0].type).toBe('warning');
expect(messages[0].text).toContain('doc.md'); expect(messages[0].text).toContain('doc.md');
@ -201,7 +211,7 @@ describe('runCommands', function() {
#### first.2.1 #### first.2.1
## Second ## Second
`); `);
const messages = runCommands([source], '1.3.0'); const messages = runCommands([source], OPTIONS_REL);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('warning'); expect(messages[0].type).toBe('warning');
expect(messages[0].text).toContain('doc.md'); expect(messages[0].text).toContain('doc.md');
@ -221,20 +231,68 @@ describe('runCommands', function() {
}); });
it('should work with multiple commands', function() { it('should work with multiple commands', function() {
const source = new Source('doc.md', ` const source = new Source('doc.md', `
<!-- gen:version -->XXX<!-- gen:stop --> <!-- gen:version -->xxx<!-- gen:stop -->
<!-- gen:empty-if-release -->YYY<!-- gen:stop --> <!-- gen:empty-if-release -->yyy<!-- gen:stop -->
<!-- gen:version -->ZZZ<!-- gen:stop --> <!-- gen:version -->zzz<!-- gen:stop -->
`); `);
const messages = runCommands([source], '1.1.1'); const messages = runCommands([source], OPTIONS_REL);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('warning'); expect(messages[0].type).toBe('warning');
expect(messages[0].text).toContain('doc.md'); expect(messages[0].text).toContain('doc.md');
expect(source.text()).toBe(` expect(source.text()).toBe(`
<!-- gen:version -->v1.1.1<!-- gen:stop --> <!-- gen:version -->v1.3.0<!-- gen:stop -->
<!-- gen:empty-if-release --><!-- gen:stop --> <!-- gen:empty-if-release --><!-- gen:stop -->
<!-- gen:version -->v1.1.1<!-- gen:stop --> <!-- gen:version -->v1.3.0<!-- gen:stop -->
`); `);
}); });
describe('gen:chromium-version-if-release', function() {
it('should work for release', function() {
const source = new Source('doc.md', `
Playwright <!-- gen:chromium-version-if-release -->XXX<!-- gen:stop -->
`);
const messages = runCommands([source], OPTIONS_REL);
expect(messages.length).toBe(1);
expect(messages[0].type).toBe('warning');
expect(messages[0].text).toContain('doc.md');
expect(source.text()).toBe(`
Playwright <!-- gen:chromium-version-if-release -->80.0.4004.0<!-- gen:stop -->
`);
});
it('should be noop for dev', function() {
const source = new Source('doc.md', `
Playwright <!-- gen:chromium-version-if-release -->XXX<!-- gen:stop -->
`);
const messages = runCommands([source], OPTIONS_DEV);
expect(messages.length).toBe(0);
expect(source.text()).toBe(`
Playwright <!-- gen:chromium-version-if-release -->XXX<!-- gen:stop -->
`);
});
});
describe('gen:firefox-version', function() {
it('should work for release', function() {
const source = new Source('doc.md', `
Playwright <!-- gen:firefox-version-if-release -->XXX<!-- gen:stop -->
`);
const messages = runCommands([source], OPTIONS_REL);
expect(messages.length).toBe(1);
expect(messages[0].type).toBe('warning');
expect(messages[0].text).toContain('doc.md');
expect(source.text()).toBe(`
Playwright <!-- gen:firefox-version-if-release -->73.0b3<!-- gen:stop -->
`);
});
it('should be noop for dev', function() {
const source = new Source('doc.md', `
Playwright <!-- gen:firefox-version-if-release -->XXX<!-- gen:stop -->
`);
const messages = runCommands([source], OPTIONS_DEV);
expect(messages.length).toBe(0);
expect(source.text()).toBe(`
Playwright <!-- gen:firefox-version-if-release -->XXX<!-- gen:stop -->
`);
});
});
}); });
runner.run(); runner.run();