chore(docker): consolidate docker code (#17314)
This patch consolidates all of docker implementation under the `docker/` folder.
This commit is contained in:
parent
35a86a2d02
commit
881f3101bd
|
|
@ -21,7 +21,6 @@ import * as docker from './docker/docker';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { colors } from 'playwright-core/lib/utilsBundle';
|
|
||||||
import { Runner, builtInReporters, kDefaultConfigFiles } from './runner';
|
import { Runner, builtInReporters, kDefaultConfigFiles } from './runner';
|
||||||
import type { ConfigCLIOverrides } from './runner';
|
import type { ConfigCLIOverrides } from './runner';
|
||||||
import { stopProfiling, startProfiling } from './profiler';
|
import { stopProfiling, startProfiling } from './profiler';
|
||||||
|
|
@ -44,44 +43,25 @@ function addDockerCommand(program: Command) {
|
||||||
dockerCommand.command('build')
|
dockerCommand.command('build')
|
||||||
.description('build local docker image')
|
.description('build local docker image')
|
||||||
.action(async function(options) {
|
.action(async function(options) {
|
||||||
await docker.ensureDockerEngineIsRunningOrDie();
|
await docker.buildPlaywrightImage();
|
||||||
await docker.buildImage();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockerCommand.command('start')
|
dockerCommand.command('start')
|
||||||
.description('start docker container')
|
.description('start docker container')
|
||||||
.action(async function(options) {
|
.action(async function(options) {
|
||||||
await docker.ensureDockerEngineIsRunningOrDie();
|
await docker.startPlaywrightContainer();
|
||||||
let info = await docker.containerInfo();
|
|
||||||
if (!info) {
|
|
||||||
process.stdout.write(`Starting docker container... `);
|
|
||||||
const time = Date.now();
|
|
||||||
info = await docker.ensureContainerOrDie();
|
|
||||||
const deltaMs = (Date.now() - time);
|
|
||||||
console.log('Done in ' + (deltaMs / 1000).toFixed(1) + 's');
|
|
||||||
}
|
|
||||||
console.log([
|
|
||||||
`- View screen:`,
|
|
||||||
` ${info.vncSession}`,
|
|
||||||
`- Run tests with browsers inside container:`,
|
|
||||||
` npx playwright docker test`,
|
|
||||||
`- Stop background container *manually* when you are done working with tests:`,
|
|
||||||
` npx playwright docker stop`,
|
|
||||||
].join('\n'));
|
|
||||||
});
|
|
||||||
|
|
||||||
dockerCommand.command('delete-image', { hidden: true })
|
|
||||||
.description('delete docker image, if any')
|
|
||||||
.action(async function(options) {
|
|
||||||
await docker.ensureDockerEngineIsRunningOrDie();
|
|
||||||
await docker.deleteImage();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockerCommand.command('stop')
|
dockerCommand.command('stop')
|
||||||
.description('stop docker container')
|
.description('stop docker container')
|
||||||
.action(async function(options) {
|
.action(async function(options) {
|
||||||
await docker.ensureDockerEngineIsRunningOrDie();
|
await docker.stopPlaywrightContainer();
|
||||||
await docker.stopContainer();
|
});
|
||||||
|
|
||||||
|
dockerCommand.command('delete-image', { hidden: true })
|
||||||
|
.description('delete docker image, if any')
|
||||||
|
.action(async function(options) {
|
||||||
|
await docker.deletePlaywrightImage();
|
||||||
});
|
});
|
||||||
|
|
||||||
addTestCommand(dockerCommand, true /* isDocker */);
|
addTestCommand(dockerCommand, true /* isDocker */);
|
||||||
|
|
@ -121,27 +101,8 @@ function addTestCommand(program: Command, isDocker: boolean) {
|
||||||
command.action(async (args, opts) => {
|
command.action(async (args, opts) => {
|
||||||
try {
|
try {
|
||||||
isDocker = isDocker || !!process.env.PLAYWRIGHT_DOCKER;
|
isDocker = isDocker || !!process.env.PLAYWRIGHT_DOCKER;
|
||||||
if (isDocker && !process.env.PW_TS_ESM_ON) {
|
if (isDocker && !process.env.PW_TS_ESM_ON)
|
||||||
console.log(colors.dim('Using docker container to run browsers.'));
|
await docker.configureTestRunnerToUseDocker();
|
||||||
await docker.ensureDockerEngineIsRunningOrDie();
|
|
||||||
let info = await docker.containerInfo();
|
|
||||||
if (!info) {
|
|
||||||
process.stdout.write(colors.dim(`Starting docker container... `));
|
|
||||||
const time = Date.now();
|
|
||||||
info = await docker.ensureContainerOrDie();
|
|
||||||
const deltaMs = (Date.now() - time);
|
|
||||||
console.log(colors.dim('Done in ' + (deltaMs / 1000).toFixed(1) + 's'));
|
|
||||||
console.log(colors.dim('The Docker container will keep running after tests finished.'));
|
|
||||||
console.log(colors.dim('Stop manually using:'));
|
|
||||||
console.log(colors.dim(' npx playwright docker stop'));
|
|
||||||
}
|
|
||||||
console.log(colors.dim(`View screen: ${info.vncSession}`));
|
|
||||||
process.env.PW_TEST_CONNECT_WS_ENDPOINT = info.wsEndpoint;
|
|
||||||
process.env.PW_TEST_CONNECT_HEADERS = JSON.stringify({
|
|
||||||
'x-playwright-proxy': '*',
|
|
||||||
});
|
|
||||||
process.env.PLAYWRIGHT_DOCKER = '1';
|
|
||||||
}
|
|
||||||
await runTests(args, opts);
|
await runTests(args, opts);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import { colors } from 'playwright-core/lib/utilsBundle';
|
||||||
import { spawnAsync } from 'playwright-core/lib/utils/spawnAsync';
|
import { spawnAsync } from 'playwright-core/lib/utils/spawnAsync';
|
||||||
import * as utils from 'playwright-core/lib/utils';
|
import * as utils from 'playwright-core/lib/utils';
|
||||||
import { getPlaywrightVersion } from 'playwright-core/lib/common/userAgent';
|
import { getPlaywrightVersion } from 'playwright-core/lib/common/userAgent';
|
||||||
|
|
@ -26,17 +27,54 @@ const VRT_IMAGE_DISTRO = 'focal';
|
||||||
const VRT_IMAGE_NAME = `playwright:local-${getPlaywrightVersion()}-${VRT_IMAGE_DISTRO}`;
|
const VRT_IMAGE_NAME = `playwright:local-${getPlaywrightVersion()}-${VRT_IMAGE_DISTRO}`;
|
||||||
const VRT_CONTAINER_NAME = `playwright-${getPlaywrightVersion()}-${VRT_IMAGE_DISTRO}`;
|
const VRT_CONTAINER_NAME = `playwright-${getPlaywrightVersion()}-${VRT_IMAGE_DISTRO}`;
|
||||||
|
|
||||||
export async function deleteImage() {
|
export async function startPlaywrightContainer() {
|
||||||
|
await checkDockerEngineIsRunningOrDie();
|
||||||
|
|
||||||
|
let info = await containerInfo();
|
||||||
|
if (!info) {
|
||||||
|
process.stdout.write(`Starting docker container... `);
|
||||||
|
const time = Date.now();
|
||||||
|
info = await ensurePlaywrightContainerOrDie();
|
||||||
|
const deltaMs = (Date.now() - time);
|
||||||
|
console.log('Done in ' + (deltaMs / 1000).toFixed(1) + 's');
|
||||||
|
}
|
||||||
|
console.log([
|
||||||
|
`- View screen:`,
|
||||||
|
` ${info.vncSession}`,
|
||||||
|
`- Run tests with browsers inside container:`,
|
||||||
|
` npx playwright docker test`,
|
||||||
|
`- Stop background container *manually* when you are done working with tests:`,
|
||||||
|
` npx playwright docker stop`,
|
||||||
|
].join('\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function stopPlaywrightContainer() {
|
||||||
|
await checkDockerEngineIsRunningOrDie();
|
||||||
|
|
||||||
|
const container = await findRunningDockerContainer();
|
||||||
|
if (!container)
|
||||||
|
return;
|
||||||
|
await dockerApi.stopContainer({
|
||||||
|
containerId: container.containerId,
|
||||||
|
waitUntil: 'removed',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deletePlaywrightImage() {
|
||||||
|
await checkDockerEngineIsRunningOrDie();
|
||||||
|
|
||||||
const dockerImage = await findDockerImage(VRT_IMAGE_NAME);
|
const dockerImage = await findDockerImage(VRT_IMAGE_NAME);
|
||||||
if (!dockerImage)
|
if (!dockerImage)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (await containerInfo())
|
if (await containerInfo())
|
||||||
await stopContainer();
|
await stopPlaywrightContainer();
|
||||||
await dockerApi.removeImage(dockerImage.imageId);
|
await dockerApi.removeImage(dockerImage.imageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function buildImage() {
|
export async function buildPlaywrightImage() {
|
||||||
|
await checkDockerEngineIsRunningOrDie();
|
||||||
|
|
||||||
const isDevelopmentMode = getPlaywrightVersion().includes('next');
|
const isDevelopmentMode = getPlaywrightVersion().includes('next');
|
||||||
let baseImageName = `mcr.microsoft.com/playwright:v${getPlaywrightVersion()}-${VRT_IMAGE_DISTRO}`;
|
let baseImageName = `mcr.microsoft.com/playwright:v${getPlaywrightVersion()}-${VRT_IMAGE_DISTRO}`;
|
||||||
// 1. Build or pull base image.
|
// 1. Build or pull base image.
|
||||||
|
|
@ -90,12 +128,35 @@ export async function buildImage() {
|
||||||
console.log(`Done!`);
|
console.log(`Done!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function configureTestRunnerToUseDocker() {
|
||||||
|
console.log(colors.dim('Using docker container to run browsers.'));
|
||||||
|
await checkDockerEngineIsRunningOrDie();
|
||||||
|
let info = await containerInfo();
|
||||||
|
if (!info) {
|
||||||
|
process.stdout.write(colors.dim(`Starting docker container... `));
|
||||||
|
const time = Date.now();
|
||||||
|
info = await ensurePlaywrightContainerOrDie();
|
||||||
|
const deltaMs = (Date.now() - time);
|
||||||
|
console.log(colors.dim('Done in ' + (deltaMs / 1000).toFixed(1) + 's'));
|
||||||
|
console.log(colors.dim('The Docker container will keep running after tests finished.'));
|
||||||
|
console.log(colors.dim('Stop manually using:'));
|
||||||
|
console.log(colors.dim(' npx playwright docker stop'));
|
||||||
|
}
|
||||||
|
console.log(colors.dim(`View screen: ${info.vncSession}`));
|
||||||
|
process.env.PW_TEST_CONNECT_WS_ENDPOINT = info.wsEndpoint;
|
||||||
|
process.env.PW_TEST_CONNECT_HEADERS = JSON.stringify({
|
||||||
|
'x-playwright-proxy': '*',
|
||||||
|
});
|
||||||
|
process.env.PLAYWRIGHT_DOCKER = '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
interface ContainerInfo {
|
interface ContainerInfo {
|
||||||
wsEndpoint: string;
|
wsEndpoint: string;
|
||||||
vncSession: string;
|
vncSession: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function containerInfo(): Promise<ContainerInfo|undefined> {
|
async function containerInfo(): Promise<ContainerInfo|undefined> {
|
||||||
const container = await findRunningDockerContainer();
|
const container = await findRunningDockerContainer();
|
||||||
if (!container)
|
if (!container)
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
@ -123,7 +184,7 @@ export async function containerInfo(): Promise<ContainerInfo|undefined> {
|
||||||
return wsEndpoint && vncSession ? { wsEndpoint, vncSession } : undefined;
|
return wsEndpoint && vncSession ? { wsEndpoint, vncSession } : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function ensureContainerOrDie(): Promise<ContainerInfo> {
|
async function ensurePlaywrightContainerOrDie(): Promise<ContainerInfo> {
|
||||||
const pwImage = await findDockerImage(VRT_IMAGE_NAME);
|
const pwImage = await findDockerImage(VRT_IMAGE_NAME);
|
||||||
if (!pwImage) {
|
if (!pwImage) {
|
||||||
console.error('\n' + utils.wrapInASCIIBox([
|
console.error('\n' + utils.wrapInASCIIBox([
|
||||||
|
|
@ -161,17 +222,7 @@ export async function ensureContainerOrDie(): Promise<ContainerInfo> {
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function stopContainer() {
|
async function checkDockerEngineIsRunningOrDie() {
|
||||||
const container = await findRunningDockerContainer();
|
|
||||||
if (!container)
|
|
||||||
return;
|
|
||||||
await dockerApi.stopContainer({
|
|
||||||
containerId: container.containerId,
|
|
||||||
waitUntil: 'removed',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function ensureDockerEngineIsRunningOrDie() {
|
|
||||||
if (await dockerApi.checkEngineRunning())
|
if (await dockerApi.checkEngineRunning())
|
||||||
return;
|
return;
|
||||||
console.error(utils.wrapInASCIIBox([
|
console.error(utils.wrapInASCIIBox([
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue