feat: make docker-compose cwd aware

Signed-off-by: Emilien Escalle <emilien.escalle@escemi.com>
This commit is contained in:
Emilien Escalle 2024-04-02 11:08:11 +02:00 committed by Emilien Escalle
parent 43a233a413
commit 9e48869ba4
10 changed files with 110 additions and 22 deletions

View File

@ -104,3 +104,27 @@ jobs:
docker-compose -f ./docker/docker-compose.yml -f ./docker/docker-compose.ci.yml ps | grep docker-helloworld4-1
docker-compose -f ./docker/docker-compose.yml -f ./docker/docker-compose.ci.yml ps | (grep docker-helloworld-1 && echo "Unexpected service is running" && exit 1) || true
docker-compose -f ./docker/docker-compose.yml -f ./docker/docker-compose.ci.yml ps | (grep docker-helloworld3-1 && echo "Unexpected service is running" && exit 1) || true
test-action-with-cwd:
runs-on: ubuntu-latest
name: Test with cwd
steps:
- uses: actions/checkout@v4
- uses: hoverkraft-tech/ci-github-nodejs/actions/setup-node@0.4.2
- name: Act
uses: ./
with:
compose-file: "docker-compose.yml"
cwd: "./docker"
services: |
helloworld2
helloworld3
- name: "Assert: only expected services are running"
run: |
docker-compose -f ./docker/docker-compose.yml ps
docker-compose -f ./docker/docker-compose.yml ps | grep docker-helloworld2-1
docker-compose -f ./docker/docker-compose.yml ps | grep docker-helloworld3-1
docker-compose -f ./docker/docker-compose.yml ps | (grep docker-helloworld-1 && echo "Unexpected service helloworld is running" && exit 1) || true

1
.prettierignore Normal file
View File

@ -0,0 +1 @@
dist

View File

@ -1,31 +1,34 @@
name: 'Docker Compose Action'
description:
'This action runs your docker-compose file and clean up before action finished'
author: 'Hoverkraft'
name: "Docker Compose Action"
description: "This action runs your docker-compose file and clean up before action finished"
author: "Hoverkraft"
branding:
icon: anchor
color: gray-dark
inputs:
compose-file:
description: 'Relative path to compose file(s). It can be a list of files.'
description: "Relative path to compose file(s). It can be a list of files."
required: false
default: './docker-compose.yml'
default: "./docker-compose.yml"
services:
description: 'Services to perform docker-compose up.'
description: "Services to perform docker-compose up."
required: false
up-flags:
description: 'Additional options to pass to `docker-compose up` command.'
description: "Additional options to pass to `docker-compose up` command."
required: false
default: ''
default: ""
down-flags:
description: 'Additional options to pass to `docker-compose down` command.'
description: "Additional options to pass to `docker-compose down` command."
required: false
default: ''
default: ""
compose-flags:
description: 'Additional options to pass to `docker-compose` command.'
description: "Additional options to pass to `docker-compose` command."
required: false
default: ''
default: ""
cwd:
description: "Current working directory"
required: false
default: ${{ github.workspace }}
runs:
using: node20
main: dist/index.js

12
dist/index.js generated vendored
View File

