mirror of
https://github.com/hoverkraft-tech/compose-action.git
synced 2026-01-10 06:33:06 +08:00
feat: add logs debug on post
Signed-off-by: Emilien Escalle <emilien.escalle@escemi.com>
This commit is contained in:
parent
a48c80beab
commit
bc90ff6758
20
README.md
20
README.md
@ -11,9 +11,6 @@
|
||||
|
||||
<!-- end title -->
|
||||
<!-- start badges -->
|
||||
|
||||
<a href="https%3A%2F%2Fgithub.com%2Fhoverkraft-tech%2Fcompose-action%2Freleases%2Flatest"><img src="https://img.shields.io/github/v/release/hoverkraft-tech/compose-action?display_name=tag&sort=semver&logo=github&style=flat-square" alt="Release%20by%20tag" /></a><a href="https%3A%2F%2Fgithub.com%2Fhoverkraft-tech%2Fcompose-action%2Freleases%2Flatest"><img src="https://img.shields.io/github/release-date/hoverkraft-tech/compose-action?display_name=tag&sort=semver&logo=github&style=flat-square" alt="Release%20by%20date" /></a><img src="https://img.shields.io/github/last-commit/hoverkraft-tech/compose-action?logo=github&style=flat-square" alt="Commit" /><a href="https%3A%2F%2Fgithub.com%2Fhoverkraft-tech%2Fcompose-action%2Fissues"><img src="https://img.shields.io/github/issues/hoverkraft-tech/compose-action?logo=github&style=flat-square" alt="Open%20Issues" /></a><img src="https://img.shields.io/github/downloads/hoverkraft-tech/compose-action/total?logo=github&style=flat-square" alt="Downloads" />
|
||||
|
||||
<!-- end badges -->
|
||||
|
||||
</div>
|
||||
@ -22,8 +19,25 @@
|
||||
This action runs your docker-compose file and clean up before action finished
|
||||
|
||||
<!-- end description -->
|
||||
|
||||
<!-- start contents -->
|
||||
<!-- end contents -->
|
||||
|
||||
## Usage
|
||||
|
||||
### Action
|
||||
|
||||
The action will run `docker-compose up` to start the services defined in the given compose file(s).
|
||||
The compose file(s) can be specified using the `compose-file` input.
|
||||
Some extra options can be passed to the `docker-compose up` command using the `up-flags` input.
|
||||
|
||||
### Post hook
|
||||
|
||||
On post hook, the action will run `docker-compose down` to clean up the services.
|
||||
In debug mode, the logs of the running services are printed before the cleanup.
|
||||
|
||||
Some extra options can be passed to the `docker-compose down` command using the `down-flags` input.
|
||||
|
||||
<!-- start usage -->
|
||||
|
||||
```yaml
|
||||
|
||||
54
dist/index.js
generated
vendored
54
dist/index.js
generated
vendored
@ -25919,50 +25919,36 @@ exports["default"] = _default;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 399:
|
||||
/***/ 3878:
|
||||
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
||||
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.run = exports.RunAction = void 0;
|
||||
exports.run = void 0;
|
||||
const core_1 = __nccwpck_require__(2186);
|
||||
const docker_compose_service_1 = __nccwpck_require__(2911);
|
||||
const input_service_1 = __nccwpck_require__(6492);
|
||||
const logger_service_1 = __nccwpck_require__(6716);
|
||||
var RunAction;
|
||||
(function (RunAction) {
|
||||
RunAction["UP"] = "up";
|
||||
RunAction["DOWN"] = "down";
|
||||
})(RunAction || (exports.RunAction = RunAction = {}));
|
||||
const docker_compose_service_1 = __nccwpck_require__(2911);
|
||||
/**
|
||||
* The main function for the action.
|
||||
* The run function for the action.
|
||||
* @returns {Promise<void>} Resolves when the action is complete.
|
||||
*/
|
||||
async function run(run) {
|
||||
async function run(callback) {
|
||||
try {
|
||||
const loggerService = new logger_service_1.LoggerService();
|
||||
const dockerComposeService = new docker_compose_service_1.DockerComposeService();
|
||||
const inputService = new input_service_1.InputService(loggerService);
|
||||
const dockerComposeService = new docker_compose_service_1.DockerComposeService();
|
||||
const inputs = inputService.getInputs();
|
||||
(0, core_1.debug)(`inputs: ${JSON.stringify(inputs)}`);
|
||||
loggerService.debug(`inputs: ${JSON.stringify(inputs)}`);
|
||||
if (!inputs.composeFiles.length) {
|
||||
loggerService.warn("no compose files found");
|
||||
return;
|
||||
}
|
||||
switch (run) {
|
||||
case RunAction.UP:
|
||||
await dockerComposeService.up(inputs);
|
||||
loggerService.info("compose started");
|
||||
break;
|
||||
case RunAction.DOWN:
|
||||
await dockerComposeService.down(inputs);
|
||||
loggerService.info("compose removed");
|
||||
break;
|
||||
}
|
||||
await callback(inputs, loggerService, dockerComposeService);
|
||||
}
|
||||
catch (error) {
|
||||
(0, core_1.setFailed)(`compose ${run} failed. ${error instanceof Error ? error : JSON.stringify(error)}`);
|
||||
(0, core_1.setFailed)(`${error instanceof Error ? error : JSON.stringify(error)}`);
|
||||
}
|
||||
}
|
||||
exports.run = run;
|
||||
@ -25997,6 +25983,17 @@ class DockerComposeService {
|
||||
};
|
||||
await docker_compose_1.v2.down(options);
|
||||
}
|
||||
async logs(inputs) {
|
||||
const options = {
|
||||
...this.getCommonOptions(inputs),
|
||||
follow: false,
|
||||
};
|
||||
const { err, out } = await docker_compose_1.v2.logs(inputs.services, options);
|
||||
return {
|
||||
error: err,
|
||||
output: out,
|
||||
};
|
||||
}
|
||||
getCommonOptions(inputs) {
|
||||
return {
|
||||
config: inputs.composeFiles,
|
||||
@ -26100,6 +26097,9 @@ class LoggerService {
|
||||
info(message) {
|
||||
(0, core_1.info)(message);
|
||||
}
|
||||
debug(message) {
|
||||
(0, core_1.debug)(message);
|
||||
}
|
||||
}
|
||||
exports.LoggerService = LoggerService;
|
||||
|
||||
@ -36438,9 +36438,13 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
/**
|
||||
* The entrypoint for the action.
|
||||
*/
|
||||
const main_1 = __nccwpck_require__(399);
|
||||
const runner_1 = __nccwpck_require__(3878);
|
||||
const callback = async (inputs, loggerService, dockerComposeService) => {
|
||||
await dockerComposeService.up(inputs);
|
||||
loggerService.info("compose started");
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
(0, main_1.run)(main_1.RunAction.UP);
|
||||
(0, runner_1.run)(callback);
|
||||
|
||||
})();
|
||||
|
||||
|
||||
59
dist/post.js
generated
vendored
59
dist/post.js
generated
vendored
@ -25919,50 +25919,36 @@ exports["default"] = _default;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 399:
|
||||
/***/ 3878:
|
||||
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
||||
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.run = exports.RunAction = void 0;
|
||||
exports.run = void 0;
|
||||
const core_1 = __nccwpck_require__(2186);
|
||||
const docker_compose_service_1 = __nccwpck_require__(2911);
|
||||
const input_service_1 = __nccwpck_require__(6492);
|
||||
const logger_service_1 = __nccwpck_require__(6716);
|
||||
var RunAction;
|
||||
(function (RunAction) {
|
||||
RunAction["UP"] = "up";
|
||||
RunAction["DOWN"] = "down";
|
||||
})(RunAction || (exports.RunAction = RunAction = {}));
|
||||
const docker_compose_service_1 = __nccwpck_require__(2911);
|
||||
/**
|
||||
* The main function for the action.
|
||||
* The run function for the action.
|
||||
* @returns {Promise<void>} Resolves when the action is complete.
|
||||
*/
|
||||
async function run(run) {
|
||||
async function run(callback) {
|
||||
try {
|
||||
const loggerService = new logger_service_1.LoggerService();
|
||||
const dockerComposeService = new docker_compose_service_1.DockerComposeService();
|
||||
const inputService = new input_service_1.InputService(loggerService);
|
||||
const dockerComposeService = new docker_compose_service_1.DockerComposeService();
|
||||
const inputs = inputService.getInputs();
|
||||
(0, core_1.debug)(`inputs: ${JSON.stringify(inputs)}`);
|
||||
loggerService.debug(`inputs: ${JSON.stringify(inputs)}`);
|
||||
if (!inputs.composeFiles.length) {
|
||||
loggerService.warn("no compose files found");
|
||||
return;
|
||||
}
|
||||
switch (run) {
|
||||
case RunAction.UP:
|
||||
await dockerComposeService.up(inputs);
|
||||
loggerService.info("compose started");
|
||||
break;
|
||||
case RunAction.DOWN:
|
||||
await dockerComposeService.down(inputs);
|
||||
loggerService.info("compose removed");
|
||||
break;
|
||||
}
|
||||
await callback(inputs, loggerService, dockerComposeService);
|
||||
}
|
||||
catch (error) {
|
||||
(0, core_1.setFailed)(`compose ${run} failed. ${error instanceof Error ? error : JSON.stringify(error)}`);
|
||||
(0, core_1.setFailed)(`${error instanceof Error ? error : JSON.stringify(error)}`);
|
||||
}
|
||||
}
|
||||
exports.run = run;
|
||||
@ -25997,6 +25983,17 @@ class DockerComposeService {
|
||||
};
|
||||
await docker_compose_1.v2.down(options);
|
||||
}
|
||||
async logs(inputs) {
|
||||
const options = {
|
||||
...this.getCommonOptions(inputs),
|
||||
follow: false,
|
||||
};
|
||||
const { err, out } = await docker_compose_1.v2.logs(inputs.services, options);
|
||||
return {
|
||||
error: err,
|
||||
output: out,
|
||||
};
|
||||
}
|
||||
getCommonOptions(inputs) {
|
||||
return {
|
||||
config: inputs.composeFiles,
|
||||
@ -26100,6 +26097,9 @@ class LoggerService {
|
||||
info(message) {
|
||||
(0, core_1.info)(message);
|
||||
}
|
||||
debug(message) {
|
||||
(0, core_1.debug)(message);
|
||||
}
|
||||
}
|
||||
exports.LoggerService = LoggerService;
|
||||
|
||||
@ -36438,9 +36438,18 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
/**
|
||||
* The entrypoint for the post action.
|
||||
*/
|
||||
const main_1 = __nccwpck_require__(399);
|
||||
const runner_1 = __nccwpck_require__(3878);
|
||||
const callback = async (inputs, loggerService, dockerComposeService) => {
|
||||
const { error, output } = await dockerComposeService.logs(inputs);
|
||||
if (error) {
|
||||
loggerService.debug("compose error:\n" + error);
|
||||
}
|
||||
loggerService.debug("compose logs:\n" + output);
|
||||
await dockerComposeService.down(inputs);
|
||||
loggerService.info("compose removed");
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
(0, main_1.run)(main_1.RunAction.DOWN);
|
||||
(0, runner_1.run)(callback);
|
||||
|
||||
})();
|
||||
|
||||
|
||||
@ -1,17 +1,56 @@
|
||||
/**
|
||||
* Unit tests for the action's entrypoint, src/index.ts
|
||||
*/
|
||||
import * as core from "@actions/core";
|
||||
import { DockerComposeService } from "./services/docker-compose.service";
|
||||
import { InputService } from "./services/input.service";
|
||||
import { LoggerService } from "./services/logger.service";
|
||||
|
||||
import * as main from "./main";
|
||||
|
||||
// Mock the action's entrypoint
|
||||
const runMock = jest.spyOn(main, "run").mockImplementation();
|
||||
let setFailedMock: jest.SpiedFunction<typeof core.setFailed>;
|
||||
let getInputsMock: jest.SpiedFunction<typeof InputService.prototype.getInputs>;
|
||||
let debugMock: jest.SpiedFunction<typeof LoggerService.prototype.debug>;
|
||||
let infoMock: jest.SpiedFunction<typeof LoggerService.prototype.info>;
|
||||
let upMock: jest.SpiedFunction<typeof DockerComposeService.prototype.up>;
|
||||
|
||||
describe("index", () => {
|
||||
it("calls run when imported", async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
require("../src/index");
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
expect(runMock).toHaveBeenCalled();
|
||||
setFailedMock = jest.spyOn(core, "setFailed").mockImplementation();
|
||||
infoMock = jest.spyOn(LoggerService.prototype, "info").mockImplementation();
|
||||
debugMock = jest.spyOn(LoggerService.prototype, "debug").mockImplementation();
|
||||
getInputsMock = jest.spyOn(InputService.prototype, "getInputs");
|
||||
upMock = jest.spyOn(DockerComposeService.prototype, "up");
|
||||
});
|
||||
|
||||
it("calls run when imported", async () => {
|
||||
getInputsMock.mockImplementation(() => ({
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
services: [],
|
||||
composeFlags: [],
|
||||
upFlags: [],
|
||||
downFlags: [],
|
||||
cwd: "/current/working/dir",
|
||||
}));
|
||||
|
||||
upMock.mockResolvedValueOnce();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
await require("../src/index");
|
||||
|
||||
// Verify that all of the functions were called correctly
|
||||
expect(debugMock).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'inputs: {"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir"}'
|
||||
);
|
||||
|
||||
expect(upMock).toHaveBeenCalledWith({
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
services: [],
|
||||
composeFlags: [],
|
||||
upFlags: [],
|
||||
downFlags: [],
|
||||
cwd: "/current/working/dir",
|
||||
});
|
||||
|
||||
expect(setFailedMock).not.toHaveBeenCalled();
|
||||
expect(infoMock).toHaveBeenCalledWith("compose started");
|
||||
});
|
||||
});
|
||||
|
||||
16
src/index.ts
16
src/index.ts
@ -1,7 +1,19 @@
|
||||
/**
|
||||
* The entrypoint for the action.
|
||||
*/
|
||||
import { run, RunAction } from "./main";
|
||||
import { RunCallback, run } from "./runner";
|
||||
import { DockerComposeService } from "./services/docker-compose.service";
|
||||
import { Inputs } from "./services/input.service";
|
||||
import { LoggerService } from "./services/logger.service";
|
||||
|
||||
const callback: RunCallback = async (
|
||||
inputs: Inputs,
|
||||
loggerService: LoggerService,
|
||||
dockerComposeService: DockerComposeService
|
||||
) => {
|
||||
await dockerComposeService.up(inputs);
|
||||
loggerService.info("compose started");
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
run(RunAction.UP);
|
||||
run(callback);
|
||||
|
||||
42
src/main.ts
42
src/main.ts
@ -1,42 +0,0 @@
|
||||
import { debug, setFailed } from "@actions/core";
|
||||
import { DockerComposeService } from "./services/docker-compose.service";
|
||||
import { InputService } from "./services/input.service";
|
||||
import { LoggerService } from "./services/logger.service";
|
||||
|
||||
export enum RunAction {
|
||||
UP = "up",
|
||||
DOWN = "down",
|
||||
}
|
||||
|
||||
/**
|
||||
* The main function for the action.
|
||||
* @returns {Promise<void>} Resolves when the action is complete.
|
||||
*/
|
||||
export async function run(run: RunAction): Promise<void> {
|
||||
try {
|
||||
const loggerService = new LoggerService();
|
||||
const dockerComposeService = new DockerComposeService();
|
||||
const inputService = new InputService(loggerService);
|
||||
|
||||
const inputs = inputService.getInputs();
|
||||
debug(`inputs: ${JSON.stringify(inputs)}`);
|
||||
|
||||
if (!inputs.composeFiles.length) {
|
||||
loggerService.warn("no compose files found");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (run) {
|
||||
case RunAction.UP:
|
||||
await dockerComposeService.up(inputs);
|
||||
loggerService.info("compose started");
|
||||
break;
|
||||
case RunAction.DOWN:
|
||||
await dockerComposeService.down(inputs);
|
||||
loggerService.info("compose removed");
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
setFailed(`compose ${run} failed. ${error instanceof Error ? error : JSON.stringify(error)}`);
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,71 @@
|
||||
/**
|
||||
* Unit tests for the action's entrypoint, src/index.ts
|
||||
*/
|
||||
import * as core from "@actions/core";
|
||||
import { DockerComposeService } from "./services/docker-compose.service";
|
||||
import { InputService } from "./services/input.service";
|
||||
import { LoggerService } from "./services/logger.service";
|
||||
|
||||
import * as main from "./main";
|
||||
|
||||
// Mock the action's entrypoint
|
||||
const runMock = jest.spyOn(main, "run").mockImplementation();
|
||||
let setFailedMock: jest.SpiedFunction<typeof core.setFailed>;
|
||||
let getInputsMock: jest.SpiedFunction<typeof InputService.prototype.getInputs>;
|
||||
let debugMock: jest.SpiedFunction<typeof LoggerService.prototype.debug>;
|
||||
let infoMock: jest.SpiedFunction<typeof LoggerService.prototype.info>;
|
||||
let downMock: jest.SpiedFunction<typeof DockerComposeService.prototype.down>;
|
||||
let logsMock: jest.SpiedFunction<typeof DockerComposeService.prototype.logs>;
|
||||
|
||||
describe("post", () => {
|
||||
it("calls run when imported", async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
require("../src/post");
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
expect(runMock).toHaveBeenCalled();
|
||||
setFailedMock = jest.spyOn(core, "setFailed").mockImplementation();
|
||||
infoMock = jest.spyOn(LoggerService.prototype, "info").mockImplementation();
|
||||
debugMock = jest.spyOn(LoggerService.prototype, "debug").mockImplementation();
|
||||
getInputsMock = jest.spyOn(InputService.prototype, "getInputs");
|
||||
downMock = jest.spyOn(DockerComposeService.prototype, "down");
|
||||
logsMock = jest.spyOn(DockerComposeService.prototype, "logs");
|
||||
});
|
||||
|
||||
it("calls run when imported", async () => {
|
||||
getInputsMock.mockImplementation(() => ({
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
services: [],
|
||||
composeFlags: [],
|
||||
upFlags: [],
|
||||
downFlags: [],
|
||||
cwd: "/current/working/dir",
|
||||
}));
|
||||
|
||||
logsMock.mockResolvedValueOnce({ error: "", output: "log" });
|
||||
downMock.mockResolvedValueOnce();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
await require("../src/post");
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
// Verify that all of the functions were called correctly
|
||||
expect(debugMock).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'inputs: {"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir"}'
|
||||
);
|
||||
|
||||
expect(logsMock).toHaveBeenCalledWith({
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
services: [],
|
||||
composeFlags: [],
|
||||
upFlags: [],
|
||||
downFlags: [],
|
||||
cwd: "/current/working/dir",
|
||||
});
|
||||
|
||||
expect(debugMock).toHaveBeenNthCalledWith(2, "compose logs:\nlog");
|
||||
|
||||
expect(downMock).toHaveBeenCalledWith({
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
services: [],
|
||||
composeFlags: [],
|
||||
upFlags: [],
|
||||
downFlags: [],
|
||||
cwd: "/current/working/dir",
|
||||
});
|
||||
|
||||
expect(setFailedMock).not.toHaveBeenCalled();
|
||||
expect(infoMock).toHaveBeenCalledWith("compose removed");
|
||||
});
|
||||
});
|
||||
|
||||
25
src/post.ts
25
src/post.ts
@ -1,7 +1,28 @@
|
||||
/**
|
||||
* The entrypoint for the post action.
|
||||
*/
|
||||
import { run, RunAction } from "./main";
|
||||
import { RunCallback, run } from "./runner";
|
||||
import { DockerComposeService } from "./services/docker-compose.service";
|
||||
import { Inputs } from "./services/input.service";
|
||||
import { LoggerService } from "./services/logger.service";
|
||||
|
||||
const callback: RunCallback = async (
|
||||
inputs: Inputs,
|
||||
loggerService: LoggerService,
|
||||
dockerComposeService: DockerComposeService
|
||||
) => {
|
||||
const { error, output } = await dockerComposeService.logs(inputs);
|
||||
|
||||
if (error) {
|
||||
loggerService.debug("compose error:\n" + error);
|
||||
}
|
||||
|
||||
loggerService.debug("compose logs:\n" + output);
|
||||
|
||||
await dockerComposeService.down(inputs);
|
||||
|
||||
loggerService.info("compose removed");
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
run(RunAction.DOWN);
|
||||
run(callback);
|
||||
|
||||
@ -10,31 +10,24 @@ import * as core from "@actions/core";
|
||||
import { DockerComposeService } from "./services/docker-compose.service";
|
||||
import { InputService } from "./services/input.service";
|
||||
import { LoggerService } from "./services/logger.service";
|
||||
import * as main from "./main";
|
||||
import * as runner from "./runner";
|
||||
|
||||
// Mock the action's main function
|
||||
const runMock = jest.spyOn(main, "run");
|
||||
const runMock = jest.spyOn(runner, "run");
|
||||
|
||||
// Mock the external libraries and services used by the action
|
||||
let debugMock: jest.SpiedFunction<typeof core.debug>;
|
||||
let debugMock: jest.SpiedFunction<typeof LoggerService.prototype.debug>;
|
||||
let warnMock: jest.SpiedFunction<typeof LoggerService.prototype.warn>;
|
||||
let infoMock: jest.SpiedFunction<typeof LoggerService.prototype.info>;
|
||||
let setFailedMock: jest.SpiedFunction<typeof core.setFailed>;
|
||||
let getInputsMock: jest.SpiedFunction<typeof InputService.prototype.getInputs>;
|
||||
let upMock: jest.SpiedFunction<typeof DockerComposeService.prototype.up>;
|
||||
let downMock: jest.SpiedFunction<typeof DockerComposeService.prototype.down>;
|
||||
|
||||
describe("run", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
debugMock = jest.spyOn(core, "debug").mockImplementation();
|
||||
debugMock = jest.spyOn(LoggerService.prototype, "debug").mockImplementation();
|
||||
warnMock = jest.spyOn(LoggerService.prototype, "warn").mockImplementation();
|
||||
infoMock = jest.spyOn(LoggerService.prototype, "info").mockImplementation();
|
||||
setFailedMock = jest.spyOn(core, "setFailed").mockImplementation();
|
||||
getInputsMock = jest.spyOn(InputService.prototype, "getInputs");
|
||||
upMock = jest.spyOn(DockerComposeService.prototype, "up");
|
||||
downMock = jest.spyOn(DockerComposeService.prototype, "down");
|
||||
});
|
||||
|
||||
it("should return and warns when composeFile is empty", async () => {
|
||||
@ -47,7 +40,9 @@ describe("run", () => {
|
||||
cwd: "/current/working/dir",
|
||||
}));
|
||||
|
||||
await main.run(main.RunAction.UP);
|
||||
const callbackMock = jest.fn();
|
||||
|
||||
await runner.run(callbackMock);
|
||||
expect(runMock).toHaveReturned();
|
||||
|
||||
// Verify that all of the functions were called correctly
|
||||
@ -56,44 +51,10 @@ describe("run", () => {
|
||||
'inputs: {"composeFiles":[],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir"}'
|
||||
);
|
||||
expect(warnMock).toHaveBeenNthCalledWith(1, "no compose files found");
|
||||
expect(upMock).not.toHaveBeenCalled();
|
||||
expect(callbackMock).not.toHaveBeenCalled();
|
||||
expect(setFailedMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call up when some compose files are provided", async () => {
|
||||
getInputsMock.mockImplementation(() => ({
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
services: [],
|
||||
composeFlags: [],
|
||||
upFlags: [],
|
||||
downFlags: [],
|
||||
cwd: "/current/working/dir",
|
||||
}));
|
||||
|
||||
upMock.mockResolvedValueOnce();
|
||||
|
||||
await main.run(main.RunAction.UP);
|
||||
expect(runMock).toHaveReturned();
|
||||
|
||||
// Verify that all of the functions were called correctly
|
||||
expect(debugMock).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'inputs: {"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir"}'
|
||||
);
|
||||
|
||||
expect(upMock).toHaveBeenCalledWith({
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
services: [],
|
||||
composeFlags: [],
|
||||
upFlags: [],
|
||||
downFlags: [],
|
||||
cwd: "/current/working/dir",
|
||||
});
|
||||
|
||||
expect(setFailedMock).not.toHaveBeenCalled();
|
||||
expect(infoMock).toHaveBeenCalledWith("compose started");
|
||||
});
|
||||
|
||||
it("sets a failed status", async () => {
|
||||
getInputsMock.mockImplementation(() => ({
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
@ -104,16 +65,18 @@ describe("run", () => {
|
||||
cwd: "/current/working/dir",
|
||||
}));
|
||||
|
||||
upMock.mockRejectedValueOnce(new Error("unkown error"));
|
||||
const callbackMock = jest.fn();
|
||||
callbackMock.mockRejectedValueOnce(new Error("unkown error"));
|
||||
|
||||
await main.run(main.RunAction.UP);
|
||||
await runner.run(callbackMock);
|
||||
expect(runMock).toHaveReturned();
|
||||
|
||||
// Verify that all of the functions were called correctly
|
||||
expect(setFailedMock).toHaveBeenNthCalledWith(1, "compose up failed. Error: unkown error");
|
||||
expect(callbackMock).toHaveBeenCalled();
|
||||
expect(setFailedMock).toHaveBeenNthCalledWith(1, "Error: unkown error");
|
||||
});
|
||||
|
||||
it("should call down when some compose files are provided", async () => {
|
||||
it("should call callback when some compose files are provided", async () => {
|
||||
getInputsMock.mockImplementation(() => ({
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
services: [],
|
||||
@ -123,9 +86,10 @@ describe("run", () => {
|
||||
cwd: "/current/working/dir",
|
||||
}));
|
||||
|
||||
downMock.mockResolvedValueOnce();
|
||||
const callbackMock = jest.fn();
|
||||
callbackMock.mockResolvedValueOnce(null);
|
||||
|
||||
await main.run(main.RunAction.DOWN);
|
||||
await runner.run(callbackMock);
|
||||
expect(runMock).toHaveReturned();
|
||||
|
||||
// Verify that all of the functions were called correctly
|
||||
@ -134,16 +98,19 @@ describe("run", () => {
|
||||
'inputs: {"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir"}'
|
||||
);
|
||||
|
||||
expect(downMock).toHaveBeenCalledWith({
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
services: [],
|
||||
composeFlags: [],
|
||||
upFlags: [],
|
||||
downFlags: [],
|
||||
cwd: "/current/working/dir",
|
||||
});
|
||||
expect(callbackMock).toHaveBeenCalledWith(
|
||||
{
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
services: [],
|
||||
composeFlags: [],
|
||||
upFlags: [],
|
||||
downFlags: [],
|
||||
cwd: "/current/working/dir",
|
||||
},
|
||||
expect.any(LoggerService),
|
||||
expect.any(DockerComposeService)
|
||||
);
|
||||
|
||||
expect(setFailedMock).not.toHaveBeenCalled();
|
||||
expect(infoMock).toHaveBeenCalledWith("compose removed");
|
||||
});
|
||||
});
|
||||
34
src/runner.ts
Normal file
34
src/runner.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { setFailed } from "@actions/core";
|
||||
import { InputService, Inputs } from "./services/input.service";
|
||||
import { LoggerService } from "./services/logger.service";
|
||||
import { DockerComposeService } from "./services/docker-compose.service";
|
||||
|
||||
export type RunCallback = (
|
||||
inputs: Inputs,
|
||||
loggerService: LoggerService,
|
||||
dockerComposeService: DockerComposeService
|
||||
) => Promise<void>;
|
||||
|
||||
/**
|
||||
* The run function for the action.
|
||||
* @returns {Promise<void>} Resolves when the action is complete.
|
||||
*/
|
||||
export async function run(callback: RunCallback): Promise<void> {
|
||||
try {
|
||||
const loggerService = new LoggerService();
|
||||
const inputService = new InputService(loggerService);
|
||||
const dockerComposeService = new DockerComposeService();
|
||||
|
||||
const inputs = inputService.getInputs();
|
||||
loggerService.debug(`inputs: ${JSON.stringify(inputs)}`);
|
||||
|
||||
if (!inputs.composeFiles.length) {
|
||||
loggerService.warn("no compose files found");
|
||||
return;
|
||||
}
|
||||
|
||||
await callback(inputs, loggerService, dockerComposeService);
|
||||
} catch (error) {
|
||||
setFailed(`${error instanceof Error ? error : JSON.stringify(error)}`);
|
||||
}
|
||||
}
|
||||
@ -9,12 +9,14 @@ describe("DockerComposeService", () => {
|
||||
let upAllMock: jest.SpiedFunction<typeof v2.upAll>;
|
||||
let upManyMock: jest.SpiedFunction<typeof v2.upMany>;
|
||||
let downMock: jest.SpiedFunction<typeof v2.down>;
|
||||
let logsMock: jest.SpiedFunction<typeof v2.logs>;
|
||||
|
||||
beforeEach(() => {
|
||||
service = new DockerComposeService();
|
||||
upAllMock = jest.spyOn(v2, "upAll").mockImplementation();
|
||||
upManyMock = jest.spyOn(v2, "upMany").mockImplementation();
|
||||
downMock = jest.spyOn(v2, "down").mockImplementation();
|
||||
logsMock = jest.spyOn(v2, "logs").mockImplementation();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -87,4 +89,29 @@ describe("DockerComposeService", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("logs", () => {
|
||||
it("should call logs with correct options", async () => {
|
||||
const inputs: Inputs = {
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
services: ["helloworld2", "helloworld3"],
|
||||
composeFlags: [],
|
||||
upFlags: [],
|
||||
downFlags: [],
|
||||
cwd: "/current/working/dir",
|
||||
};
|
||||
|
||||
logsMock.mockResolvedValue({ exitCode: 0, err: "", out: "logs" });
|
||||
|
||||
await service.logs(inputs);
|
||||
|
||||
expect(v2.logs).toHaveBeenCalledWith(["helloworld2", "helloworld3"], {
|
||||
composeOptions: [],
|
||||
config: ["docker-compose.yml"],
|
||||
log: true,
|
||||
cwd: "/current/working/dir",
|
||||
follow: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { IDockerComposeOptions, v2 } from "docker-compose";
|
||||
import { IDockerComposeLogOptions, IDockerComposeOptions, v2 } from "docker-compose";
|
||||
import { Inputs } from "./input.service";
|
||||
|
||||
export class DockerComposeService {
|
||||
async up(inputs: Inputs): Promise<void> {
|
||||
const options = {
|
||||
const options: IDockerComposeOptions = {
|
||||
...this.getCommonOptions(inputs),
|
||||
commandOptions: inputs.upFlags,
|
||||
};
|
||||
@ -17,7 +17,7 @@ export class DockerComposeService {
|
||||
}
|
||||
|
||||
async down(inputs: Inputs): Promise<void> {
|
||||
const options = {
|
||||
const options: IDockerComposeOptions = {
|
||||
...this.getCommonOptions(inputs),
|
||||
commandOptions: inputs.downFlags,
|
||||
};
|
||||
@ -25,6 +25,20 @@ export class DockerComposeService {
|
||||
await v2.down(options);
|
||||
}
|
||||
|
||||
async logs(inputs: Inputs): Promise<{ error: string; output: string }> {
|
||||
const options: IDockerComposeLogOptions = {
|
||||
...this.getCommonOptions(inputs),
|
||||
follow: false,
|
||||
};
|
||||
|
||||
const { err, out } = await v2.logs(inputs.services, options);
|
||||
|
||||
return {
|
||||
error: err,
|
||||
output: out,
|
||||
};
|
||||
}
|
||||
|
||||
private getCommonOptions(inputs: Inputs): IDockerComposeOptions {
|
||||
return {
|
||||
config: inputs.composeFiles,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { info, warning } from "@actions/core";
|
||||
import { debug, info, warning } from "@actions/core";
|
||||
|
||||
export class LoggerService {
|
||||
warn(message: string): void {
|
||||
@ -8,4 +8,8 @@ export class LoggerService {
|
||||
info(message: string): void {
|
||||
info(message);
|
||||
}
|
||||
|
||||
debug(message: string) {
|
||||
debug(message);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user