mirror of
				https://github.com/actions/cache.git
				synced 2025-11-04 21:39:09 +08:00 
			
		
		
		
	Use zstd instead of gzip if available
Add zstd to cache versioning
This commit is contained in:
		@@ -1,12 +1,12 @@
 | 
			
		||||
import { getCacheVersion } from "../src/cacheHttpClient";
 | 
			
		||||
import { Inputs } from "../src/constants";
 | 
			
		||||
import { CompressionMethod, Inputs } from "../src/constants";
 | 
			
		||||
import * as testUtils from "../src/utils/testUtils";
 | 
			
		||||
 | 
			
		||||
afterEach(() => {
 | 
			
		||||
    testUtils.clearInputs();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("getCacheVersion with path input returns version", async () => {
 | 
			
		||||
test("getCacheVersion with path input and compression method undefined returns version", async () => {
 | 
			
		||||
    testUtils.setInput(Inputs.Path, "node_modules");
 | 
			
		||||
 | 
			
		||||
    const result = getCacheVersion();
 | 
			
		||||
@@ -16,6 +16,24 @@ test("getCacheVersion with path input returns version", async () => {
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("getCacheVersion with zstd compression returns version", async () => {
 | 
			
		||||
    testUtils.setInput(Inputs.Path, "node_modules");
 | 
			
		||||
    const result = getCacheVersion(CompressionMethod.Zstd);
 | 
			
		||||
 | 
			
		||||
    expect(result).toEqual(
 | 
			
		||||
        "273877e14fd65d270b87a198edbfa2db5a43de567c9a548d2a2505b408befe24"
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("getCacheVersion with gzip compression does not change vesion", async () => {
 | 
			
		||||
    testUtils.setInput(Inputs.Path, "node_modules");
 | 
			
		||||
    const result = getCacheVersion(CompressionMethod.Gzip);
 | 
			
		||||
 | 
			
		||||
    expect(result).toEqual(
 | 
			
		||||
        "b3e0c6cb5ecf32614eeb2997d905b9c297046d7cbf69062698f25b14b4cb0985"
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("getCacheVersion with no input throws", async () => {
 | 
			
		||||
    expect(() => getCacheVersion()).toThrow();
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,12 @@ import * as core from "@actions/core";
 | 
			
		||||
import * as path from "path";
 | 
			
		||||
 | 
			
		||||
import * as cacheHttpClient from "../src/cacheHttpClient";
 | 
			
		||||
import { Events, Inputs } from "../src/constants";
 | 
			
		||||
import {
 | 
			
		||||
    CacheFilename,
 | 
			
		||||
    CompressionMethod,
 | 
			
		||||
    Events,
 | 
			
		||||
    Inputs
 | 
			
		||||
} from "../src/constants";
 | 
			
		||||
import { ArtifactCacheEntry } from "../src/contracts";
 | 
			
		||||
import run from "../src/restore";
 | 
			
		||||
import * as tar from "../src/tar";
 | 
			
		||||
@@ -30,6 +35,11 @@ beforeAll(() => {
 | 
			
		||||
        const actualUtils = jest.requireActual("../src/utils/actionUtils");
 | 
			
		||||
        return actualUtils.getSupportedEvents();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(actionUtils, "getCacheFileName").mockImplementation(cm => {
 | 
			
		||||
        const actualUtils = jest.requireActual("../src/utils/actionUtils");
 | 
			
		||||
        return actualUtils.getCacheFileName(cm);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
beforeEach(() => {
 | 
			
		||||
@@ -197,7 +207,7 @@ test("restore with restore keys and no cache found", async () => {
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("restore with cache found", async () => {
 | 
			
		||||
test("restore with gzip compressed cache found", async () => {
 | 
			
		||||
    const key = "node-test";
 | 
			
		||||
    testUtils.setInputs({
 | 
			
		||||
        path: "node_modules",
 | 
			
		||||
@@ -227,7 +237,7 @@ test("restore with cache found", async () => {
 | 
			
		||||
        return Promise.resolve(tempPath);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const archivePath = path.join(tempPath, "cache.tgz");
 | 
			
		||||
    const archivePath = path.join(tempPath, CacheFilename.Gzip);
 | 
			
		||||
    const setCacheStateMock = jest.spyOn(actionUtils, "setCacheState");
 | 
			
		||||
    const downloadCacheMock = jest.spyOn(cacheHttpClient, "downloadCache");
 | 
			
		||||
 | 
			
		||||
@@ -240,10 +250,17 @@ test("restore with cache found", async () => {
 | 
			
		||||
    const unlinkFileMock = jest.spyOn(actionUtils, "unlinkFile");
 | 
			
		||||
    const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
 | 
			
		||||
 | 
			
		||||
    const compression = CompressionMethod.Gzip;
 | 
			
		||||
    const getCompressionMock = jest
 | 
			
		||||
        .spyOn(actionUtils, "getCompressionMethod")
 | 
			
		||||
        .mockReturnValue(Promise.resolve(compression));
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
 | 
			
		||||
    expect(getCacheMock).toHaveBeenCalledWith([key]);
 | 
			
		||||
    expect(getCacheMock).toHaveBeenCalledWith([key], {
 | 
			
		||||
        compressionMethod: compression
 | 
			
		||||
    });
 | 
			
		||||
    expect(setCacheStateMock).toHaveBeenCalledWith(cacheEntry);
 | 
			
		||||
    expect(createTempDirectoryMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(downloadCacheMock).toHaveBeenCalledWith(
 | 
			
		||||
@@ -253,7 +270,7 @@ test("restore with cache found", async () => {
 | 
			
		||||
    expect(getArchiveFileSizeMock).toHaveBeenCalledWith(archivePath);
 | 
			
		||||
 | 
			
		||||
    expect(extractTarMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(extractTarMock).toHaveBeenCalledWith(archivePath);
 | 
			
		||||
    expect(extractTarMock).toHaveBeenCalledWith(archivePath, compression);
 | 
			
		||||
 | 
			
		||||
    expect(unlinkFileMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(unlinkFileMock).toHaveBeenCalledWith(archivePath);
 | 
			
		||||
@@ -263,9 +280,10 @@ test("restore with cache found", async () => {
 | 
			
		||||
 | 
			
		||||
    expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(getCompressionMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("restore with a pull request event and cache found", async () => {
 | 
			
		||||
test("restore with a pull request event and zstd compressed cache found", async () => {
 | 
			
		||||
    const key = "node-test";
 | 
			
		||||
    testUtils.setInputs({
 | 
			
		||||
        path: "node_modules",
 | 
			
		||||
@@ -297,7 +315,7 @@ test("restore with a pull request event and cache found", async () => {
 | 
			
		||||
        return Promise.resolve(tempPath);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const archivePath = path.join(tempPath, "cache.tgz");
 | 
			
		||||
    const archivePath = path.join(tempPath, CacheFilename.Zstd);
 | 
			
		||||
    const setCacheStateMock = jest.spyOn(actionUtils, "setCacheState");
 | 
			
		||||
    const downloadCacheMock = jest.spyOn(cacheHttpClient, "downloadCache");
 | 
			
		||||
 | 
			
		||||
@@ -308,11 +326,17 @@ test("restore with a pull request event and cache found", async () => {
 | 
			
		||||
 | 
			
		||||
    const extractTarMock = jest.spyOn(tar, "extractTar");
 | 
			
		||||
    const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
 | 
			
		||||
    const compression = CompressionMethod.Zstd;
 | 
			
		||||
    const getCompressionMock = jest
 | 
			
		||||
        .spyOn(actionUtils, "getCompressionMethod")
 | 
			
		||||
        .mockReturnValue(Promise.resolve(compression));
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
 | 
			
		||||
    expect(getCacheMock).toHaveBeenCalledWith([key]);
 | 
			
		||||
    expect(getCacheMock).toHaveBeenCalledWith([key], {
 | 
			
		||||
        compressionMethod: compression
 | 
			
		||||
    });
 | 
			
		||||
    expect(setCacheStateMock).toHaveBeenCalledWith(cacheEntry);
 | 
			
		||||
    expect(createTempDirectoryMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(downloadCacheMock).toHaveBeenCalledWith(
 | 
			
		||||
@@ -323,13 +347,14 @@ test("restore with a pull request event and cache found", async () => {
 | 
			
		||||
    expect(infoMock).toHaveBeenCalledWith(`Cache Size: ~60 MB (62915000 B)`);
 | 
			
		||||
 | 
			
		||||
    expect(extractTarMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(extractTarMock).toHaveBeenCalledWith(archivePath);
 | 
			
		||||
    expect(extractTarMock).toHaveBeenCalledWith(archivePath, compression);
 | 
			
		||||
 | 
			
		||||
    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(setCacheHitOutputMock).toHaveBeenCalledWith(true);
 | 
			
		||||
 | 
			
		||||
    expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(getCompressionMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("restore with cache found for restore key", async () => {
 | 
			
		||||
@@ -364,7 +389,7 @@ test("restore with cache found for restore key", async () => {
 | 
			
		||||
        return Promise.resolve(tempPath);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const archivePath = path.join(tempPath, "cache.tgz");
 | 
			
		||||
    const archivePath = path.join(tempPath, CacheFilename.Zstd);
 | 
			
		||||
    const setCacheStateMock = jest.spyOn(actionUtils, "setCacheState");
 | 
			
		||||
    const downloadCacheMock = jest.spyOn(cacheHttpClient, "downloadCache");
 | 
			
		||||
 | 
			
		||||
@@ -375,11 +400,17 @@ test("restore with cache found for restore key", async () => {
 | 
			
		||||
 | 
			
		||||
    const extractTarMock = jest.spyOn(tar, "extractTar");
 | 
			
		||||
    const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
 | 
			
		||||
    const compression = CompressionMethod.Zstd;
 | 
			
		||||
    const getCompressionMock = jest
 | 
			
		||||
        .spyOn(actionUtils, "getCompressionMethod")
 | 
			
		||||
        .mockReturnValue(Promise.resolve(compression));
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
 | 
			
		||||
    expect(getCacheMock).toHaveBeenCalledWith([key, restoreKey]);
 | 
			
		||||
    expect(getCacheMock).toHaveBeenCalledWith([key, restoreKey], {
 | 
			
		||||
        compressionMethod: compression
 | 
			
		||||
    });
 | 
			
		||||
    expect(setCacheStateMock).toHaveBeenCalledWith(cacheEntry);
 | 
			
		||||
    expect(createTempDirectoryMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(downloadCacheMock).toHaveBeenCalledWith(
 | 
			
		||||
@@ -390,7 +421,7 @@ test("restore with cache found for restore key", async () => {
 | 
			
		||||
    expect(infoMock).toHaveBeenCalledWith(`Cache Size: ~0 MB (142 B)`);
 | 
			
		||||
 | 
			
		||||
    expect(extractTarMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(extractTarMock).toHaveBeenCalledWith(archivePath);
 | 
			
		||||
    expect(extractTarMock).toHaveBeenCalledWith(archivePath, compression);
 | 
			
		||||
 | 
			
		||||
    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
 | 
			
		||||
@@ -399,4 +430,5 @@ test("restore with cache found for restore key", async () => {
 | 
			
		||||
        `Cache restored from key: ${restoreKey}`
 | 
			
		||||
    );
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(getCompressionMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,12 @@ import * as core from "@actions/core";
 | 
			
		||||
import * as path from "path";
 | 
			
		||||
 | 
			
		||||
import * as cacheHttpClient from "../src/cacheHttpClient";
 | 
			
		||||
import { CacheFilename, Events, Inputs } from "../src/constants";
 | 
			
		||||
import {
 | 
			
		||||
    CacheFilename,
 | 
			
		||||
    CompressionMethod,
 | 
			
		||||
    Events,
 | 
			
		||||
    Inputs
 | 
			
		||||
} from "../src/constants";
 | 
			
		||||
import { ArtifactCacheEntry } from "../src/contracts";
 | 
			
		||||
import run from "../src/save";
 | 
			
		||||
import * as tar from "../src/tar";
 | 
			
		||||
@@ -50,6 +55,11 @@ beforeAll(() => {
 | 
			
		||||
    jest.spyOn(actionUtils, "createTempDirectory").mockImplementation(() => {
 | 
			
		||||
        return Promise.resolve("/foo/bar");
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(actionUtils, "getCacheFileName").mockImplementation(cm => {
 | 
			
		||||
        const actualUtils = jest.requireActual("../src/utils/actionUtils");
 | 
			
		||||
        return actualUtils.getCacheFileName(cm);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
beforeEach(() => {
 | 
			
		||||
@@ -201,20 +211,27 @@ test("save with large cache outputs warning", async () => {
 | 
			
		||||
    jest.spyOn(actionUtils, "getArchiveFileSize").mockImplementationOnce(() => {
 | 
			
		||||
        return cacheSize;
 | 
			
		||||
    });
 | 
			
		||||
    const compression = CompressionMethod.Gzip;
 | 
			
		||||
    const getCompressionMock = jest
 | 
			
		||||
        .spyOn(actionUtils, "getCompressionMethod")
 | 
			
		||||
        .mockReturnValue(Promise.resolve(compression));
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    const archiveFolder = "/foo/bar";
 | 
			
		||||
 | 
			
		||||
    expect(createTarMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(createTarMock).toHaveBeenCalledWith(archiveFolder, cachePaths);
 | 
			
		||||
 | 
			
		||||
    expect(createTarMock).toHaveBeenCalledWith(
 | 
			
		||||
        archiveFolder,
 | 
			
		||||
        cachePaths,
 | 
			
		||||
        compression
 | 
			
		||||
    );
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledWith(
 | 
			
		||||
        "Cache size of ~6144 MB (6442450944 B) is over the 5GB limit, not saving cache."
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(getCompressionMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("save with reserve cache failure outputs warning", async () => {
 | 
			
		||||
@@ -250,13 +267,18 @@ test("save with reserve cache failure outputs warning", async () => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    const createTarMock = jest.spyOn(tar, "createTar");
 | 
			
		||||
 | 
			
		||||
    const saveCacheMock = jest.spyOn(cacheHttpClient, "saveCache");
 | 
			
		||||
    const compression = CompressionMethod.Zstd;
 | 
			
		||||
    const getCompressionMock = jest
 | 
			
		||||
        .spyOn(actionUtils, "getCompressionMethod")
 | 
			
		||||
        .mockReturnValue(Promise.resolve(compression));
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    expect(reserveCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey);
 | 
			
		||||
    expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, {
 | 
			
		||||
        compressionMethod: compression
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    expect(infoMock).toHaveBeenCalledWith(
 | 
			
		||||
        `Unable to reserve cache with key ${primaryKey}, another job may be creating this cache.`
 | 
			
		||||
@@ -266,6 +288,7 @@ test("save with reserve cache failure outputs warning", async () => {
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(getCompressionMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("save with server error outputs warning", async () => {
 | 
			
		||||
@@ -308,17 +331,27 @@ test("save with server error outputs warning", async () => {
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            throw new Error("HTTP Error Occurred");
 | 
			
		||||
        });
 | 
			
		||||
    const compression = CompressionMethod.Zstd;
 | 
			
		||||
    const getCompressionMock = jest
 | 
			
		||||
        .spyOn(actionUtils, "getCompressionMethod")
 | 
			
		||||
        .mockReturnValue(Promise.resolve(compression));
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    expect(reserveCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey);
 | 
			
		||||
    expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, {
 | 
			
		||||
        compressionMethod: compression
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const archiveFolder = "/foo/bar";
 | 
			
		||||
    const archiveFile = path.join(archiveFolder, CacheFilename);
 | 
			
		||||
    const archiveFile = path.join(archiveFolder, CacheFilename.Zstd);
 | 
			
		||||
 | 
			
		||||
    expect(createTarMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(createTarMock).toHaveBeenCalledWith(archiveFolder, cachePaths);
 | 
			
		||||
    expect(createTarMock).toHaveBeenCalledWith(
 | 
			
		||||
        archiveFolder,
 | 
			
		||||
        cachePaths,
 | 
			
		||||
        compression
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledWith(cacheId, archiveFile);
 | 
			
		||||
@@ -327,6 +360,7 @@ test("save with server error outputs warning", async () => {
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledWith("HTTP Error Occurred");
 | 
			
		||||
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(getCompressionMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("save with valid inputs uploads a cache", async () => {
 | 
			
		||||
@@ -364,20 +398,31 @@ test("save with valid inputs uploads a cache", async () => {
 | 
			
		||||
    const createTarMock = jest.spyOn(tar, "createTar");
 | 
			
		||||
 | 
			
		||||
    const saveCacheMock = jest.spyOn(cacheHttpClient, "saveCache");
 | 
			
		||||
    const compression = CompressionMethod.Zstd;
 | 
			
		||||
    const getCompressionMock = jest
 | 
			
		||||
        .spyOn(actionUtils, "getCompressionMethod")
 | 
			
		||||
        .mockReturnValue(Promise.resolve(compression));
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    expect(reserveCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey);
 | 
			
		||||
    expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, {
 | 
			
		||||
        compressionMethod: compression
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const archiveFolder = "/foo/bar";
 | 
			
		||||
    const archiveFile = path.join(archiveFolder, CacheFilename);
 | 
			
		||||
    const archiveFile = path.join(archiveFolder, CacheFilename.Zstd);
 | 
			
		||||
 | 
			
		||||
    expect(createTarMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(createTarMock).toHaveBeenCalledWith(archiveFolder, cachePaths);
 | 
			
		||||
    expect(createTarMock).toHaveBeenCalledWith(
 | 
			
		||||
        archiveFolder,
 | 
			
		||||
        cachePaths,
 | 
			
		||||
        compression
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledWith(cacheId, archiveFile);
 | 
			
		||||
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(getCompressionMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -2,14 +2,17 @@ import * as exec from "@actions/exec";
 | 
			
		||||
import * as io from "@actions/io";
 | 
			
		||||
import * as path from "path";
 | 
			
		||||
 | 
			
		||||
import { CacheFilename } from "../src/constants";
 | 
			
		||||
import { CacheFilename, CompressionMethod } from "../src/constants";
 | 
			
		||||
import * as tar from "../src/tar";
 | 
			
		||||
import * as utils from "../src/utils/actionUtils";
 | 
			
		||||
 | 
			
		||||
import fs = require("fs");
 | 
			
		||||
 | 
			
		||||
jest.mock("@actions/exec");
 | 
			
		||||
jest.mock("@actions/io");
 | 
			
		||||
 | 
			
		||||
const IS_WINDOWS = process.platform === "win32";
 | 
			
		||||
 | 
			
		||||
function getTempDir(): string {
 | 
			
		||||
    return path.join(__dirname, "_temp", "tar");
 | 
			
		||||
}
 | 
			
		||||
@@ -28,29 +31,28 @@ afterAll(async () => {
 | 
			
		||||
    await jest.requireActual("@actions/io").rmRF(getTempDir());
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("extract BSD tar", async () => {
 | 
			
		||||
test("zstd extract tar", async () => {
 | 
			
		||||
    const mkdirMock = jest.spyOn(io, "mkdirP");
 | 
			
		||||
    const execMock = jest.spyOn(exec, "exec");
 | 
			
		||||
 | 
			
		||||
    const IS_WINDOWS = process.platform === "win32";
 | 
			
		||||
    const archivePath = IS_WINDOWS
 | 
			
		||||
        ? `${process.env["windir"]}\\fakepath\\cache.tar`
 | 
			
		||||
        : "cache.tar";
 | 
			
		||||
    const workspace = process.env["GITHUB_WORKSPACE"];
 | 
			
		||||
 | 
			
		||||
    await tar.extractTar(archivePath);
 | 
			
		||||
    await tar.extractTar(archivePath, CompressionMethod.Zstd);
 | 
			
		||||
 | 
			
		||||
    expect(mkdirMock).toHaveBeenCalledWith(workspace);
 | 
			
		||||
 | 
			
		||||
    const tarPath = IS_WINDOWS
 | 
			
		||||
        ? `${process.env["windir"]}\\System32\\tar.exe`
 | 
			
		||||
        : "tar";
 | 
			
		||||
    expect(execMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(execMock).toHaveBeenCalledWith(
 | 
			
		||||
        `"${tarPath}"`,
 | 
			
		||||
        `${tarPath}`,
 | 
			
		||||
        [
 | 
			
		||||
            "-xz",
 | 
			
		||||
            "-f",
 | 
			
		||||
            "--use-compress-program",
 | 
			
		||||
            "zstd -d",
 | 
			
		||||
            "-xf",
 | 
			
		||||
            IS_WINDOWS ? archivePath.replace(/\\/g, "/") : archivePath,
 | 
			
		||||
            "-P",
 | 
			
		||||
            "-C",
 | 
			
		||||
@@ -60,24 +62,55 @@ test("extract BSD tar", async () => {
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("extract GNU tar", async () => {
 | 
			
		||||
    const IS_WINDOWS = process.platform === "win32";
 | 
			
		||||
test("gzip extract tar", async () => {
 | 
			
		||||
    const mkdirMock = jest.spyOn(io, "mkdirP");
 | 
			
		||||
    const execMock = jest.spyOn(exec, "exec");
 | 
			
		||||
    const archivePath = IS_WINDOWS
 | 
			
		||||
        ? `${process.env["windir"]}\\fakepath\\cache.tar`
 | 
			
		||||
        : "cache.tar";
 | 
			
		||||
    const workspace = process.env["GITHUB_WORKSPACE"];
 | 
			
		||||
 | 
			
		||||
    await tar.extractTar(archivePath, CompressionMethod.Gzip);
 | 
			
		||||
 | 
			
		||||
    expect(mkdirMock).toHaveBeenCalledWith(workspace);
 | 
			
		||||
    const tarPath = IS_WINDOWS
 | 
			
		||||
        ? `${process.env["windir"]}\\System32\\tar.exe`
 | 
			
		||||
        : "tar";
 | 
			
		||||
    expect(execMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(execMock).toHaveBeenCalledWith(
 | 
			
		||||
        `${tarPath}`,
 | 
			
		||||
        [
 | 
			
		||||
            "-z",
 | 
			
		||||
            "-xf",
 | 
			
		||||
            IS_WINDOWS ? archivePath.replace(/\\/g, "/") : archivePath,
 | 
			
		||||
            "-P",
 | 
			
		||||
            "-C",
 | 
			
		||||
            IS_WINDOWS ? workspace?.replace(/\\/g, "/") : workspace
 | 
			
		||||
        ],
 | 
			
		||||
        { cwd: undefined }
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("gzip extract GNU tar on windows", async () => {
 | 
			
		||||
    if (IS_WINDOWS) {
 | 
			
		||||
        jest.spyOn(fs, "existsSync").mockReturnValueOnce(false);
 | 
			
		||||
        jest.spyOn(tar, "isGnuTar").mockReturnValue(Promise.resolve(true));
 | 
			
		||||
 | 
			
		||||
        const isGnuMock = jest
 | 
			
		||||
            .spyOn(utils, "useGnuTar")
 | 
			
		||||
            .mockReturnValue(Promise.resolve(true));
 | 
			
		||||
        const execMock = jest.spyOn(exec, "exec");
 | 
			
		||||
        const archivePath = `${process.env["windir"]}\\fakepath\\cache.tar`;
 | 
			
		||||
        const workspace = process.env["GITHUB_WORKSPACE"];
 | 
			
		||||
 | 
			
		||||
        await tar.extractTar(archivePath);
 | 
			
		||||
        await tar.extractTar(archivePath, CompressionMethod.Gzip);
 | 
			
		||||
 | 
			
		||||
        expect(execMock).toHaveBeenCalledTimes(2);
 | 
			
		||||
        expect(execMock).toHaveBeenLastCalledWith(
 | 
			
		||||
            `"tar"`,
 | 
			
		||||
        expect(isGnuMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(execMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(execMock).toHaveBeenCalledWith(
 | 
			
		||||
            `tar`,
 | 
			
		||||
            [
 | 
			
		||||
                "-xz",
 | 
			
		||||
                "-f",
 | 
			
		||||
                "-z",
 | 
			
		||||
                "-xf",
 | 
			
		||||
                archivePath.replace(/\\/g, "/"),
 | 
			
		||||
                "-P",
 | 
			
		||||
                "-C",
 | 
			
		||||
@@ -89,7 +122,7 @@ test("extract GNU tar", async () => {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("create BSD tar", async () => {
 | 
			
		||||
test("zstd create tar", async () => {
 | 
			
		||||
    const execMock = jest.spyOn(exec, "exec");
 | 
			
		||||
 | 
			
		||||
    const archiveFolder = getTempDir();
 | 
			
		||||
@@ -98,20 +131,66 @@ test("create BSD tar", async () => {
 | 
			
		||||
 | 
			
		||||
    await fs.promises.mkdir(archiveFolder, { recursive: true });
 | 
			
		||||
 | 
			
		||||
    await tar.createTar(archiveFolder, sourceDirectories);
 | 
			
		||||
    await tar.createTar(
 | 
			
		||||
        archiveFolder,
 | 
			
		||||
        sourceDirectories,
 | 
			
		||||
        CompressionMethod.Zstd
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const IS_WINDOWS = process.platform === "win32";
 | 
			
		||||
    const tarPath = IS_WINDOWS
 | 
			
		||||
        ? `${process.env["windir"]}\\System32\\tar.exe`
 | 
			
		||||
        : "tar";
 | 
			
		||||
 | 
			
		||||
    expect(execMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(execMock).toHaveBeenCalledWith(
 | 
			
		||||
        `"${tarPath}"`,
 | 
			
		||||
        `${tarPath}`,
 | 
			
		||||
        [
 | 
			
		||||
            "-cz",
 | 
			
		||||
            "-f",
 | 
			
		||||
            IS_WINDOWS ? CacheFilename.replace(/\\/g, "/") : CacheFilename,
 | 
			
		||||
            "--use-compress-program",
 | 
			
		||||
            "zstd -T0",
 | 
			
		||||
            "-cf",
 | 
			
		||||
            IS_WINDOWS
 | 
			
		||||
                ? CacheFilename.Zstd.replace(/\\/g, "/")
 | 
			
		||||
                : CacheFilename.Zstd,
 | 
			
		||||
            "-P",
 | 
			
		||||
            "-C",
 | 
			
		||||
            IS_WINDOWS ? workspace?.replace(/\\/g, "/") : workspace,
 | 
			
		||||
            "--files-from",
 | 
			
		||||
            "manifest.txt"
 | 
			
		||||
        ],
 | 
			
		||||
        {
 | 
			
		||||
            cwd: archiveFolder
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("gzip create tar", async () => {
 | 
			
		||||
    const execMock = jest.spyOn(exec, "exec");
 | 
			
		||||
 | 
			
		||||
    const archiveFolder = getTempDir();
 | 
			
		||||
    const workspace = process.env["GITHUB_WORKSPACE"];
 | 
			
		||||
    const sourceDirectories = ["~/.npm/cache", `${workspace}/dist`];
 | 
			
		||||
 | 
			
		||||
    await fs.promises.mkdir(archiveFolder, { recursive: true });
 | 
			
		||||
 | 
			
		||||
    await tar.createTar(
 | 
			
		||||
        archiveFolder,
 | 
			
		||||
        sourceDirectories,
 | 
			
		||||
        CompressionMethod.Gzip
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const tarPath = IS_WINDOWS
 | 
			
		||||
        ? `${process.env["windir"]}\\System32\\tar.exe`
 | 
			
		||||
        : "tar";
 | 
			
		||||
 | 
			
		||||
    expect(execMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(execMock).toHaveBeenCalledWith(
 | 
			
		||||
        `${tarPath}`,
 | 
			
		||||
        [
 | 
			
		||||
            "-z",
 | 
			
		||||
            "-cf",
 | 
			
		||||
            IS_WINDOWS
 | 
			
		||||
                ? CacheFilename.Gzip.replace(/\\/g, "/")
 | 
			
		||||
                : CacheFilename.Gzip,
 | 
			
		||||
            "-P",
 | 
			
		||||
            "-C",
 | 
			
		||||
            IS_WINDOWS ? workspace?.replace(/\\/g, "/") : workspace,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user