diff --git a/README.md b/README.md index f8e474d..8651e2a 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ See ["Caching dependencies to speed up workflows"](https://docs.github.com/en/ac ### ⚠️ Important changes > [!IMPORTANT] -> `actions/cache@v6` runs on the Node.js 24 runtime and requires a minimum Actions Runner version of `2.327.1`. +> `actions/cache@v5` runs on the Node.js 24 runtime and requires a minimum Actions Runner version of `2.327.1`. > If you are using self-hosted runners, ensure they are updated before upgrading. The cache backend service has been rewritten from the ground up for improved performance and reliability. [actions/cache](https://github.com/actions/cache) now integrates with the new cache service (v2) APIs. diff --git a/__tests__/actionUtils.test.ts b/__tests__/actionUtils.test.ts index d4eb482..304952f 100644 --- a/__tests__/actionUtils.test.ts +++ b/__tests__/actionUtils.test.ts @@ -50,7 +50,7 @@ let pristineEnv: NodeJS.ProcessEnv; beforeEach(() => { pristineEnv = { ...process.env }; jest.clearAllMocks(); - (core.getInput as jest.Mock).mockImplementation( + jest.mocked(core.getInput).mockImplementation( (name: string, options?: { required?: boolean }) => { const val = process.env[`INPUT_${name.replace(/ /g, "_").toUpperCase()}`] || @@ -217,12 +217,12 @@ test("getInputAsBool throws if required and value missing", () => { }); test("isCacheFeatureAvailable for ac enabled", () => { - (cache.isFeatureAvailable as jest.Mock).mockReturnValue(true); + jest.mocked(cache.isFeatureAvailable).mockReturnValue(true); expect(actionUtils.isCacheFeatureAvailable()).toBe(true); }); test("isCacheFeatureAvailable for ac disabled on GHES", () => { - (cache.isFeatureAvailable as jest.Mock).mockReturnValue(false); + jest.mocked(cache.isFeatureAvailable).mockReturnValue(false); const message = `Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not. Otherwise please upgrade to GHES version >= 3.5 and If you are also using Github Connect, please unretire the actions/cache namespace before upgrade (see https://docs.github.com/en/enterprise-server@3.5/admin/github-actions/managing-access-to-actions-from-githubcom/enabling-automatic-access-to-githubcom-actions-using-github-connect#automatic-retirement-of-namespaces-for-actions-accessed-on-githubcom)`; @@ -237,7 +237,7 @@ Otherwise please upgrade to GHES version >= 3.5 and If you are also using Github }); test("isCacheFeatureAvailable for ac disabled on dotcom", () => { - (cache.isFeatureAvailable as jest.Mock).mockReturnValue(false); + jest.mocked(cache.isFeatureAvailable).mockReturnValue(false); const message = "An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions."; diff --git a/__tests__/restoreImpl.test.ts b/__tests__/restoreImpl.test.ts index f8c6fac..6e35d22 100644 --- a/__tests__/restoreImpl.test.ts +++ b/__tests__/restoreImpl.test.ts @@ -48,7 +48,7 @@ const testUtils = await import("../src/utils/testUtils"); beforeEach(() => { jest.clearAllMocks(); - (core.getInput as jest.Mock).mockImplementation( + jest.mocked(core.getInput).mockImplementation( (name: string, options?: { required?: boolean }) => { const val = process.env[`INPUT_${name.replace(/ /g, "_").toUpperCase()}`] || @@ -59,8 +59,8 @@ beforeEach(() => { return val.trim(); } ); - (core.getState as jest.Mock).mockReturnValue(""); - (cache.isFeatureAvailable as jest.Mock).mockReturnValue(true); + jest.mocked(core.getState).mockReturnValue(""); + jest.mocked(cache.isFeatureAvailable).mockReturnValue(true); process.env[Events.Key] = Events.Push; process.env[RefKey] = "refs/heads/feature-branch"; }); @@ -83,7 +83,7 @@ test("restore with invalid event outputs warning", async () => { }); test("restore without AC available should no-op", async () => { - (cache.isFeatureAvailable as jest.Mock).mockReturnValue(false); + jest.mocked(cache.isFeatureAvailable).mockReturnValue(false); await restoreImpl(new StateProvider()); @@ -93,13 +93,21 @@ test("restore without AC available should no-op", async () => { }); test("restore on GHES without AC available should no-op", async () => { - (cache.isFeatureAvailable as jest.Mock).mockReturnValue(false); + process.env["GITHUB_SERVER_URL"] = "https://my-ghes-server.com"; + jest.mocked(cache.isFeatureAvailable).mockReturnValue(false); await restoreImpl(new StateProvider()); expect(cache.restoreCache).toHaveBeenCalledTimes(0); expect(core.setOutput).toHaveBeenCalledTimes(1); expect(core.setOutput).toHaveBeenCalledWith("cache-hit", "false"); + expect(core.info).toHaveBeenCalledWith( + expect.stringContaining( + "Cache action is only supported on GHES version >= 3.5" + ) + ); + + delete process.env["GITHUB_SERVER_URL"]; }); test("restore on GHES with AC available ", async () => { @@ -111,7 +119,7 @@ test("restore on GHES with AC available ", async () => { enableCrossOsArchive: false }); - (cache.restoreCache as jest.Mock).mockResolvedValue(key); + jest.mocked(cache.restoreCache).mockResolvedValue(key); await restoreImpl(new StateProvider()); @@ -160,7 +168,7 @@ test("restore with too many keys should fail", async () => { restoreKeys, enableCrossOsArchive: false }); - (cache.restoreCache as jest.Mock).mockRejectedValue( + jest.mocked(cache.restoreCache).mockRejectedValue( new Error("Key Validation Error: Keys are limited to a maximum of 10.") ); await restoreImpl(new StateProvider()); @@ -178,7 +186,7 @@ test("restore with large key should fail", async () => { key, enableCrossOsArchive: false }); - (cache.restoreCache as jest.Mock).mockRejectedValue( + jest.mocked(cache.restoreCache).mockRejectedValue( new Error( `Key Validation Error: ${key} cannot be larger than 512 characters.` ) @@ -198,7 +206,7 @@ test("restore with invalid key should fail", async () => { key, enableCrossOsArchive: false }); - (cache.restoreCache as jest.Mock).mockRejectedValue( + jest.mocked(cache.restoreCache).mockRejectedValue( new Error(`Key Validation Error: ${key} cannot contain commas.`) ); await restoreImpl(new StateProvider()); @@ -217,7 +225,7 @@ test("restore with no cache found", async () => { enableCrossOsArchive: false }); - (cache.restoreCache as jest.Mock).mockResolvedValue(undefined); + jest.mocked(cache.restoreCache).mockResolvedValue(undefined); await restoreImpl(new StateProvider()); @@ -240,7 +248,7 @@ test("restore with restore keys and no cache found", async () => { enableCrossOsArchive: false }); - (cache.restoreCache as jest.Mock).mockResolvedValue(undefined); + jest.mocked(cache.restoreCache).mockResolvedValue(undefined); await restoreImpl(new StateProvider()); @@ -261,7 +269,7 @@ test("restore with cache found for key", async () => { enableCrossOsArchive: false }); - (cache.restoreCache as jest.Mock).mockResolvedValue(key); + jest.mocked(cache.restoreCache).mockResolvedValue(key); await restoreImpl(new StateProvider()); @@ -284,7 +292,7 @@ test("restore with cache found for restore key", async () => { enableCrossOsArchive: false }); - (cache.restoreCache as jest.Mock).mockResolvedValue(restoreKey); + jest.mocked(cache.restoreCache).mockResolvedValue(restoreKey); await restoreImpl(new StateProvider()); @@ -307,7 +315,7 @@ test("restore with lookup-only set", async () => { lookupOnly: true }); - (cache.restoreCache as jest.Mock).mockResolvedValue(key); + jest.mocked(cache.restoreCache).mockResolvedValue(key); await restoreImpl(new StateProvider()); diff --git a/__tests__/saveImpl.test.ts b/__tests__/saveImpl.test.ts index c777077..c61b22e 100644 --- a/__tests__/saveImpl.test.ts +++ b/__tests__/saveImpl.test.ts @@ -101,11 +101,19 @@ test("save without AC available should no-op", async () => { }); test("save on ghes without AC available should no-op", async () => { + process.env["GITHUB_SERVER_URL"] = "https://my-ghes-server.com"; (cache.isFeatureAvailable as jest.Mock).mockReturnValue(false); await saveImpl(new StateProvider()); expect(cache.saveCache).toHaveBeenCalledTimes(0); + expect(core.info).toHaveBeenCalledWith( + expect.stringContaining( + "Cache action is only supported on GHES version >= 3.5" + ) + ); + + delete process.env["GITHUB_SERVER_URL"]; }); test("save on GHES with AC available", async () => { @@ -159,8 +167,8 @@ test("save with missing input outputs warning", async () => { const savedCacheKey = "Linux-node-"; (core.getState as jest.Mock) - .mockReturnValueOnce(savedCacheKey) - .mockReturnValueOnce(primaryKey); + .mockReturnValueOnce(primaryKey) + .mockReturnValueOnce(savedCacheKey); await saveImpl(new StateProvider()); diff --git a/package.json b/package.json index 88408e2..498ad69 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "main": "dist/restore/index.js", "scripts": { "build": "tsc && ncc build -o dist/restore src/restore.ts && ncc build -o dist/save src/save.ts && ncc build -o dist/restore-only src/restoreOnly.ts && ncc build -o dist/save-only src/saveOnly.ts", - "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage", + "test": "tsc --noEmit && node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage", "lint": "eslint **/*.ts --cache", "format": "prettier --write **/*.ts", "format-check": "prettier --check **/*.ts"