From 8c9a1ef19e0bf4eb971b510ead95db3f3b799969 Mon Sep 17 00:00:00 2001 From: Ivan Cherviakov Date: Tue, 24 Dec 2024 14:47:14 +0700 Subject: [PATCH] feat(docker): Add gzip option --- src/docker.test.ts | 55 +++++++++++++++++++++++++++++++++++------ src/docker.ts | 3 ++- src/integration.test.ts | 2 +- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/docker.test.ts b/src/docker.test.ts index 6cf45e8..3938c1b 100644 --- a/src/docker.test.ts +++ b/src/docker.test.ts @@ -92,13 +92,14 @@ describe("Docker images", (): void => { key: string, readOnly = false, prevSave = false, + gzip = false, ): void => { expect(core.getInput).nthCalledWith<[string, InputOptions]>(1, "key", { required: true, }); expect(core.getState).nthCalledWith<[string]>(1, docker.CACHE_HIT); if (!cacheHit) { - expect(core.getInput).lastCalledWith("read-only"); + expect(core.getInput).nthCalledWith(2, "read-only"); if (!readOnly) { expect(cache.restoreCache).lastCalledWith([""], key, [], { lookupOnly: true, @@ -110,6 +111,9 @@ describe("Docker images", (): void => { "Listing Docker images.", ); expect(util.execBashCommand).nthCalledWith<[string]>(1, LIST_COMMAND); + if (gzip) { + expect(core.getInput).lastCalledWith("gzip"); + } } } } @@ -120,6 +124,7 @@ describe("Docker images", (): void => { cacheHit: boolean, readOnly: boolean, prevSave: boolean, + gzip: boolean, preexistingImages: string[], newImages: string[], ): Promise => { @@ -132,6 +137,9 @@ describe("Docker images", (): void => { cache.restoreCache.mockResolvedValueOnce(key); } else { cache.restoreCache.mockResolvedValueOnce(undefined); + if (gzip) { + core.getInput.mockReturnValueOnce(gzip.toString()); + } core.getState.mockReturnValueOnce(preexistingImages.join("\n")); const images = preexistingImages.concat(newImages); util.execBashCommand.mockResolvedValueOnce(images.join("\n")); @@ -140,7 +148,7 @@ describe("Docker images", (): void => { } await docker.saveDockerImages(); - assertSaveDockerImages(cacheHit, key, readOnly, prevSave); + assertSaveDockerImages(cacheHit, key, readOnly, prevSave, gzip); }; const assertCacheNotSaved = (): void => { @@ -178,6 +186,32 @@ describe("Docker images", (): void => { expect(cache.saveCache).not.toHaveBeenCalled(); }; + const assertSaveCacheMissWithGzip = (key: string, newImages: string[]): void => { + expect(core.info).lastCalledWith( + "Images present before restore step will be skipped; only new images " + + "will be saved.", + ); + expect(util.execBashCommand).lastCalledWith( + `docker save ${newImages.join(" ")} | gzip > ${docker.DOCKER_IMAGES_PATH}` + ); + expect(cache.saveCache).lastCalledWith([docker.DOCKER_IMAGES_PATH], key); + + /* The Docker images must be saved before the cache can be. This at least + * checks that the calls are made in the right order, but doesn't ensure + * that the Docker images finished saving before the cache started saving. + */ + assertCalledInOrder( + core.getInput, + core.getState, + core.getInput, + core.getState, + util.execBashCommand, + core.getInput, + util.execBashCommand, + cache.saveCache, + ); + }; + const assertSaveCacheMiss = (key: string, newImages: string[]): void => { expect(core.info).lastCalledWith( "Images present before restore step will be skipped; only new images " + @@ -200,6 +234,7 @@ describe("Docker images", (): void => { core.getInput, core.getState, util.execBashCommand, + core.getInput, util.execBashCommand, cache.saveCache, ); @@ -262,6 +297,7 @@ describe("Docker images", (): void => { boolean(), boolean(), boolean(), + boolean(), uniquePair(dockerImages(), dockerImages()), ], async ( @@ -269,6 +305,7 @@ describe("Docker images", (): void => { cacheHit: boolean, readOnly: boolean, prevSave: boolean, + gzip: boolean, [preexistingImages, newImages]: [string[], string[]], ): Promise => { jest.clearAllMocks(); @@ -277,6 +314,7 @@ describe("Docker images", (): void => { cacheHit, readOnly, prevSave, + gzip, preexistingImages, newImages, ); @@ -289,17 +327,20 @@ describe("Docker images", (): void => { assertSavePrevSave(key); } else if (newImages.length === 0) { assertNoNewImagesToSave(); + } else if (gzip) { + assertSaveCacheMissWithGzip(key, newImages); } else { assertSaveCacheMiss(key, newImages); } }, { examples: [ - ["my-key", false, false, false, [["preexisting-image"], ["new-image"]]], - ["my-key", false, false, false, [["preexisting-image"], []]], - ["my-key", false, true, false, [["preexisting-image"], ["new-image"]]], - ["my-key", true, false, false, [["preexisting-image"], ["new-image"]]], - ["my-key", false, false, true, [["preexisting-image"], ["new-image"]]], + ["my-key", false, false, false, false, [["preexisting-image"], ["new-image"]]], + ["my-key", false, false, false, false, [["preexisting-image"], []]], + ["my-key", false, true, false, false, [["preexisting-image"], ["new-image"]]], + ["my-key", true, false, false, false, [["preexisting-image"], ["new-image"]]], + ["my-key", false, false, true, false, [["preexisting-image"], ["new-image"]]], + ["my-key", false, false, false, true, [["preexisting-image"], ["new-image"]]], ], }, ); diff --git a/src/docker.ts b/src/docker.ts index 93f84d1..1c74470 100644 --- a/src/docker.ts +++ b/src/docker.ts @@ -65,7 +65,8 @@ const saveDockerImages = async (): Promise => { "will be saved.", ); const newImagesArgs = newImages.join(" "); - const cmd = `docker save --output ${DOCKER_IMAGES_PATH} ${newImagesArgs}`; + const isUseGzip = getInput("gzip") === "true"; + const cmd = isUseGzip ? `docker save ${newImagesArgs} | gzip > ${DOCKER_IMAGES_PATH}` : `docker save --output ${DOCKER_IMAGES_PATH} ${newImagesArgs}`; await execBashCommand(cmd); await saveCache([DOCKER_IMAGES_PATH], key); } diff --git a/src/integration.test.ts b/src/integration.test.ts index cd11d13..15b2afb 100644 --- a/src/integration.test.ts +++ b/src/integration.test.ts @@ -153,7 +153,7 @@ describe("Integration Test", (): void => { listStderr: string, saveOutput: ConsoleOutput, ): void => { - expect(core.getInput).lastCalledWith("read-only"); + expect(core.getInput).nthCalledWith(2, "read-only"); expect(core.info).nthCalledWith<[string]>(1, "Listing Docker images."); const listOutput = joinOutput(dockerImages, listStderr); assertExecBashCommand(2, 1, LIST_COMMAND, listOutput);