From 881f3101bd9d195ac0953c27e02105d7b6538186 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Tue, 13 Sep 2022 16:14:49 -0700 Subject: [PATCH] chore(docker): consolidate docker code (#17314) This patch consolidates all of docker implementation under the `docker/` folder. --- packages/playwright-test/src/cli.ts | 61 +++----------- packages/playwright-test/src/docker/docker.ts | 83 +++++++++++++++---- 2 files changed, 78 insertions(+), 66 deletions(-) diff --git a/packages/playwright-test/src/cli.ts b/packages/playwright-test/src/cli.ts index 25472a9839..a158ca2753 100644 --- a/packages/playwright-test/src/cli.ts +++ b/packages/playwright-test/src/cli.ts @@ -21,7 +21,6 @@ import * as docker from './docker/docker'; import fs from 'fs'; import url from 'url'; import path from 'path'; -import { colors } from 'playwright-core/lib/utilsBundle'; import { Runner, builtInReporters, kDefaultConfigFiles } from './runner'; import type { ConfigCLIOverrides } from './runner'; import { stopProfiling, startProfiling } from './profiler'; @@ -44,44 +43,25 @@ function addDockerCommand(program: Command) { dockerCommand.command('build') .description('build local docker image') .action(async function(options) { - await docker.ensureDockerEngineIsRunningOrDie(); - await docker.buildImage(); + await docker.buildPlaywrightImage(); }); dockerCommand.command('start') .description('start docker container') .action(async function(options) { - await docker.ensureDockerEngineIsRunningOrDie(); - 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(); + await docker.startPlaywrightContainer(); }); dockerCommand.command('stop') .description('stop docker container') .action(async function(options) { - await docker.ensureDockerEngineIsRunningOrDie(); - await docker.stopContainer(); + await docker.stopPlaywrightContainer(); + }); + + dockerCommand.command('delete-image', { hidden: true }) + .description('delete docker image, if any') + .action(async function(options) { + await docker.deletePlaywrightImage(); }); addTestCommand(dockerCommand, true /* isDocker */); @@ -121,27 +101,8 @@ function addTestCommand(program: Command, isDocker: boolean) { command.action(async (args, opts) => { try { isDocker = isDocker || !!process.env.PLAYWRIGHT_DOCKER; - if (isDocker && !process.env.PW_TS_ESM_ON) { - console.log(colors.dim('Using docker container to run browsers.')); - 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'; - } + if (isDocker && !process.env.PW_TS_ESM_ON) + await docker.configureTestRunnerToUseDocker(); await runTests(args, opts); } catch (e) { console.error(e); diff --git a/packages/playwright-test/src/docker/docker.ts b/packages/playwright-test/src/docker/docker.ts index aa8900196a..b86dab8a56 100644 --- a/packages/playwright-test/src/docker/docker.ts +++ b/packages/playwright-test/src/docker/docker.ts @@ -17,6 +17,7 @@ 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'; @@ -26,17 +27,54 @@ const VRT_IMAGE_DISTRO = 'focal'; const VRT_IMAGE_NAME = `playwright:local-${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); if (!dockerImage) return; if (await containerInfo()) - await stopContainer(); + await stopPlaywrightContainer(); await dockerApi.removeImage(dockerImage.imageId); } -export async function buildImage() { +export async function buildPlaywrightImage() { + await checkDockerEngineIsRunningOrDie(); + const isDevelopmentMode = getPlaywrightVersion().includes('next'); let baseImageName = `mcr.microsoft.com/playwright:v${getPlaywrightVersion()}-${VRT_IMAGE_DISTRO}`; // 1. Build or pull base image. @@ -90,12 +128,35 @@ export async function buildImage() { 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 { wsEndpoint: string; vncSession: string; } -export async function containerInfo(): Promise { +async function containerInfo(): Promise { const container = await findRunningDockerContainer(); if (!container) return undefined; @@ -123,7 +184,7 @@ export async function containerInfo(): Promise { return wsEndpoint && vncSession ? { wsEndpoint, vncSession } : undefined; } -export async function ensureContainerOrDie(): Promise { +async function ensurePlaywrightContainerOrDie(): Promise { const pwImage = await findDockerImage(VRT_IMAGE_NAME); if (!pwImage) { console.error('\n' + utils.wrapInASCIIBox([ @@ -161,17 +222,7 @@ export async function ensureContainerOrDie(): Promise { return info; } -export async function stopContainer() { - const container = await findRunningDockerContainer(); - if (!container) - return; - await dockerApi.stopContainer({ - containerId: container.containerId, - waitUntil: 'removed', - }); -} - -export async function ensureDockerEngineIsRunningOrDie() { +async function checkDockerEngineIsRunningOrDie() { if (await dockerApi.checkEngineRunning()) return; console.error(utils.wrapInASCIIBox([