diff --git a/.github/ghadocs/examples/1_environment-variables.md b/.github/ghadocs/examples/1_environment-variables.md index 9b7bee6..69270e4 100644 --- a/.github/ghadocs/examples/1_environment-variables.md +++ b/.github/ghadocs/examples/1_environment-variables.md @@ -1,4 +1,5 @@ - + + ### Example Using environment variables ```yaml diff --git a/.github/ghadocs/examples/2_services.md b/.github/ghadocs/examples/2_services.md index 02e7113..78a4af2 100644 --- a/.github/ghadocs/examples/2_services.md +++ b/.github/ghadocs/examples/2_services.md @@ -1,4 +1,5 @@ - + + ### Example using `services` Perform `docker compose up` to some given service instead of all of them diff --git a/.github/ghadocs/examples/3_up-flags.md b/.github/ghadocs/examples/3_up-flags.md index 013936c..53ecfa5 100644 --- a/.github/ghadocs/examples/3_up-flags.md +++ b/.github/ghadocs/examples/3_up-flags.md @@ -1,4 +1,5 @@ - + + ### Example using `up-flags` Specify flags to pass to the `docker compose up`. Default is none. Can be used diff --git a/.github/ghadocs/examples/4_down-flags.md b/.github/ghadocs/examples/4_down-flags.md index 0157502..647af9d 100644 --- a/.github/ghadocs/examples/4_down-flags.md +++ b/.github/ghadocs/examples/4_down-flags.md @@ -1,4 +1,5 @@ - + + ### Example using `down-flags` Specify flags to pass to the `docker-compose down` command during cleanup. diff --git a/.github/ghadocs/examples/5_compose-flags.md b/.github/ghadocs/examples/5_compose-flags.md index e708d49..ea91263 100644 --- a/.github/ghadocs/examples/5_compose-flags.md +++ b/.github/ghadocs/examples/5_compose-flags.md @@ -1,4 +1,5 @@ - + + ### Example using `compose-flags` Specify flags to pass to the `docker compose` command. Default is none. A full diff --git a/.github/workflows/__check-action.yml b/.github/workflows/__check-action.yml index 9085e1a..afdec5b 100644 --- a/.github/workflows/__check-action.yml +++ b/.github/workflows/__check-action.yml @@ -269,5 +269,6 @@ jobs: - name: Act uses: ./ with: + docker-flags: "--context test-context" compose-file: "./test/docker-compose.yml" compose-version: "latest" diff --git a/README.md b/README.md index 8d01f1c..f9c6747 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,11 @@ -Release%20by%20tagRelease%20by%20dateCommitOpen%20IssuesDownloads +Release%20by%20tag +Release%20by%20date +Commit +Open%20Issues +Downloads diff --git a/action.yml b/action.yml index 57a7a82..09858fa 100644 --- a/action.yml +++ b/action.yml @@ -1,11 +1,14 @@ name: "Docker Compose Action" -description: "This action runs your compose file and clean up before action finished" +description: "This action runs your compose file(s) and clean up before action finished" author: "Hoverkraft" branding: icon: anchor color: gray-dark inputs: + docker-flags: + description: "Additional options to pass to `docker` command." + required: false compose-file: description: "Path to compose file(s). It can be a list of files. It can be absolute or relative to the current working directory (cwd)." required: false diff --git a/dist/index.js b/dist/index.js index 053e9c2..f5968fe 100644 --- a/dist/index.js +++ b/dist/index.js @@ -33172,6 +33172,7 @@ async function run() { loggerService.info(`docker compose version: ${installedVersion}`); loggerService.info("Bringing up docker compose service(s)"); await dockerComposeService.up({ + dockerFlags: inputs.dockerFlags, composeFiles: inputs.composeFiles, composeFlags: inputs.composeFlags, cwd: inputs.cwd, @@ -33313,12 +33314,16 @@ class DockerComposeService { output: out, }; } - getCommonOptions({ composeFiles, composeFlags, cwd, debug, }) { + getCommonOptions({ dockerFlags, composeFiles, composeFlags, cwd, debug, }) { return { config: composeFiles, composeOptions: composeFlags, cwd: cwd, callback: (chunk) => debug(chunk.toString()), + executable: { + executablePath: "docker", + options: dockerFlags, + }, }; } } @@ -33339,6 +33344,7 @@ const fs_1 = __nccwpck_require__(9896); const path_1 = __nccwpck_require__(6928); var InputNames; (function (InputNames) { + InputNames["DockerFlags"] = "docker-flags"; InputNames["ComposeFile"] = "compose-file"; InputNames["Services"] = "services"; InputNames["ComposeFlags"] = "compose-flags"; @@ -33352,6 +33358,7 @@ exports.COMPOSE_VERSION_LATEST = "latest"; class InputService { getInputs() { return { + dockerFlags: this.getDockerFlags(), composeFiles: this.getComposeFiles(), services: this.getServices(), composeFlags: this.getComposeFlags(), @@ -33362,6 +33369,9 @@ class InputService { githubToken: this.getGithubToken(), }; } + getDockerFlags() { + return this.parseFlags((0, core_1.getInput)(InputNames.DockerFlags)); + } getComposeFiles() { const cwd = this.getCwd(); const composeFiles = (0, core_1.getMultilineInput)(InputNames.ComposeFile).filter((composeFile) => { diff --git a/dist/post.js b/dist/post.js index b36364b..56918a6 100644 --- a/dist/post.js +++ b/dist/post.js @@ -26335,6 +26335,7 @@ async function run() { const dockerComposeService = new docker_compose_service_1.DockerComposeService(); const inputs = inputService.getInputs(); const { error, output } = await dockerComposeService.logs({ + dockerFlags: inputs.dockerFlags, composeFiles: inputs.composeFiles, composeFlags: inputs.composeFlags, cwd: inputs.cwd, @@ -26346,6 +26347,7 @@ async function run() { } loggerService.debug("docker compose logs:\n" + output); await dockerComposeService.down({ + dockerFlags: inputs.dockerFlags, composeFiles: inputs.composeFiles, composeFlags: inputs.composeFlags, cwd: inputs.cwd, @@ -26401,12 +26403,16 @@ class DockerComposeService { output: out, }; } - getCommonOptions({ composeFiles, composeFlags, cwd, debug, }) { + getCommonOptions({ dockerFlags, composeFiles, composeFlags, cwd, debug, }) { return { config: composeFiles, composeOptions: composeFlags, cwd: cwd, callback: (chunk) => debug(chunk.toString()), + executable: { + executablePath: "docker", + options: dockerFlags, + }, }; } } @@ -26427,6 +26433,7 @@ const fs_1 = __nccwpck_require__(9896); const path_1 = __nccwpck_require__(6928); var InputNames; (function (InputNames) { + InputNames["DockerFlags"] = "docker-flags"; InputNames["ComposeFile"] = "compose-file"; InputNames["Services"] = "services"; InputNames["ComposeFlags"] = "compose-flags"; @@ -26440,6 +26447,7 @@ exports.COMPOSE_VERSION_LATEST = "latest"; class InputService { getInputs() { return { + dockerFlags: this.getDockerFlags(), composeFiles: this.getComposeFiles(), services: this.getServices(), composeFlags: this.getComposeFlags(), @@ -26450,6 +26458,9 @@ class InputService { githubToken: this.getGithubToken(), }; } + getDockerFlags() { + return this.parseFlags((0, core_1.getInput)(InputNames.DockerFlags)); + } getComposeFiles() { const cwd = this.getCwd(); const composeFiles = (0, core_1.getMultilineInput)(InputNames.ComposeFile).filter((composeFile) => { diff --git a/src/index-runner.test.ts b/src/index-runner.test.ts index 7b6083a..7a33749 100644 --- a/src/index-runner.test.ts +++ b/src/index-runner.test.ts @@ -28,6 +28,7 @@ describe("run", () => { it("should install docker compose with specified version", async () => { // Arrange getInputsMock.mockImplementation(() => ({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: [], composeFlags: [], @@ -49,7 +50,7 @@ describe("run", () => { expect(infoMock).toHaveBeenCalledWith("Setting up docker compose version 1.29.2"); expect(debugMock).toHaveBeenCalledWith( - 'inputs: {"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}' ); expect(installMock).toHaveBeenCalledWith({ @@ -59,6 +60,7 @@ describe("run", () => { }); expect(upMock).toHaveBeenCalledWith({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], composeFlags: [], cwd: "/current/working/dir", @@ -73,6 +75,7 @@ describe("run", () => { it("should bring up docker compose services", async () => { // Arrange getInputsMock.mockImplementation(() => ({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: ["web"], composeFlags: [], @@ -88,6 +91,7 @@ describe("run", () => { // Assert expect(upMock).toHaveBeenCalledWith({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], composeFlags: [], cwd: "/current/working/dir", @@ -104,6 +108,7 @@ describe("run", () => { upMock.mockRejectedValue(error); getInputsMock.mockImplementation(() => ({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: ["web"], composeFlags: [], @@ -127,6 +132,7 @@ describe("run", () => { upMock.mockRejectedValue(error); getInputsMock.mockImplementation(() => ({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: ["web"], composeFlags: [], diff --git a/src/index-runner.ts b/src/index-runner.ts index 3646b24..0cb2ed0 100644 --- a/src/index-runner.ts +++ b/src/index-runner.ts @@ -36,6 +36,7 @@ export async function run(): Promise { loggerService.info("Bringing up docker compose service(s)"); await dockerComposeService.up({ + dockerFlags: inputs.dockerFlags, composeFiles: inputs.composeFiles, composeFlags: inputs.composeFlags, cwd: inputs.cwd, diff --git a/src/index.test.ts b/src/index.test.ts index 8410d2a..c2ff37c 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -25,6 +25,7 @@ describe("index", () => { it("calls run when imported", async () => { getInputsMock.mockImplementation(() => ({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: [], composeFlags: [], @@ -48,12 +49,13 @@ describe("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","composeVersion":null,"githubToken":null}' + 'inputs: {"dockerFlags":[],"composeFiles":["docker-compose.yml"],"services":[],"composeFlags":[],"upFlags":[],"downFlags":[],"cwd":"/current/working/dir","composeVersion":null,"githubToken":null}' ); expect(infoMock).toHaveBeenNthCalledWith(3, "Bringing up docker compose service(s)"); expect(upMock).toHaveBeenCalledWith({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: [], composeFlags: [], diff --git a/src/post-runner.test.ts b/src/post-runner.test.ts index 5cbc43a..3f8ce72 100644 --- a/src/post-runner.test.ts +++ b/src/post-runner.test.ts @@ -27,6 +27,7 @@ describe("run", () => { it("should bring down docker compose service(s) and log output", async () => { // Arrange getInputsMock.mockImplementation(() => ({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: [], composeFlags: [], @@ -46,6 +47,7 @@ describe("run", () => { // Assert expect(logsMock).toHaveBeenCalledWith({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], composeFlags: [], cwd: "/current/working/dir", @@ -54,6 +56,7 @@ describe("run", () => { }); expect(downMock).toHaveBeenCalledWith({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], composeFlags: [], cwd: "/current/working/dir", @@ -71,6 +74,7 @@ describe("run", () => { it("should log docker composer errors if any", async () => { // Arrange getInputsMock.mockImplementation(() => ({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: [], composeFlags: [], @@ -96,6 +100,7 @@ describe("run", () => { composeFiles: ["docker-compose.yml"], composeFlags: [], cwd: "/current/working/dir", + dockerFlags: [], services: [], debug: debugMock, }); @@ -104,6 +109,7 @@ describe("run", () => { composeFiles: ["docker-compose.yml"], composeFlags: [], cwd: "/current/working/dir", + dockerFlags: [], downFlags: [], debug: debugMock, }); @@ -133,6 +139,7 @@ describe("run", () => { downMock.mockRejectedValue(error); getInputsMock.mockImplementation(() => ({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: ["web"], composeFlags: [], @@ -156,6 +163,7 @@ describe("run", () => { downMock.mockRejectedValue(error); getInputsMock.mockImplementation(() => ({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: ["web"], composeFlags: [], diff --git a/src/post-runner.ts b/src/post-runner.ts index ddbe22d..2314010 100644 --- a/src/post-runner.ts +++ b/src/post-runner.ts @@ -16,6 +16,7 @@ export async function run(): Promise { const inputs = inputService.getInputs(); const { error, output } = await dockerComposeService.logs({ + dockerFlags: inputs.dockerFlags, composeFiles: inputs.composeFiles, composeFlags: inputs.composeFlags, cwd: inputs.cwd, @@ -30,6 +31,7 @@ export async function run(): Promise { loggerService.debug("docker compose logs:\n" + output); await dockerComposeService.down({ + dockerFlags: inputs.dockerFlags, composeFiles: inputs.composeFiles, composeFlags: inputs.composeFlags, cwd: inputs.cwd, diff --git a/src/post.test.ts b/src/post.test.ts index 126d463..495565e 100644 --- a/src/post.test.ts +++ b/src/post.test.ts @@ -24,6 +24,7 @@ describe("post", () => { it("calls run when imported", async () => { getInputsMock.mockImplementation(() => ({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: [], composeFlags: [], @@ -42,6 +43,7 @@ describe("post", () => { await new Promise((resolve) => setTimeout(resolve, 0)); expect(logsMock).toHaveBeenCalledWith({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], composeFlags: [], cwd: "/current/working/dir", @@ -50,6 +52,7 @@ describe("post", () => { }); expect(downMock).toHaveBeenCalledWith({ + dockerFlags: [], composeFiles: ["docker-compose.yml"], composeFlags: [], cwd: "/current/working/dir", diff --git a/src/services/docker-compose.service.test.ts b/src/services/docker-compose.service.test.ts index b1a167d..78aa83d 100644 --- a/src/services/docker-compose.service.test.ts +++ b/src/services/docker-compose.service.test.ts @@ -25,6 +25,7 @@ describe("DockerComposeService", () => { describe("up", () => { it("should call up with correct options", async () => { const upInputs: UpInputs = { + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: [], composeFlags: [], @@ -39,6 +40,36 @@ describe("DockerComposeService", () => { composeOptions: [], commandOptions: [], config: ["docker-compose.yml"], + executable: { + executablePath: "docker", + options: [], + }, + cwd: "/current/working/dir", + callback: expect.any(Function), + }); + }); + + it("should call up with specific docker flags", async () => { + const upInputs: UpInputs = { + dockerFlags: ["--context", "dev"], + composeFiles: ["docker-compose.yml"], + services: [], + composeFlags: [], + upFlags: [], + cwd: "/current/working/dir", + debug: jest.fn(), + }; + + await service.up(upInputs); + + expect(upAllMock).toHaveBeenCalledWith({ + composeOptions: [], + commandOptions: [], + config: ["docker-compose.yml"], + executable: { + executablePath: "docker", + options: ["--context", "dev"], + }, cwd: "/current/working/dir", callback: expect.any(Function), }); @@ -46,6 +77,7 @@ describe("DockerComposeService", () => { it("should call up with specific services", async () => { const upInputs: UpInputs = { + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: ["helloworld2", "helloworld3"], composeFlags: [], @@ -62,6 +94,10 @@ describe("DockerComposeService", () => { config: ["docker-compose.yml"], cwd: "/current/working/dir", callback: expect.any(Function), + executable: { + executablePath: "docker", + options: [], + }, }); }); }); @@ -69,6 +105,7 @@ describe("DockerComposeService", () => { describe("down", () => { it("should call down with correct options", async () => { const downInputs: DownInputs = { + dockerFlags: [], composeFiles: [], composeFlags: [], downFlags: ["--volumes", "--remove-orphans"], @@ -82,6 +119,10 @@ describe("DockerComposeService", () => { composeOptions: [], commandOptions: ["--volumes", "--remove-orphans"], config: [], + executable: { + executablePath: "docker", + options: [], + }, cwd: "/current/working/dir", callback: expect.any(Function), }); @@ -92,6 +133,7 @@ describe("DockerComposeService", () => { it("should call logs with correct options", async () => { const debugMock = jest.fn(); const logsInputs: LogsInputs = { + dockerFlags: [], composeFiles: ["docker-compose.yml"], services: ["helloworld2", "helloworld3"], composeFlags: [], @@ -107,6 +149,10 @@ describe("DockerComposeService", () => { composeOptions: [], config: ["docker-compose.yml"], cwd: "/current/working/dir", + executable: { + executablePath: "docker", + options: [], + }, follow: false, callback: expect.any(Function), }); diff --git a/src/services/docker-compose.service.ts b/src/services/docker-compose.service.ts index 55bf368..bdc0a36 100644 --- a/src/services/docker-compose.service.ts +++ b/src/services/docker-compose.service.ts @@ -9,6 +9,7 @@ import { import { Inputs } from "./input.service"; type OptionsInputs = { + dockerFlags: Inputs["dockerFlags"]; composeFiles: Inputs["composeFiles"]; composeFlags: Inputs["composeFlags"]; cwd: Inputs["cwd"]; @@ -61,6 +62,7 @@ export class DockerComposeService { } private getCommonOptions({ + dockerFlags, composeFiles, composeFlags, cwd, @@ -71,6 +73,10 @@ export class DockerComposeService { composeOptions: composeFlags, cwd: cwd, callback: (chunk) => debug(chunk.toString()), + executable: { + executablePath: "docker", + options: dockerFlags, + }, }; } } diff --git a/src/services/input.service.test.ts b/src/services/input.service.test.ts index d46d38c..863af98 100644 --- a/src/services/input.service.test.ts +++ b/src/services/input.service.test.ts @@ -23,6 +23,53 @@ 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: + return "docker-flag1 docker-flag2"; + default: + return ""; + } + }); + + existsSyncMock.mockReturnValue(true); + + const inputs = service.getInputs(); + + expect(inputs.dockerFlags).toEqual(["docker-flag1", "docker-flag2"]); + }); + + 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); + + const inputs = service.getInputs(); + + expect(inputs.dockerFlags).toEqual([]); + }); + }); + describe("composeFiles", () => { it("should return given composeFiles input", () => { getMultilineInputMock.mockImplementation((inputName) => { diff --git a/src/services/input.service.ts b/src/services/input.service.ts index 1bf4240..2faf383 100644 --- a/src/services/input.service.ts +++ b/src/services/input.service.ts @@ -3,6 +3,7 @@ import { existsSync } from "fs"; import { join } from "path"; export type Inputs = { + dockerFlags: string[]; composeFiles: string[]; services: string[]; composeFlags: string[]; @@ -14,6 +15,7 @@ export type Inputs = { }; export enum InputNames { + DockerFlags = "docker-flags", ComposeFile = "compose-file", Services = "services", ComposeFlags = "compose-flags", @@ -29,6 +31,7 @@ export const COMPOSE_VERSION_LATEST = "latest"; export class InputService { getInputs(): Inputs { return { + dockerFlags: this.getDockerFlags(), composeFiles: this.getComposeFiles(), services: this.getServices(), composeFlags: this.getComposeFlags(), @@ -40,6 +43,10 @@ export class InputService { }; } + private getDockerFlags(): string[] { + return this.parseFlags(getInput(InputNames.DockerFlags)); + } + private getComposeFiles(): string[] { const cwd = this.getCwd(); const composeFiles = getMultilineInput(InputNames.ComposeFile).filter((composeFile: string) => {