mirror of
https://github.com/hoverkraft-tech/compose-action.git
synced 2026-08-31 23:52:49 +08:00
fix: avoid buffering compose logs during cleanup
Co-authored-by: neilime <314088+neilime@users.noreply.github.com>
This commit is contained in:
parent
26f805aa21
commit
75b024b03b
33
dist/index.js
generated
vendored
33
dist/index.js
generated
vendored
@ -31409,20 +31409,42 @@ var DockerComposeService = class {
|
||||
composeFiles: optionsInputs.composeFiles,
|
||||
commandArgs: services
|
||||
});
|
||||
return await new Promise((resolve2, reject) => {
|
||||
return new Promise((resolve2) => {
|
||||
let settled = false;
|
||||
const childProcess = spawn2("docker", commandArgs, {
|
||||
cwd: optionsInputs.cwd
|
||||
});
|
||||
childProcess.on("error", reject);
|
||||
childProcess.on("error", (error2) => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
resolve2({
|
||||
error: `Unable to collect docker compose logs: ${error2.message}`,
|
||||
output: ""
|
||||
});
|
||||
});
|
||||
if (!childProcess.stdout || !childProcess.stderr) {
|
||||
settled = true;
|
||||
resolve2({
|
||||
error: "Unable to collect docker compose logs: stdout/stderr unavailable",
|
||||
output: ""
|
||||
});
|
||||
return;
|
||||
}
|
||||
childProcess.stdout.on("data", (chunk) => {
|
||||
optionsInputs.serviceLogger(chunk.toString());
|
||||
});
|
||||
childProcess.stderr.on("data", (chunk) => {
|
||||
optionsInputs.serviceLogger(chunk.toString());
|
||||
});
|
||||
childProcess.on("close", (exitCode) => {
|
||||
childProcess.on("close", (exitCode, signal) => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
resolve2({
|
||||
error: exitCode && exitCode !== 0 ? `Docker Compose logs command failed with exit code ${exitCode}` : "",
|
||||
error: signal ? `Docker Compose logs command failed with signal ${signal}` : exitCode !== null && exitCode !== 0 ? `Docker Compose logs command failed with exit code ${exitCode}` : "",
|
||||
output: ""
|
||||
});
|
||||
});
|
||||
@ -31446,6 +31468,9 @@ var DockerComposeService = class {
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Builds docker CLI arguments in the order expected by `docker compose`.
|
||||
*/
|
||||
getDockerComposeCommandArgs(command, {
|
||||
dockerFlags,
|
||||
composeFlags,
|
||||
|
||||
33
dist/post.js
generated
vendored
33
dist/post.js
generated
vendored
@ -27146,20 +27146,42 @@ var DockerComposeService = class {
|
||||
composeFiles: optionsInputs.composeFiles,
|
||||
commandArgs: services
|
||||
});
|
||||
return await new Promise((resolve, reject) => {
|
||||
return new Promise((resolve) => {
|
||||
let settled = false;
|
||||
const childProcess = spawn("docker", commandArgs, {
|
||||
cwd: optionsInputs.cwd
|
||||
});
|
||||
childProcess.on("error", reject);
|
||||
childProcess.on("error", (error2) => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
resolve({
|
||||
error: `Unable to collect docker compose logs: ${error2.message}`,
|
||||
output: ""
|
||||
});
|
||||
});
|
||||
if (!childProcess.stdout || !childProcess.stderr) {
|
||||
settled = true;
|
||||
resolve({
|
||||
error: "Unable to collect docker compose logs: stdout/stderr unavailable",
|
||||
output: ""
|
||||
});
|
||||
return;
|
||||
}
|
||||
childProcess.stdout.on("data", (chunk) => {
|
||||
optionsInputs.serviceLogger(chunk.toString());
|
||||
});
|
||||
childProcess.stderr.on("data", (chunk) => {
|
||||
optionsInputs.serviceLogger(chunk.toString());
|
||||
});
|
||||
childProcess.on("close", (exitCode) => {
|
||||
childProcess.on("close", (exitCode, signal) => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
resolve({
|
||||
error: exitCode && exitCode !== 0 ? `Docker Compose logs command failed with exit code ${exitCode}` : "",
|
||||
error: signal ? `Docker Compose logs command failed with signal ${signal}` : exitCode !== null && exitCode !== 0 ? `Docker Compose logs command failed with exit code ${exitCode}` : "",
|
||||
output: ""
|
||||
});
|
||||
});
|
||||
@ -27183,6 +27205,9 @@ var DockerComposeService = class {
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Builds docker CLI arguments in the order expected by `docker compose`.
|
||||
*/
|
||||
getDockerComposeCommandArgs(command, {
|
||||
dockerFlags,
|
||||
composeFlags,
|
||||
|
||||
@ -440,5 +440,85 @@ describe("DockerComposeService", () => {
|
||||
output: "",
|
||||
});
|
||||
});
|
||||
|
||||
it("should return a non-fatal error message when logs command is terminated by a signal", async () => {
|
||||
const logsInputs = {
|
||||
dockerFlags: [] as string[],
|
||||
composeFiles: ["docker-compose.yml"] as string[],
|
||||
services: [] as string[],
|
||||
composeFlags: [] as string[],
|
||||
cwd: "/current/working/dir",
|
||||
serviceLogger: vi.fn(),
|
||||
};
|
||||
|
||||
const childProcess = new EventEmitter() as EventEmitter & {
|
||||
stdout: EventEmitter;
|
||||
stderr: EventEmitter;
|
||||
};
|
||||
childProcess.stdout = new EventEmitter();
|
||||
childProcess.stderr = new EventEmitter();
|
||||
spawnMock.mockReturnValue(childProcess);
|
||||
|
||||
const logsPromise = service.logs(logsInputs);
|
||||
|
||||
childProcess.emit("close", null, "SIGTERM");
|
||||
|
||||
await expect(logsPromise).resolves.toEqual({
|
||||
error: "Docker Compose logs command failed with signal SIGTERM",
|
||||
output: "",
|
||||
});
|
||||
});
|
||||
|
||||
it("should return a non-fatal error message when spawning logs fails", async () => {
|
||||
const logsInputs = {
|
||||
dockerFlags: [] as string[],
|
||||
composeFiles: ["docker-compose.yml"] as string[],
|
||||
services: [] as string[],
|
||||
composeFlags: [] as string[],
|
||||
cwd: "/current/working/dir",
|
||||
serviceLogger: vi.fn(),
|
||||
};
|
||||
|
||||
const childProcess = new EventEmitter() as EventEmitter & {
|
||||
stdout: EventEmitter;
|
||||
stderr: EventEmitter;
|
||||
};
|
||||
childProcess.stdout = new EventEmitter();
|
||||
childProcess.stderr = new EventEmitter();
|
||||
spawnMock.mockReturnValue(childProcess);
|
||||
|
||||
const logsPromise = service.logs(logsInputs);
|
||||
|
||||
childProcess.emit("error", new Error("spawn ENOENT"));
|
||||
|
||||
await expect(logsPromise).resolves.toEqual({
|
||||
error: "Unable to collect docker compose logs: spawn ENOENT",
|
||||
output: "",
|
||||
});
|
||||
});
|
||||
|
||||
it("should return a non-fatal error message when output streams are unavailable", async () => {
|
||||
const logsInputs = {
|
||||
dockerFlags: [] as string[],
|
||||
composeFiles: ["docker-compose.yml"] as string[],
|
||||
services: [] as string[],
|
||||
composeFlags: [] as string[],
|
||||
cwd: "/current/working/dir",
|
||||
serviceLogger: vi.fn(),
|
||||
};
|
||||
|
||||
const childProcess = new EventEmitter() as EventEmitter & {
|
||||
stdout: EventEmitter | null;
|
||||
stderr: EventEmitter | null;
|
||||
};
|
||||
childProcess.stdout = null;
|
||||
childProcess.stderr = null;
|
||||
spawnMock.mockReturnValue(childProcess);
|
||||
|
||||
await expect(service.logs(logsInputs)).resolves.toEqual({
|
||||
error: "Unable to collect docker compose logs: stdout/stderr unavailable",
|
||||
output: "",
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -66,22 +66,47 @@ export class DockerComposeService {
|
||||
commandArgs: services,
|
||||
});
|
||||
|
||||
return await new Promise((resolve, reject) => {
|
||||
return new Promise((resolve) => {
|
||||
let settled = false;
|
||||
const childProcess = spawn("docker", commandArgs, {
|
||||
cwd: optionsInputs.cwd,
|
||||
});
|
||||
|
||||
childProcess.on("error", reject);
|
||||
childProcess.stdout.on("data", (chunk: Buffer) => {
|
||||
childProcess.on("error", (error) => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
resolve({
|
||||
error: `Unable to collect docker compose logs: ${error.message}`,
|
||||
output: "",
|
||||
});
|
||||
});
|
||||
if (!childProcess.stdout || !childProcess.stderr) {
|
||||
settled = true;
|
||||
resolve({
|
||||
error: "Unable to collect docker compose logs: stdout/stderr unavailable",
|
||||
output: "",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
childProcess.stdout.on("data", (chunk: Buffer | string) => {
|
||||
optionsInputs.serviceLogger(chunk.toString());
|
||||
});
|
||||
childProcess.stderr.on("data", (chunk: Buffer) => {
|
||||
childProcess.stderr.on("data", (chunk: Buffer | string) => {
|
||||
optionsInputs.serviceLogger(chunk.toString());
|
||||
});
|
||||
childProcess.on("close", (exitCode) => {
|
||||
childProcess.on("close", (exitCode, signal) => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
resolve({
|
||||
error:
|
||||
exitCode && exitCode !== 0
|
||||
signal
|
||||
? `Docker Compose logs command failed with signal ${signal}`
|
||||
: exitCode !== null && exitCode !== 0
|
||||
? `Docker Compose logs command failed with exit code ${exitCode}`
|
||||
: "",
|
||||
output: "",
|
||||
@ -109,8 +134,11 @@ export class DockerComposeService {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds docker CLI arguments in the order expected by `docker compose`.
|
||||
*/
|
||||
private getDockerComposeCommandArgs(
|
||||
command: string,
|
||||
command: "logs",
|
||||
{
|
||||
dockerFlags,
|
||||
composeFlags,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user