fix(docker): stop containers started with npx playwright docker start (#17316)

This patch makes `npx playwright docker stop` command to stop
containers that were launched with previous playwright version.
This commit is contained in:
Andrey Lushnikov 2022-09-13 17:08:01 -07:00 committed by GitHub
parent dfcd2a273d
commit 210f7b2203
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 16 deletions

View File

@ -55,7 +55,7 @@ function addDockerCommand(program: Command) {
dockerCommand.command('stop')
.description('stop docker container')
.action(async function(options) {
await docker.stopPlaywrightContainer();
await docker.stopAllPlaywrightContainers();
});
dockerCommand.command('delete-image', { hidden: true })

View File

@ -28,6 +28,8 @@ import type { FullConfig, Reporter, Suite } from '../../types/testReporter';
const VRT_IMAGE_DISTRO = 'focal';
const VRT_IMAGE_NAME = `playwright:local-${getPlaywrightVersion()}-${VRT_IMAGE_DISTRO}`;
const VRT_CONTAINER_NAME = `playwright-${getPlaywrightVersion()}-${VRT_IMAGE_DISTRO}`;
const VRT_CONTAINER_LABEL_NAME = 'dev.playwright.vrt-service.version';
const VRT_CONTAINER_LABEL_VALUE = '1';
export async function startPlaywrightContainer() {
await checkDockerEngineIsRunningOrDie();
@ -50,16 +52,15 @@ export async function startPlaywrightContainer() {
].join('\n'));
}
export async function stopPlaywrightContainer() {
export async function stopAllPlaywrightContainers() {
await checkDockerEngineIsRunningOrDie();
const container = await findRunningDockerContainer();
if (!container)
return;
await dockerApi.stopContainer({
const allContainers = await dockerApi.listContainers();
const vrtContainers = allContainers.filter(container => container.labels[VRT_CONTAINER_LABEL_NAME] === VRT_CONTAINER_LABEL_VALUE);
await Promise.all(vrtContainers.map(container => dockerApi.stopContainer({
containerId: container.containerId,
waitUntil: 'removed',
});
})));
}
export async function deletePlaywrightImage() {
@ -70,7 +71,7 @@ export async function deletePlaywrightImage() {
return;
if (await containerInfo())
await stopPlaywrightContainer();
await stopAllPlaywrightContainers();
await dockerApi.removeImage(dockerImage.imageId);
}
@ -168,7 +169,9 @@ interface ContainerInfo {
}
async function containerInfo(): Promise<ContainerInfo|undefined> {
const container = await findRunningDockerContainer();
const allContainers = await dockerApi.listContainers();
const pwDockerImage = await findDockerImage(VRT_IMAGE_NAME);
const container = allContainers.find(container => container.imageId === pwDockerImage?.imageId && container.state === 'running');
if (!container)
return undefined;
const logLines = await dockerApi.getContainerLogs(container.containerId);
@ -218,6 +221,9 @@ async function ensurePlaywrightContainerOrDie(): Promise<ContainerInfo> {
name: VRT_CONTAINER_NAME,
autoRemove: true,
ports: [5400, 7900],
labels: {
[VRT_CONTAINER_LABEL_NAME]: VRT_CONTAINER_LABEL_VALUE,
},
});
// Wait for the service to become available.
@ -251,10 +257,3 @@ async function findDockerImage(imageName: string): Promise<dockerApi.DockerImage
return images.find(image => image.names.includes(imageName));
}
async function findRunningDockerContainer(): Promise<dockerApi.DockerContainer|undefined> {
const containers = await dockerApi.listContainers();
const dockerImage = await findDockerImage(VRT_IMAGE_NAME);
const container = dockerImage ? containers.find(container => container.imageId === dockerImage.imageId) : undefined;
return container?.state === 'running' ? container : undefined;
}

View File

@ -33,6 +33,7 @@ export interface PortBinding {
export interface DockerContainer {
containerId: string;
labels: Record<string, string>;
imageId: string;
state: 'created'|'restarting'|'running'|'removing'|'paused'|'exited'|'dead';
names: string[];
@ -51,6 +52,7 @@ export async function listContainers(): Promise<DockerContainer[]> {
hostPort: portInfo.PublicPort,
containerPort: portInfo.PrivatePort,
})) ?? [],
labels: container.Labels ?? {},
}));
}
@ -58,6 +60,7 @@ interface LaunchContainerOptions {
imageId: string;
autoRemove: boolean;
command?: string[];
labels?: Record<string, string>;
ports?: Number[];
name?: string;
waitUntil?: 'not-running' | 'next-exit' | 'removed';
@ -72,6 +75,7 @@ export async function launchContainer(options: LaunchContainerOptions): Promise<
}
const container = await postJSON(`/containers/create` + (options.name ? '?name=' + options.name : ''), {
Cmd: options.command,
Labels: options.labels ?? {},
AttachStdout: true,
AttachStderr: true,
Image: options.imageId,