diff --git a/README.md b/README.md index b1c0917..a57b9ca 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,10 @@ Some extra options can be passed to the `docker compose up` command using the `u ### Post hook On post hook, the action will run `docker compose down` to clean up the services. -In [debug mode](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/enabling-debug-logging), the logs of the running services are printed before the cleanup. + +Logs of the Docker Compose services are logged using GitHub `core.ts` API before the cleanup. +The log level can be set using the `services-log-level` input. The default is `debug`, which will +only print logs if [debug mode](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/enabling-debug-logging) is switched on. Some extra options can be passed to the `docker compose down` command using the `down-flags` input. @@ -92,6 +95,10 @@ Some extra options can be passed to the `docker compose down` command using the # # Default: ${{ github.token }} github-token: "" + + # Description: The log level used for Docker Compose service logs. Can be one of "debug", "info". + # Default: "debug" + services-log-level: "debug" ``` @@ -100,17 +107,18 @@ Some extra options can be passed to the `docker compose down` command using the -| **Input** | **Description** | **Default** | **Required** | -| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------ | ------------ | -| docker-flags | Additional options to pass to docker command. | | **false** | -| compose-file | Path to compose file(s). It can be a list of files. It can be absolute or relative to the current working directory (cwd). | ./docker-compose.yml | **false** | -| services | Services to perform docker compose up. | | **false** | -| up-flags | Additional options to pass to docker compose up command. | | **false** | -| down-flags | Additional options to pass to docker compose down command. | | **false** | -| compose-flags | Additional options to pass to docker compose command. | | **false** | -| cwd | Current working directory | ${{ github.workspace }} | **false** | -| compose-version | Compose version to use.
If null (default), it will use the current installed version.
If "latest", it will install the latest version. | | **false** | -| github-token | The GitHub token used to create an authenticated client (to fetch the latest version of docker compose). | ${{ github.token }} | **false** | +| **Input** | **Description** | **Default** | **Required** | +| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------ | ------------ | +| docker-flags | Additional options to pass to docker command. | | **false** | +| compose-file | Path to compose file(s). It can be a list of files. It can be absolute or relative to the current working directory (cwd). | ./docker-compose.yml | **false** | +| services | Services to perform docker compose up. | | **false** | +| up-flags | Additional options to pass to docker compose up command. | | **false** | +| down-flags | Additional options to pass to docker compose down command. | | **false** | +| compose-flags | Additional options to pass to docker compose command. | | **false** | +| cwd | Current working directory | ${{ github.workspace }} | **false** | +| compose-version | Compose version to use.
If null (default), it will use the current installed version.
If "latest", it will install the latest version. | | **false** | +| github-token | The GitHub token used to create an authenticated client (to fetch the latest version of docker compose). | ${{ github.token }} | **false** | +| services-log-level | The log level used for Docker Compose service logs. Can be one of "debug", "info". | debug | **false** | diff --git a/dist/index.js b/dist/index.js index e2e948a..f04fcd3 100644 --- a/dist/index.js +++ b/dist/index.js @@ -33052,7 +33052,7 @@ async function run() { cwd: inputs.cwd, upFlags: inputs.upFlags, services: inputs.services, - debug: loggerService.debug, + serviceLogger: loggerService.getServiceLogger(inputs.serviceLogLevel), }); loggerService.info("docker compose service(s) are up"); } @@ -33197,12 +33197,12 @@ class DockerComposeService { output: out, }; } - getCommonOptions({ dockerFlags, composeFiles, composeFlags, cwd, debug, }) { + getCommonOptions({ dockerFlags, composeFiles, composeFlags, cwd, serviceLogger, }) { return { config: composeFiles, composeOptions: composeFlags, cwd: cwd, - callback: (chunk) => debug(chunk.toString()), + callback: (chunk) => serviceLogger(chunk.toString()), executable: { executablePath: "docker", options: dockerFlags, @@ -33225,6 +33225,7 @@ exports.InputService = exports.COMPOSE_VERSION_LATEST = exports.InputNames = voi const core_1 = __nccwpck_require__(7484); const fs_1 = __nccwpck_require__(9896); const path_1 = __nccwpck_require__(6928); +const logger_service_1 = __nccwpck_require__(8187); var InputNames; (function (InputNames) { InputNames["DockerFlags"] = "docker-flags"; @@ -33236,6 +33237,7 @@ var InputNames; InputNames["Cwd"] = "cwd"; InputNames["ComposeVersion"] = "compose-version"; InputNames["GithubToken"] = "github-token"; + InputNames["ServiceLogLevel"] = "services-log-level"; })(InputNames || (exports.InputNames = InputNames = {})); exports.COMPOSE_VERSION_LATEST = "latest"; class InputService { @@ -33250,6 +33252,7 @@ class InputService { cwd: this.getCwd(), composeVersion: this.getComposeVersion(), githubToken: this.getGithubToken(), + serviceLogLevel: this.getServiceLogLevel(), }; } getDockerFlags() { @@ -33305,6 +33308,13 @@ class InputService { required: false, }) || null); } + getServiceLogLevel() { + const configuredLevel = (0, core_1.getInput)(InputNames.ServiceLogLevel, { required: false }); + if (configuredLevel && !Object.values(logger_service_1.LogLevel).includes(configuredLevel)) { + throw new Error(`Invalid service log level "${configuredLevel}". Valid values are: ${Object.values(logger_service_1.LogLevel).join(", ")}`); + } + return configuredLevel || logger_service_1.LogLevel.Debug; + } } exports.InputService = InputService; @@ -33377,7 +33387,7 @@ exports.ManualInstallerAdapter = ManualInstallerAdapter; "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.LoggerService = void 0; +exports.LogLevel = exports.LoggerService = void 0; const core_1 = __nccwpck_require__(7484); class LoggerService { warn(message) { @@ -33389,8 +33399,23 @@ class LoggerService { debug(message) { (0, core_1.debug)(message); } + getServiceLogger(level) { + switch (level) { + case LogLevel.Debug: + return this.debug; + case LogLevel.Info: + return this.info; + default: + return this.info; + } + } } exports.LoggerService = LoggerService; +var LogLevel; +(function (LogLevel) { + LogLevel["Debug"] = "debug"; + LogLevel["Info"] = "info"; +})(LogLevel || (exports.LogLevel = LogLevel = {})); /***/ }), diff --git a/dist/post.js b/dist/post.js index e1d25a9..be39b21 100644 --- a/dist/post.js +++ b/dist/post.js @@ -26212,7 +26212,7 @@ async function run() { composeFlags: inputs.composeFlags, cwd: inputs.cwd, services: inputs.services, - debug: loggerService.debug, + serviceLogger: loggerService.getServiceLogger(inputs.serviceLogLevel), }); if (error) { loggerService.debug("docker compose error:\n" + error); @@ -26224,7 +26224,7 @@ async function run() { composeFlags: inputs.composeFlags, cwd: inputs.cwd, downFlags: inputs.downFlags, - debug: loggerService.debug, + serviceLogger: loggerService.getServiceLogger(inputs.serviceLogLevel), }); loggerService.info("docker compose is down"); } @@ -26274,12 +26274,12 @@ class DockerComposeService { output: out, }; } - getCommonOptions({ dockerFlags, composeFiles, composeFlags, cwd, debug, }) { + getCommonOptions({ dockerFlags, composeFiles, composeFlags, cwd, serviceLogger, }) { return { config: composeFiles, composeOptions: composeFlags, cwd: cwd, - callback: (chunk) => debug(chunk.toString()), + callback: (chunk) => serviceLogger(chunk.toString()), executable: { executablePath: "docker", options: dockerFlags, @@ -26302,6 +26302,7 @@ exports.InputService = exports.COMPOSE_VERSION_LATEST = exports.InputNames = voi const core_1 = __nccwpck_require__(7484); const fs_1 = __nccwpck_require__(9896); const path_1 = __nccwpck_require__(6928); +const logger_service_1 = __nccwpck_require__(8187); var InputNames; (function (InputNames) { InputNames["DockerFlags"] = "docker-flags"; @@ -26313,6 +26314,7 @@ var InputNames; InputNames["Cwd"] = "cwd"; InputNames["ComposeVersion"] = "compose-version"; InputNames["GithubToken"] = "github-token"; + InputNames["ServiceLogLevel"] = "services-log-level"; })(InputNames || (exports.InputNames = InputNames = {})); exports.COMPOSE_VERSION_LATEST = "latest"; class InputService { @@ -26327,6 +26329,7 @@ class InputService { cwd: this.getCwd(), composeVersion: this.getComposeVersion(), githubToken: this.getGithubToken(), + serviceLogLevel: this.getServiceLogLevel(), }; } getDockerFlags() { @@ -26382,6 +26385,13 @@ class InputService { required: false, }) || null); } + getServiceLogLevel() { + const configuredLevel = (0, core_1.getInput)(InputNames.ServiceLogLevel, { required: false }); + if (configuredLevel && !Object.values(logger_service_1.LogLevel).includes(configuredLevel)) { + throw new Error(`Invalid service log level "${configuredLevel}". Valid values are: ${Object.values(logger_service_1.LogLevel).join(", ")}`); + } + return configuredLevel || logger_service_1.LogLevel.Debug; + } } exports.InputService = InputService; @@ -26394,7 +26404,7 @@ exports.InputService = InputService; "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.LoggerService = void 0; +exports.LogLevel = exports.LoggerService = void 0; const core_1 = __nccwpck_require__(7484); class LoggerService { warn(message) { @@ -26406,8 +26416,23 @@ class LoggerService { debug(message) { (0, core_1.debug)(message); } + getServiceLogger(level) { + switch (level) { + case LogLevel.Debug: + return this.debug; + case LogLevel.Info: + return this.info; + default: + return this.info; + } + } } exports.LoggerService = LoggerService; +var LogLevel; +(function (LogLevel) { + LogLevel["Debug"] = "debug"; + LogLevel["Info"] = "info"; +})(LogLevel || (exports.LogLevel = LogLevel = {})); /***/ }), diff --git a/package.json b/package.json index e6a0002..2daf9d9 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "lint": "eslint \"src/**/*.{ts,tsx}\"", "all": "npm run format && npm run lint && npm run test && npm run package", "build": "tsc --noEmit", - "format": "prettier --cache --write '**/*.ts'", + "format": "prettier --cache --write .", "jest": "jest --detectOpenHandles --forceExit", "test": "npm run jest --maxWorkers=50%", "test:watch": "npm run jest --watch --maxWorkers=25%", diff --git a/src/index-runner.test.ts b/src/index-runner.test.ts index 7a33749..3dd80d7 100644 --- a/src/index-runner.test.ts +++ b/src/index-runner.test.ts @@ -1,6 +1,6 @@ import * as core from "@actions/core"; import { InputService } from "./services/input.service"; -import { LoggerService } from "./services/logger.service"; +import { LoggerService, LogLevel } from "./services/logger.service"; import { DockerComposeInstallerService } from "./services/docker-compose-installer.service"; import * as indexRunner from "./index-runner"; import { DockerComposeService } from "./services/docker-compose.service"; @@ -37,6 +37,7 @@ describe("run", () => { cwd: "/current/working/dir", composeVersion: "1.29.2", githubToken: null, + serviceLogLevel: LogLevel.Debug, })); installMock.mockResolvedValue("1.29.2"); @@ -50,7 +51,7 @@ describe("run", () => { expect(infoMock).toHaveBeenCalledWith("Setting up docker compose version 1.29.2"); expect(debugMock).toHaveBeenCalledWith( - 'inputs: {"dockerFlags":[],"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir","composeVersion":"1.29.2","githubToken":null}' + 'inputs: {"dockerFlags":[],"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir","composeVersion":"1.29.2","githubToken":null,"serviceLogLevel":"debug"}' ); expect(installMock).toHaveBeenCalledWith({ @@ -66,7 +67,7 @@ describe("run", () => { cwd: "/current/working/dir", upFlags: [], services: [], - debug: debugMock, + serviceLogger: debugMock, }); expect(setFailedMock).not.toHaveBeenCalled(); @@ -84,6 +85,7 @@ describe("run", () => { cwd: "/current/working/dir", composeVersion: null, githubToken: null, + serviceLogLevel: LogLevel.Debug, })); // Act @@ -97,7 +99,7 @@ describe("run", () => { cwd: "/current/working/dir", upFlags: [], services: ["web"], - debug: debugMock, + serviceLogger: debugMock, }); expect(setFailedMock).not.toHaveBeenCalled(); }); @@ -117,6 +119,7 @@ describe("run", () => { cwd: "/current/working/dir", composeVersion: null, githubToken: null, + serviceLogLevel: LogLevel.Debug, })); // Act @@ -141,6 +144,7 @@ describe("run", () => { cwd: "/current/working/dir", composeVersion: null, githubToken: null, + serviceLogLevel: LogLevel.Debug, })); // Act diff --git a/src/index-runner.ts b/src/index-runner.ts index 0cb2ed0..03632ff 100644 --- a/src/index-runner.ts +++ b/src/index-runner.ts @@ -42,7 +42,7 @@ export async function run(): Promise { cwd: inputs.cwd, upFlags: inputs.upFlags, services: inputs.services, - debug: loggerService.debug, + serviceLogger: loggerService.getServiceLogger(inputs.serviceLogLevel), }); loggerService.info("docker compose service(s) are up"); } catch (error) { diff --git a/src/index.test.ts b/src/index.test.ts index c2ff37c..2fd2ec4 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,7 +1,7 @@ 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 { LoggerService, LogLevel } from "./services/logger.service"; import { DockerComposeInstallerService } from "./services/docker-compose-installer.service"; let setFailedMock: jest.SpiedFunction; @@ -34,6 +34,7 @@ describe("index", () => { cwd: "/current/working/dir", composeVersion: null, githubToken: null, + serviceLogLevel: LogLevel.Debug, })); installMock.mockResolvedValue("1.2.3"); @@ -49,7 +50,7 @@ describe("index", () => { // Verify that all of the functions were called correctly expect(debugMock).toHaveBeenNthCalledWith( 1, - 'inputs: {"dockerFlags":[],"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir","composeVersion":null,"githubToken":null}' + 'inputs: {"dockerFlags":[],"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir","composeVersion":null,"githubToken":null,"serviceLogLevel":"debug"}' ); expect(infoMock).toHaveBeenNthCalledWith(3, "Bringing up docker compose service(s)"); @@ -61,7 +62,7 @@ describe("index", () => { composeFlags: [], upFlags: [], cwd: "/current/working/dir", - debug: debugMock, + serviceLogger: debugMock, }); expect(setFailedMock).not.toHaveBeenCalled(); diff --git a/src/post-runner.test.ts b/src/post-runner.test.ts index 3f8ce72..d20774e 100644 --- a/src/post-runner.test.ts +++ b/src/post-runner.test.ts @@ -1,6 +1,6 @@ import * as core from "@actions/core"; import { InputService } from "./services/input.service"; -import { LoggerService } from "./services/logger.service"; +import { LoggerService, LogLevel } from "./services/logger.service"; import * as postRunner from "./post-runner"; import { DockerComposeService } from "./services/docker-compose.service"; @@ -36,6 +36,7 @@ describe("run", () => { cwd: "/current/working/dir", composeVersion: null, githubToken: null, + serviceLogLevel: LogLevel.Debug, })); logsMock.mockResolvedValue({ error: "", output: "test logs" }); @@ -52,7 +53,7 @@ describe("run", () => { composeFlags: [], cwd: "/current/working/dir", services: [], - debug: debugMock, + serviceLogger: debugMock, }); expect(downMock).toHaveBeenCalledWith({ @@ -61,7 +62,7 @@ describe("run", () => { composeFlags: [], cwd: "/current/working/dir", downFlags: [], - debug: debugMock, + serviceLogger: debugMock, }); expect(debugMock).toHaveBeenCalledWith("docker compose logs:\ntest logs"); @@ -83,6 +84,7 @@ describe("run", () => { cwd: "/current/working/dir", composeVersion: null, githubToken: null, + serviceLogLevel: LogLevel.Debug, })); logsMock.mockResolvedValue({ @@ -102,7 +104,7 @@ describe("run", () => { cwd: "/current/working/dir", dockerFlags: [], services: [], - debug: debugMock, + serviceLogger: debugMock, }); expect(downMock).toHaveBeenCalledWith({ @@ -111,7 +113,7 @@ describe("run", () => { cwd: "/current/working/dir", dockerFlags: [], downFlags: [], - debug: debugMock, + serviceLogger: debugMock, }); expect(debugMock).toHaveBeenCalledWith("docker compose error:\ntest logs error"); @@ -148,6 +150,7 @@ describe("run", () => { cwd: "/current/working/dir", composeVersion: null, githubToken: null, + serviceLogLevel: LogLevel.Debug, })); // Act @@ -172,6 +175,7 @@ describe("run", () => { cwd: "/current/working/dir", composeVersion: null, githubToken: null, + serviceLogLevel: LogLevel.Debug, })); // Act diff --git a/src/post-runner.ts b/src/post-runner.ts index 2314010..f6f3023 100644 --- a/src/post-runner.ts +++ b/src/post-runner.ts @@ -21,7 +21,7 @@ export async function run(): Promise { composeFlags: inputs.composeFlags, cwd: inputs.cwd, services: inputs.services, - debug: loggerService.debug, + serviceLogger: loggerService.getServiceLogger(inputs.serviceLogLevel), }); if (error) { @@ -36,7 +36,7 @@ export async function run(): Promise { composeFlags: inputs.composeFlags, cwd: inputs.cwd, downFlags: inputs.downFlags, - debug: loggerService.debug, + serviceLogger: loggerService.getServiceLogger(inputs.serviceLogLevel), }); loggerService.info("docker compose is down"); diff --git a/src/post.test.ts b/src/post.test.ts index 495565e..8511007 100644 --- a/src/post.test.ts +++ b/src/post.test.ts @@ -1,7 +1,7 @@ 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 { LoggerService, LogLevel } from "./services/logger.service"; let setFailedMock: jest.SpiedFunction; let getInputsMock: jest.SpiedFunction; @@ -33,6 +33,7 @@ describe("post", () => { cwd: "/current/working/dir", composeVersion: null, githubToken: null, + serviceLogLevel: LogLevel.Debug, })); logsMock.mockResolvedValue({ error: "", output: "test logs" }); @@ -48,7 +49,7 @@ describe("post", () => { composeFlags: [], cwd: "/current/working/dir", services: [], - debug: debugMock, + serviceLogger: debugMock, }); expect(downMock).toHaveBeenCalledWith({ @@ -57,7 +58,7 @@ describe("post", () => { composeFlags: [], cwd: "/current/working/dir", downFlags: [], - debug: debugMock, + serviceLogger: debugMock, }); expect(debugMock).toHaveBeenNthCalledWith(1, "docker compose logs:\ntest logs"); diff --git a/src/services/docker-compose.service.test.ts b/src/services/docker-compose.service.test.ts index 78aa83d..8ba985e 100644 --- a/src/services/docker-compose.service.test.ts +++ b/src/services/docker-compose.service.test.ts @@ -31,7 +31,7 @@ describe("DockerComposeService", () => { composeFlags: [], upFlags: [], cwd: "/current/working/dir", - debug: jest.fn(), + serviceLogger: jest.fn(), }; await service.up(upInputs); @@ -47,6 +47,15 @@ describe("DockerComposeService", () => { cwd: "/current/working/dir", callback: expect.any(Function), }); + + // Ensure callback is calling the service logger + const callback = upAllMock?.mock?.calls[0][0]?.callback; + expect(callback).toBeDefined(); + + const message = "test log output"; + callback ? callback(Buffer.from(message)) : null; + + expect(upInputs.serviceLogger).toHaveBeenCalledWith("test log output"); }); it("should call up with specific docker flags", async () => { @@ -57,7 +66,7 @@ describe("DockerComposeService", () => { composeFlags: [], upFlags: [], cwd: "/current/working/dir", - debug: jest.fn(), + serviceLogger: jest.fn(), }; await service.up(upInputs); @@ -83,7 +92,7 @@ describe("DockerComposeService", () => { composeFlags: [], upFlags: ["--build"], cwd: "/current/working/dir", - debug: jest.fn(), + serviceLogger: jest.fn(), }; await service.up(upInputs); @@ -110,7 +119,7 @@ describe("DockerComposeService", () => { composeFlags: [], downFlags: ["--volumes", "--remove-orphans"], cwd: "/current/working/dir", - debug: jest.fn(), + serviceLogger: jest.fn(), }; await service.down(downInputs); @@ -138,7 +147,7 @@ describe("DockerComposeService", () => { services: ["helloworld2", "helloworld3"], composeFlags: [], cwd: "/current/working/dir", - debug: debugMock, + serviceLogger: debugMock, }; logsMock.mockResolvedValue({ exitCode: 0, err: "", out: "logs" }); diff --git a/src/services/docker-compose.service.ts b/src/services/docker-compose.service.ts index bdc0a36..5f3bbde 100644 --- a/src/services/docker-compose.service.ts +++ b/src/services/docker-compose.service.ts @@ -13,7 +13,7 @@ type OptionsInputs = { composeFiles: Inputs["composeFiles"]; composeFlags: Inputs["composeFlags"]; cwd: Inputs["cwd"]; - debug: (message: string) => void; + serviceLogger: (message: string) => void; }; export type UpInputs = OptionsInputs & { upFlags: Inputs["upFlags"]; services: Inputs["services"] }; @@ -66,13 +66,13 @@ export class DockerComposeService { composeFiles, composeFlags, cwd, - debug, + serviceLogger, }: OptionsInputs): IDockerComposeOptions { return { config: composeFiles, composeOptions: composeFlags, cwd: cwd, - callback: (chunk) => debug(chunk.toString()), + callback: (chunk) => serviceLogger(chunk.toString()), executable: { executablePath: "docker", options: dockerFlags, diff --git a/src/services/input.service.test.ts b/src/services/input.service.test.ts index 863af98..648d91e 100644 --- a/src/services/input.service.test.ts +++ b/src/services/input.service.test.ts @@ -1,6 +1,7 @@ import * as core from "@actions/core"; import fs from "fs"; import { InputService, InputNames } from "./input.service"; +import { LogLevel } from "./logger.service"; describe("InputService", () => { let service: InputService; @@ -15,6 +16,15 @@ describe("InputService", () => { getInputMock = jest.spyOn(core, "getInput").mockImplementation(); getMultilineInputMock = jest.spyOn(core, "getMultilineInput").mockImplementation(); + getMultilineInputMock.mockImplementation((inputName) => { + switch (inputName) { + case InputNames.ComposeFile: + return ["file1"]; + default: + return []; + } + }); + service = new InputService(); }); @@ -25,15 +35,6 @@ describe("InputService", () => { describe("getInputs", () => { describe("docker-flags", () => { it("should return given docker-flags input", () => { - getMultilineInputMock.mockImplementation((inputName) => { - switch (inputName) { - case InputNames.ComposeFile: - return ["file1"]; - default: - return []; - } - }); - getInputMock.mockImplementation((inputName) => { switch (inputName) { case InputNames.DockerFlags: @@ -51,15 +52,6 @@ describe("InputService", () => { }); it("should return empty array when no docker-flags input", () => { - getMultilineInputMock.mockImplementation((inputName) => { - switch (inputName) { - case InputNames.ComposeFile: - return ["file1"]; - default: - return []; - } - }); - getInputMock.mockReturnValue(""); existsSyncMock.mockReturnValue(true); @@ -149,15 +141,6 @@ describe("InputService", () => { describe("compose-flags", () => { it("should return given compose-flags input", () => { - getMultilineInputMock.mockImplementation((inputName) => { - switch (inputName) { - case InputNames.ComposeFile: - return ["file1"]; - default: - return []; - } - }); - getInputMock.mockImplementation((inputName) => { switch (inputName) { case InputNames.ComposeFlags: @@ -175,15 +158,6 @@ describe("InputService", () => { }); it("should return empty array when no compose-flags input", () => { - getMultilineInputMock.mockImplementation((inputName) => { - switch (inputName) { - case InputNames.ComposeFile: - return ["file1"]; - default: - return []; - } - }); - getInputMock.mockReturnValue(""); existsSyncMock.mockReturnValue(true); @@ -196,15 +170,6 @@ describe("InputService", () => { describe("up-flags", () => { it("should return given up-flags input", () => { - getMultilineInputMock.mockImplementation((inputName) => { - switch (inputName) { - case InputNames.ComposeFile: - return ["file1"]; - default: - return []; - } - }); - getInputMock.mockImplementation((inputName) => { switch (inputName) { case InputNames.UpFlags: @@ -222,15 +187,6 @@ describe("InputService", () => { }); it("should return empty array when no up-flags input", () => { - getMultilineInputMock.mockImplementation((inputName) => { - switch (inputName) { - case InputNames.ComposeFile: - return ["file1"]; - default: - return []; - } - }); - getInputMock.mockReturnValue(""); existsSyncMock.mockReturnValue(true); @@ -243,15 +199,6 @@ describe("InputService", () => { describe("down-flags", () => { it("should return given down-flags input", () => { - getMultilineInputMock.mockImplementation((inputName) => { - switch (inputName) { - case InputNames.ComposeFile: - return ["file1"]; - default: - return []; - } - }); - getInputMock.mockImplementation((inputName) => { switch (inputName) { case InputNames.DownFlags: @@ -269,15 +216,6 @@ describe("InputService", () => { }); it("should return empty array when no down-flags input", () => { - getMultilineInputMock.mockImplementation((inputName) => { - switch (inputName) { - case InputNames.ComposeFile: - return ["file1"]; - default: - return []; - } - }); - getInputMock.mockReturnValue(""); existsSyncMock.mockReturnValue(true); @@ -289,14 +227,6 @@ describe("InputService", () => { describe("cwd", () => { it("should return given cwd input", () => { - getMultilineInputMock.mockImplementation((inputName) => { - switch (inputName) { - case InputNames.ComposeFile: - return ["file1"]; - default: - return []; - } - }); getInputMock.mockImplementation((inputName) => { switch (inputName) { case InputNames.Cwd: @@ -315,14 +245,6 @@ describe("InputService", () => { describe("compose-version", () => { it("should return given compose-version input", () => { - getMultilineInputMock.mockImplementation((inputName) => { - switch (inputName) { - case InputNames.ComposeFile: - return ["file1"]; - default: - return []; - } - }); getInputMock.mockImplementation((inputName) => { switch (inputName) { case InputNames.ComposeVersion: @@ -338,5 +260,53 @@ describe("InputService", () => { expect(inputs.composeVersion).toEqual("compose-version"); }); }); + + describe("services-log-level", () => { + it("should return given services-log-level input", () => { + getInputMock.mockImplementation((inputName) => { + switch (inputName) { + case InputNames.ServiceLogLevel: + return "info"; + default: + return ""; + } + }); + existsSyncMock.mockReturnValue(true); + + const inputs = service.getInputs(); + expect(inputs.serviceLogLevel).toEqual(LogLevel.Info); + }); + + it("should return default services-log-level input", () => { + getInputMock.mockImplementation((inputName) => { + switch (inputName) { + case InputNames.ServiceLogLevel: + return ""; + default: + return ""; + } + }); + existsSyncMock.mockReturnValue(true); + + const inputs = service.getInputs(); + expect(inputs.serviceLogLevel).toEqual(LogLevel.Debug); + }); + + it("should throw an error when services-log-level input is invalid", () => { + getInputMock.mockImplementation((inputName) => { + switch (inputName) { + case InputNames.ServiceLogLevel: + return "invalid-log-level"; + default: + return ""; + } + }); + existsSyncMock.mockReturnValue(true); + + expect(() => service.getInputs()).toThrow( + 'Invalid service log level "invalid-log-level". Valid values are: debug, info' + ); + }); + }); }); }); diff --git a/src/services/input.service.ts b/src/services/input.service.ts index 2faf383..eb7f7d4 100644 --- a/src/services/input.service.ts +++ b/src/services/input.service.ts @@ -1,6 +1,7 @@ import { getInput, getMultilineInput } from "@actions/core"; import { existsSync } from "fs"; import { join } from "path"; +import { LogLevel } from "./logger.service"; export type Inputs = { dockerFlags: string[]; @@ -12,6 +13,7 @@ export type Inputs = { cwd: string; composeVersion: string | null; githubToken: string | null; + serviceLogLevel: LogLevel; }; export enum InputNames { @@ -24,6 +26,7 @@ export enum InputNames { Cwd = "cwd", ComposeVersion = "compose-version", GithubToken = "github-token", + ServiceLogLevel = "services-log-level", } export const COMPOSE_VERSION_LATEST = "latest"; @@ -40,6 +43,7 @@ export class InputService { cwd: this.getCwd(), composeVersion: this.getComposeVersion(), githubToken: this.getGithubToken(), + serviceLogLevel: this.getServiceLogLevel(), }; } @@ -115,4 +119,14 @@ export class InputService { }) || null ); } + + private getServiceLogLevel(): LogLevel { + const configuredLevel = getInput(InputNames.ServiceLogLevel, { required: false }); + if (configuredLevel && !Object.values(LogLevel).includes(configuredLevel as LogLevel)) { + throw new Error( + `Invalid service log level "${configuredLevel}". Valid values are: ${Object.values(LogLevel).join(", ")}` + ); + } + return (configuredLevel as LogLevel) || LogLevel.Debug; + } } diff --git a/src/services/logger.service.test.ts b/src/services/logger.service.test.ts index 31e172e..d31acd2 100644 --- a/src/services/logger.service.test.ts +++ b/src/services/logger.service.test.ts @@ -1,4 +1,4 @@ -import { LoggerService } from "./logger.service"; +import { LoggerService, LogLevel } from "./logger.service"; import { debug, info, warning } from "@actions/core"; jest.mock("@actions/core", () => ({ @@ -43,4 +43,21 @@ describe("LoggerService", () => { expect(debug).toHaveBeenCalledWith(message); }); }); + + describe("getServiceLogger", () => { + it("should return the correct logger function for debug level", () => { + const logger = loggerService.getServiceLogger(LogLevel.Debug); + expect(logger).toBe(loggerService.debug); + }); + + it("should return the correct logger function for info level", () => { + const logger = loggerService.getServiceLogger(LogLevel.Info); + expect(logger).toBe(loggerService.info); + }); + + it("should default to info level if an unknown level is provided", () => { + const logger = loggerService.getServiceLogger("unknown" as LogLevel); + expect(logger).toBe(loggerService.info); + }); + }); }); diff --git a/src/services/logger.service.ts b/src/services/logger.service.ts index 0b75935..fa50cf5 100644 --- a/src/services/logger.service.ts +++ b/src/services/logger.service.ts @@ -12,4 +12,20 @@ export class LoggerService { debug(message: string) { debug(message); } + + getServiceLogger(level: LogLevel): (message: string) => void { + switch (level) { + case LogLevel.Debug: + return this.debug; + case LogLevel.Info: + return this.info; + default: + return this.info; + } + } +} + +export enum LogLevel { + Debug = "debug", + Info = "info", }