@ -26002,6 +26002,7 @@ class DockerComposeService {
config: inputs.composeFiles,
log: true,
composeOptions: inputs.composeFlags,
cwd: inputs.cwd,
};
}
}
@ -26019,6 +26020,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.InputService = exports.InputNames = void 0;
const core_1 = __nccwpck_require__(2186);
const fs_1 = __nccwpck_require__(7147);
const path_1 = __nccwpck_require__(1017);
var InputNames;
(function (InputNames) {
InputNames["ComposeFile"] = "compose-file";
@ -26026,6 +26028,7 @@ var InputNames;
InputNames["ComposeFlags"] = "compose-flags";
InputNames["UpFlags"] = "up-flags";
InputNames["DownFlags"] = "down-flags";
InputNames["Cwd"] = "cwd";
})(InputNames || (exports.InputNames = InputNames = {}));
class InputService {
logger;
@ -26039,15 +26042,17 @@ class InputService {
composeFlags: this.getComposeFlags(),
upFlags: this.getUpFlags(),
downFlags: this.getDownFlags(),
cwd: this.getCwd(),
};
}
getComposeFiles() {
const cwd = this.getCwd();
return (0, core_1.getMultilineInput)(InputNames.ComposeFile).filter((composeFile) => {
if (!composeFile.length) {
return false;
}
if (!(0, fs_1.existsSync)(composeFile)) {
this.logger.warn(`${composeFile} not exists`);
if (!(0, fs_1.existsSync)((0, path_1.join)(cwd, composeFile))) {
this.logger.warn(`${composeFile} does not exist in ${cwd}`);
return false;
}
return true;
@ -26071,6 +26076,9 @@ class InputService {
}
return flags.trim().split(" ");
}
getCwd() {
return (0, core_1.getInput)(InputNames.Cwd);
}
}
exports.InputService = InputService;

12
dist/post.js generated vendored
View File

@ -26002,6 +26002,7 @@ class DockerComposeService {
config: inputs.composeFiles,
log: true,
composeOptions: inputs.composeFlags,
cwd: inputs.cwd,
};
}
}
@ -26019,6 +26020,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.InputService = exports.InputNames = void 0;
const core_1 = __nccwpck_require__(2186);
const fs_1 = __nccwpck_require__(7147);
const path_1 = __nccwpck_require__(1017);
var InputNames;
(function (InputNames) {
InputNames["ComposeFile"] = "compose-file";
@ -26026,6 +26028,7 @@ var InputNames;
InputNames["ComposeFlags"] = "compose-flags";
InputNames["UpFlags"] = "up-flags";
InputNames["DownFlags"] = "down-flags";
InputNames["Cwd"] = "cwd";
})(InputNames || (exports.InputNames = InputNames = {}));
class InputService {
logger;
@ -26039,15 +26042,17 @@ class InputService {
composeFlags: this.getComposeFlags(),
upFlags: this.getUpFlags(),
downFlags: this.getDownFlags(),
cwd: this.getCwd(),
};
}
getComposeFiles() {
const cwd = this.getCwd();
return (0, core_1.getMultilineInput)(InputNames.ComposeFile).filter((composeFile) => {
if (!composeFile.length) {
return false;
}
if (!(0, fs_1.existsSync)(composeFile)) {
this.logger.warn(`${composeFile} not exists`);
if (!(0, fs_1.existsSync)((0, path_1.join)(cwd, composeFile))) {
this.logger.warn(`${composeFile} does not exist in ${cwd}`);
return false;
}
return true;
@ -26071,6 +26076,9 @@ class InputService {
}
return flags.trim().split(" ");
}
getCwd() {
return (0, core_1.getInput)(InputNames.Cwd);
}
}
exports.InputService = InputService;

View File

@ -44,6 +44,7 @@ describe("run", () => {
composeFlags: [],
upFlags: [],
downFlags: [],
cwd: "/current/working/dir",
}));
await main.run(main.RunAction.UP);
@ -52,7 +53,7 @@ describe("run", () => {
// Verify that all of the functions were called correctly
expect(debugMock).toHaveBeenNthCalledWith(
1,
'inputs: {"composeFiles":[],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[]}'
'inputs: {"composeFiles":[],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir"}'
);
expect(warnMock).toHaveBeenNthCalledWith(1, "no compose files found");
expect(upMock).not.toHaveBeenCalled();
@ -66,6 +67,7 @@ describe("run", () => {
composeFlags: [],
upFlags: [],
downFlags: [],
cwd: "/current/working/dir",
}));
upMock.mockResolvedValueOnce();
@ -76,7 +78,7 @@ describe("run", () => {
// Verify that all of the functions were called correctly
expect(debugMock).toHaveBeenNthCalledWith(
1,
'inputs: {"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[]}'
'inputs: {"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir"}'
);
expect(upMock).toHaveBeenCalledWith({
@ -85,6 +87,7 @@ describe("run", () => {
composeFlags: [],
upFlags: [],
downFlags: [],
cwd: "/current/working/dir",
});
expect(setFailedMock).not.toHaveBeenCalled();
@ -98,6 +101,7 @@ describe("run", () => {
composeFlags: [],
upFlags: [],
downFlags: [],
cwd: "/current/working/dir",
}));
upMock.mockRejectedValueOnce(new Error("unkown error"));
@ -116,6 +120,7 @@ describe("run", () => {
composeFlags: [],
upFlags: [],
downFlags: [],
cwd: "/current/working/dir",
}));
downMock.mockResolvedValueOnce();
@ -126,7 +131,7 @@ describe("run", () => {
// Verify that all of the functions were called correctly
expect(debugMock).toHaveBeenNthCalledWith(
1,
'inputs: {"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[]}'
'inputs: {"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir"}'
);
expect(downMock).toHaveBeenCalledWith({
@ -135,6 +140,7 @@ describe("run", () => {
composeFlags: [],
upFlags: [],
downFlags: [],
cwd: "/current/working/dir",
});
expect(setFailedMock).not.toHaveBeenCalled();

View File

@ -29,6 +29,7 @@ describe("DockerComposeService", () => {
composeFlags: [],
upFlags: [],
downFlags: [],
cwd: "/current/working/dir",
};
await service.up(inputs);
@ -38,6 +39,7 @@ describe("DockerComposeService", () => {
commandOptions: [],
config: ["docker-compose.yml"],
log: true,
cwd: "/current/working/dir",
});
});
@ -48,6 +50,7 @@ describe("DockerComposeService", () => {
composeFlags: [],
upFlags: ["--build"],
downFlags: [],
cwd: "/current/working/dir",
};
await service.up(inputs);
@ -57,6 +60,7 @@ describe("DockerComposeService", () => {
commandOptions: ["--build"],
config: ["docker-compose.yml"],
log: true,
cwd: "/current/working/dir",
});
});
});
@ -69,6 +73,7 @@ describe("DockerComposeService", () => {
composeFlags: [],
upFlags: [],
downFlags: ["--volumes", "--remove-orphans"],
cwd: "/current/working/dir",
};
await service.down(inputs);
@ -78,6 +83,7 @@ describe("DockerComposeService", () => {
commandOptions: ["--volumes", "--remove-orphans"],
config: [],
log: true,
cwd: "/current/working/dir",
});
});
});

View File

@ -30,6 +30,7 @@ export class DockerComposeService {
config: inputs.composeFiles,
log: true,
composeOptions: inputs.composeFlags,
cwd: inputs.cwd,
};
}
}

