chore: move container integration back to playwright-core (#17487)
This commit is contained in:
parent
0abb1c773b
commit
d431958603
|
|
@ -24,6 +24,7 @@
|
|||
"./lib/outofprocess": "./lib/outofprocess.js",
|
||||
"./lib/utils": "./lib/utils/index.js",
|
||||
"./lib/common/userAgent": "./lib/common/userAgent.js",
|
||||
"./lib/containers/docker": "./lib/containers/docker.js",
|
||||
"./lib/utils/comparators": "./lib/utils/comparators.js",
|
||||
"./lib/utils/eventsHelper": "./lib/utils/eventsHelper.js",
|
||||
"./lib/utils/fileUtils": "./lib/utils/fileUtils.js",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
[cli.ts]
|
||||
../server/trace/viewer/traceViewer.ts
|
||||
../server/
|
||||
../containers/
|
||||
|
||||
[driver.ts]
|
||||
../**
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import type { GridFactory } from '../grid/gridServer';
|
|||
import { GridServer } from '../grid/gridServer';
|
||||
import type { Executable } from '../server';
|
||||
import { registry, writeDockerVersion } from '../server';
|
||||
import { addDockerCLI } from '../containers/docker';
|
||||
|
||||
const packageJSON = require('../../package.json');
|
||||
|
||||
|
|
@ -114,6 +115,7 @@ function checkBrowsersToInstall(args: string[]): Executable[] {
|
|||
return executables;
|
||||
}
|
||||
|
||||
|
||||
program
|
||||
.command('install [browser...]')
|
||||
.description('ensure browsers necessary for this version of Playwright are installed')
|
||||
|
|
@ -305,6 +307,8 @@ Examples:
|
|||
|
||||
$ show-trace https://example.com/trace.zip`);
|
||||
|
||||
addDockerCLI(program);
|
||||
|
||||
if (!process.env.PW_LANG_NAME) {
|
||||
let playwrightTestPackagePath = null;
|
||||
const resolvePwTestPaths = [__dirname, process.cwd()];
|
||||
|
|
|
|||
4
packages/playwright-core/src/containers/DEPS.list
Normal file
4
packages/playwright-core/src/containers/DEPS.list
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[*]
|
||||
../utils/
|
||||
../utilsBundle.ts
|
||||
../common/
|
||||
|
|
@ -17,13 +17,11 @@
|
|||
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { colors } from 'playwright-core/lib/utilsBundle';
|
||||
import { spawnAsync } from 'playwright-core/lib/utils/spawnAsync';
|
||||
import * as utils from 'playwright-core/lib/utils';
|
||||
import { getPlaywrightVersion } from 'playwright-core/lib/common/userAgent';
|
||||
import { spawnAsync } from '../utils/spawnAsync';
|
||||
import * as utils from '../utils';
|
||||
import { getPlaywrightVersion } from '../common/userAgent';
|
||||
import * as dockerApi from './dockerApi';
|
||||
import type { TestRunnerPlugin } from '../plugins';
|
||||
import type { FullConfig, Reporter, Suite } from '../../types/testReporter';
|
||||
import type { Command } from '../utilsBundle';
|
||||
|
||||
const VRT_IMAGE_DISTRO = 'focal';
|
||||
const VRT_IMAGE_NAME = `playwright:local-${getPlaywrightVersion()}-${VRT_IMAGE_DISTRO}`;
|
||||
|
|
@ -31,7 +29,7 @@ const VRT_CONTAINER_NAME = `playwright-${getPlaywrightVersion()}-${VRT_IMAGE_DIS
|
|||
const VRT_CONTAINER_LABEL_NAME = 'dev.playwright.vrt-service.version';
|
||||
const VRT_CONTAINER_LABEL_VALUE = '1';
|
||||
|
||||
export async function startPlaywrightContainer() {
|
||||
async function startPlaywrightContainer() {
|
||||
await checkDockerEngineIsRunningOrDie();
|
||||
|
||||
let info = await containerInfo();
|
||||
|
|
@ -52,7 +50,7 @@ export async function startPlaywrightContainer() {
|
|||
].join('\n'));
|
||||
}
|
||||
|
||||
export async function stopAllPlaywrightContainers() {
|
||||
async function stopAllPlaywrightContainers() {
|
||||
await checkDockerEngineIsRunningOrDie();
|
||||
|
||||
const allContainers = await dockerApi.listContainers();
|
||||
|
|
@ -63,7 +61,7 @@ export async function stopAllPlaywrightContainers() {
|
|||
})));
|
||||
}
|
||||
|
||||
export async function deletePlaywrightImage() {
|
||||
async function deletePlaywrightImage() {
|
||||
await checkDockerEngineIsRunningOrDie();
|
||||
|
||||
const dockerImage = await findDockerImage(VRT_IMAGE_NAME);
|
||||
|
|
@ -75,7 +73,7 @@ export async function deletePlaywrightImage() {
|
|||
await dockerApi.removeImage(dockerImage.imageId);
|
||||
}
|
||||
|
||||
export async function buildPlaywrightImage() {
|
||||
async function buildPlaywrightImage() {
|
||||
await checkDockerEngineIsRunningOrDie();
|
||||
|
||||
const isDevelopmentMode = getPlaywrightVersion().includes('next');
|
||||
|
|
@ -130,44 +128,12 @@ export async function buildPlaywrightImage() {
|
|||
console.log(`Done!`);
|
||||
}
|
||||
|
||||
export const dockerPlugin: TestRunnerPlugin = {
|
||||
name: 'playwright:docker',
|
||||
|
||||
async setup(config: FullConfig, configDir: string, rootSuite: Suite, reporter: Reporter) {
|
||||
if (!process.env.PLAYWRIGHT_DOCKER)
|
||||
return;
|
||||
|
||||
const print = (text: string) => reporter.onStdOut?.(text);
|
||||
const println = (text: string) => reporter.onStdOut?.(text + '\n');
|
||||
|
||||
println(colors.dim('Using docker container to run browsers.'));
|
||||
await checkDockerEngineIsRunningOrDie();
|
||||
let info = await containerInfo();
|
||||
if (!info) {
|
||||
print(colors.dim(`Starting docker container... `));
|
||||
const time = Date.now();
|
||||
info = await ensurePlaywrightContainerOrDie();
|
||||
const deltaMs = (Date.now() - time);
|
||||
println(colors.dim('Done in ' + (deltaMs / 1000).toFixed(1) + 's'));
|
||||
println(colors.dim('The Docker container will keep running after tests finished.'));
|
||||
println(colors.dim('Stop manually using:'));
|
||||
println(colors.dim(' npx playwright docker stop'));
|
||||
}
|
||||
println(colors.dim(`View screen: ${info.vncSession}`));
|
||||
println('');
|
||||
process.env.PW_TEST_CONNECT_WS_ENDPOINT = info.wsEndpoint;
|
||||
process.env.PW_TEST_CONNECT_HEADERS = JSON.stringify({
|
||||
'x-playwright-proxy': '*',
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
interface ContainerInfo {
|
||||
wsEndpoint: string;
|
||||
vncSession: string;
|
||||
}
|
||||
|
||||
export async function printDockerStatus() {
|
||||
async function printDockerStatus() {
|
||||
const isDockerEngine = await dockerApi.checkEngineRunning();
|
||||
const imageIsPulled = isDockerEngine && !!(await findDockerImage(VRT_IMAGE_NAME));
|
||||
const info = isDockerEngine ? await containerInfo() : undefined;
|
||||
|
|
@ -180,7 +146,7 @@ export async function printDockerStatus() {
|
|||
}, null, 2));
|
||||
}
|
||||
|
||||
async function containerInfo(): Promise<ContainerInfo|undefined> {
|
||||
export async function containerInfo(): Promise<ContainerInfo|undefined> {
|
||||
const allContainers = await dockerApi.listContainers();
|
||||
const pwDockerImage = await findDockerImage(VRT_IMAGE_NAME);
|
||||
const container = allContainers.find(container => container.imageId === pwDockerImage?.imageId && container.state === 'running');
|
||||
|
|
@ -210,7 +176,7 @@ async function containerInfo(): Promise<ContainerInfo|undefined> {
|
|||
return wsEndpoint && vncSession ? { wsEndpoint, vncSession } : undefined;
|
||||
}
|
||||
|
||||
async function ensurePlaywrightContainerOrDie(): Promise<ContainerInfo> {
|
||||
export async function ensurePlaywrightContainerOrDie(): Promise<ContainerInfo> {
|
||||
const pwImage = await findDockerImage(VRT_IMAGE_NAME);
|
||||
if (!pwImage) {
|
||||
throw createStacklessError('\n' + utils.wrapInASCIIBox([
|
||||
|
|
@ -284,7 +250,7 @@ async function ensurePlaywrightContainerOrDie(): Promise<ContainerInfo> {
|
|||
return info;
|
||||
}
|
||||
|
||||
async function checkDockerEngineIsRunningOrDie() {
|
||||
export async function checkDockerEngineIsRunningOrDie() {
|
||||
if (await dockerApi.checkEngineRunning())
|
||||
return;
|
||||
throw createStacklessError(utils.wrapInASCIIBox([
|
||||
|
|
@ -306,3 +272,54 @@ function createStacklessError(message: string) {
|
|||
error.stack = '';
|
||||
return error;
|
||||
}
|
||||
|
||||
export function addDockerCLI(program: Command) {
|
||||
const dockerCommand = program.command('docker')
|
||||
.description(`Manage Docker integration (EXPERIMENTAL)`);
|
||||
|
||||
dockerCommand.command('build')
|
||||
.description('build local docker image')
|
||||
.action(async function(options) {
|
||||
try {
|
||||
await buildPlaywrightImage();
|
||||
} catch (e) {
|
||||
console.error(e.stack ? e : e.message);
|
||||
}
|
||||
});
|
||||
|
||||
dockerCommand.command('start')
|
||||
.description('start docker container')
|
||||
.action(async function(options) {
|
||||
try {
|
||||
await startPlaywrightContainer();
|
||||
} catch (e) {
|
||||
console.error(e.stack ? e : e.message);
|
||||
}
|
||||
});
|
||||
|
||||
dockerCommand.command('stop')
|
||||
.description('stop docker container')
|
||||
.action(async function(options) {
|
||||
try {
|
||||
await stopAllPlaywrightContainers();
|
||||
} catch (e) {
|
||||
console.error(e.stack ? e : e.message);
|
||||
}
|
||||
});
|
||||
|
||||
dockerCommand.command('delete-image', { hidden: true })
|
||||
.description('delete docker image, if any')
|
||||
.action(async function(options) {
|
||||
try {
|
||||
await deletePlaywrightImage();
|
||||
} catch (e) {
|
||||
console.error(e.stack ? e : e.message);
|
||||
}
|
||||
});
|
||||
|
||||
dockerCommand.command('print-status-json', { hidden: true })
|
||||
.description('print docker status')
|
||||
.action(async function(options) {
|
||||
await printDockerStatus();
|
||||
});
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
[*]
|
||||
./utilsBundle.ts
|
||||
docker/
|
||||
matchers/
|
||||
reporters/
|
||||
third_party/
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
/* eslint-disable no-console */
|
||||
|
||||
import type { Command } from 'playwright-core/lib/utilsBundle';
|
||||
import * as docker from './docker/docker';
|
||||
import fs from 'fs';
|
||||
import url from 'url';
|
||||
import path from 'path';
|
||||
|
|
@ -33,58 +32,6 @@ export function addTestCommands(program: Command) {
|
|||
addTestCommand(program);
|
||||
addShowReportCommand(program);
|
||||
addListFilesCommand(program);
|
||||
addDockerCommand(program);
|
||||
}
|
||||
|
||||
function addDockerCommand(program: Command) {
|
||||
const dockerCommand = program.command('docker')
|
||||
.description(`Manage Docker integration (EXPERIMENTAL)`);
|
||||
|
||||
dockerCommand.command('build')
|
||||
.description('build local docker image')
|
||||
.action(async function(options) {
|
||||
try {
|
||||
await docker.buildPlaywrightImage();
|
||||
} catch (e) {
|
||||
console.error(e.stack ? e : e.message);
|
||||
}
|
||||
});
|
||||
|
||||
dockerCommand.command('start')
|
||||
.description('start docker container')
|
||||
.action(async function(options) {
|
||||
try {
|
||||
await docker.startPlaywrightContainer();
|
||||
} catch (e) {
|
||||
console.error(e.stack ? e : e.message);
|
||||
}
|
||||
});
|
||||
|
||||
dockerCommand.command('stop')
|
||||
.description('stop docker container')
|
||||
.action(async function(options) {
|
||||
try {
|
||||
await docker.stopAllPlaywrightContainers();
|
||||
} catch (e) {
|
||||
console.error(e.stack ? e : e.message);
|
||||
}
|
||||
});
|
||||
|
||||
dockerCommand.command('delete-image', { hidden: true })
|
||||
.description('delete docker image, if any')
|
||||
.action(async function(options) {
|
||||
try {
|
||||
await docker.deletePlaywrightImage();
|
||||
} catch (e) {
|
||||
console.error(e.stack ? e : e.message);
|
||||
}
|
||||
});
|
||||
|
||||
dockerCommand.command('print-status-json', { hidden: true })
|
||||
.description('print docker status')
|
||||
.action(async function(options) {
|
||||
await docker.printDockerStatus();
|
||||
});
|
||||
}
|
||||
|
||||
function addTestCommand(program: Command) {
|
||||
|
|
|
|||
54
packages/playwright-test/src/plugins/dockerPlugin.ts
Normal file
54
packages/playwright-test/src/plugins/dockerPlugin.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import type { TestRunnerPlugin } from '.';
|
||||
import type { FullConfig, Reporter, Suite } from '../../types/testReporter';
|
||||
import { colors } from 'playwright-core/lib/utilsBundle';
|
||||
import { checkDockerEngineIsRunningOrDie, containerInfo, ensurePlaywrightContainerOrDie } from 'playwright-core/lib/containers/docker';
|
||||
|
||||
export const dockerPlugin: TestRunnerPlugin = {
|
||||
name: 'playwright:docker',
|
||||
|
||||
async setup(config: FullConfig, configDir: string, rootSuite: Suite, reporter: Reporter) {
|
||||
if (!process.env.PLAYWRIGHT_DOCKER)
|
||||
return;
|
||||
|
||||
const print = (text: string) => reporter.onStdOut?.(text);
|
||||
const println = (text: string) => reporter.onStdOut?.(text + '\n');
|
||||
|
||||
println(colors.dim('Using docker container to run browsers.'));
|
||||
await checkDockerEngineIsRunningOrDie();
|
||||
let info = await containerInfo();
|
||||
if (!info) {
|
||||
print(colors.dim(`Starting docker container... `));
|
||||
const time = Date.now();
|
||||
info = await ensurePlaywrightContainerOrDie();
|
||||
const deltaMs = (Date.now() - time);
|
||||
println(colors.dim('Done in ' + (deltaMs / 1000).toFixed(1) + 's'));
|
||||
println(colors.dim('The Docker container will keep running after tests finished.'));
|
||||
println(colors.dim('Stop manually using:'));
|
||||
println(colors.dim(' npx playwright docker stop'));
|
||||
}
|
||||
println(colors.dim(`View screen: ${info.vncSession}`));
|
||||
println('');
|
||||
process.env.PW_TEST_CONNECT_WS_ENDPOINT = info.wsEndpoint;
|
||||
process.env.PW_TEST_CONNECT_HEADERS = JSON.stringify({
|
||||
'x-playwright-proxy': '*',
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ import { SigIntWatcher } from './sigIntWatcher';
|
|||
import type { TestRunnerPlugin } from './plugins';
|
||||
import { setRunnerToAddPluginsTo } from './plugins';
|
||||
import { webServerPluginsForConfig } from './plugins/webServerPlugin';
|
||||
import { dockerPlugin } from './docker/docker';
|
||||
import { dockerPlugin } from './plugins/dockerPlugin';
|
||||
import { MultiMap } from 'playwright-core/lib/utils/multimap';
|
||||
|
||||
const removeFolderAsync = promisify(rimraf);
|
||||
|
|
|
|||
|
|
@ -301,14 +301,14 @@ copyFiles.push({
|
|||
// Babel doesn't touch JS files, so copy them manually.
|
||||
// For example: diff_match_patch.js
|
||||
copyFiles.push({
|
||||
files: 'packages/playwright-core/src/**/*.js',
|
||||
files: 'packages/playwright-core/src/**/*.(js|sh)',
|
||||
from: 'packages/playwright-core/src',
|
||||
to: 'packages/playwright-core/lib',
|
||||
ignored: ['**/.eslintrc.js', '**/webpack*.config.js', '**/injected/**/*']
|
||||
});
|
||||
|
||||
copyFiles.push({
|
||||
files: 'packages/playwright-test/src/**/*.(js|sh)',
|
||||
files: 'packages/playwright-test/src/**/*.sh',
|
||||
from: 'packages/playwright-test/src',
|
||||
to: 'packages/playwright-test/lib',
|
||||
ignored: ['**/.eslintrc.js']
|
||||
|
|
|
|||
Loading…
Reference in a new issue