Skip to content

Commit

Permalink
Fix run in container flakiness (#489)
Browse files Browse the repository at this point in the history
  • Loading branch information
cristianrgreco authored Mar 9, 2023
1 parent 351973a commit d69689d
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 29 deletions.
39 changes: 10 additions & 29 deletions src/docker/functions/run-in-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { DockerImageName } from "../../docker-image-name";
import { pullImage } from "./image/pull-image";
import { startContainer } from "./container/start-container";
import { attachContainer } from "./container/attach-container";
import { inspectContainer } from "./container/inspect-container";
import Dockerode from "dockerode";
import { streamToString } from "../../stream-utils";

export const runInContainer = async (
dockerode: Dockerode,
Expand All @@ -13,43 +13,24 @@ export const runInContainer = async (
command: string[]
): Promise<string | undefined> => {
try {
const imageName = DockerImageName.fromString(image);

await pullImage(dockerode, indexServerAddress, { imageName, force: false });
await pullImage(dockerode, indexServerAddress, { imageName: DockerImageName.fromString(image), force: false });

log.debug(`Creating container: ${image} with command: ${command.join(" ")}`);
const container = await dockerode.createContainer({ Image: image, Cmd: command, HostConfig: { AutoRemove: true } });
const container = await dockerode.createContainer({ Image: image, Cmd: command });

log.debug(`Attaching to container: ${container.id}`);
const stream = await attachContainer(dockerode, container);

const promise = new Promise<string>((resolve) => {
const interval = setInterval(async () => {
const inspect = await inspectContainer(container);

if (inspect.state.status === "exited") {
clearInterval(interval);
stream.destroy();
}
}, 100);

const chunks: string[] = [];
stream.on("data", (chunk) => chunks.push(chunk));
stream.on("end", () => {
clearInterval(interval);
resolve(chunks.join("").trim());
});
});

log.debug(`Starting container: ${container.id}`);
await startContainer(container);

log.debug(`Waiting for container output: ${container.id}`);
const output = await promise;
const output = await streamToString(stream, { trim: true });

log.debug(`Removing container: ${container.id}`);
await container.remove({ force: true, v: true });

if (output.length === 0) {
return undefined;
} else {
return output;
}
return output.length === 0 ? undefined : output;
} catch (err) {
log.error(`Failed to run command in container: "${command.join(" ")}", error: "${err}"`);
return undefined;
Expand Down
15 changes: 15 additions & 0 deletions src/stream-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Readable } from "stream";

type Options = { trim: boolean };

export const streamToString = async (stream: Readable, options: Options = { trim: false }): Promise<string> => {
const chunks = [];

for await (const chunk of stream) {
chunks.push(Buffer.from(chunk));
}

const str = Buffer.concat(chunks).toString("utf-8");

return options.trim ? str.trim() : str;
};

0 comments on commit d69689d

Please sign in to comment.