View File

@ -71,6 +71,7 @@ describe("InputService", () => {
expect(inputs.composeFiles).toEqual(["file1"]);
});
});
describe("services", () => {
it("should return given services input", () => {
getMultilineInputMock.mockImplementation((inputName) => {
@ -89,6 +90,7 @@ describe("InputService", () => {
expect(inputs.services).toEqual(["service1", "service2"]);
});
});
describe("compose-flags", () => {
it("should return given compose-flags input", () => {
getMultilineInputMock.mockReturnValue([]);
@ -116,6 +118,7 @@ describe("InputService", () => {
expect(inputs.composeFlags).toEqual([]);
});
});
describe("up-flags", () => {
it("should return given up-flags input", () => {
getMultilineInputMock.mockReturnValue([]);
@ -143,6 +146,7 @@ describe("InputService", () => {
expect(inputs.upFlags).toEqual([]);
});
});
describe("down-flags", () => {
it("should return given down-flags input", () => {
getMultilineInputMock.mockReturnValue([]);
@ -170,5 +174,23 @@ describe("InputService", () => {
expect(inputs.downFlags).toEqual([]);
});
});
describe("cwd", () => {
it("should return given cwd input", () => {
getMultilineInputMock.mockReturnValue([]);
getInputMock.mockImplementation((inputName) => {
switch (inputName) {
case InputNames.Cwd:
return "cwd";
default:
return "";
}
});
const inputs = service.getInputs();
expect(inputs.cwd).toEqual("cwd");
});
});
});
});

View File

@ -1,6 +1,7 @@
import { getInput, getMultilineInput } from "@actions/core";
import { LoggerService } from "./logger.service";
import { existsSync } from "fs";
import { join } from "path";
export type Inputs = {
composeFiles: string[];
@ -8,6 +9,7 @@ export type Inputs = {
composeFlags: string[];
upFlags: string[];
downFlags: string[];
cwd: string;
};
export enum InputNames {
@ -16,6 +18,7 @@ export enum InputNames {
ComposeFlags = "compose-flags",
UpFlags = "up-flags",
DownFlags = "down-flags",
Cwd = "cwd",
}
export class InputService {
@ -28,17 +31,19 @@ export class InputService {
composeFlags: this.getComposeFlags(),
upFlags: this.getUpFlags(),
downFlags: this.getDownFlags(),
cwd: this.getCwd(),
};
}
private getComposeFiles(): string[] {
const cwd = this.getCwd();
return getMultilineInput(InputNames.ComposeFile).filter((composeFile) => {
if (!composeFile.length) {
return false;
}
if (!existsSync(composeFile)) {
this.logger.warn(`${composeFile} not exists`);
if (!existsSync(join(cwd, composeFile))) {
this.logger.warn(`${composeFile} does not exist in ${cwd}`);
return false;
}
@ -69,4 +74,8 @@ export class InputService {
return flags.trim().split(" ");
}
private getCwd(): string {
return getInput(InputNames.Cwd);
}
}