mirror of
				https://gitea.com/actions/cache.git
				synced 2025-11-02 07:47:08 +00:00 
			
		
		
		
	Compare commits
	
		
			26 Commits
		
	
	
		
			bishal-pdM
			...
			tanuj077/c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					0685539942 | ||
| 
						 | 
					a92fb881ae | ||
| 
						 | 
					5f3ddebb2f | ||
| 
						 | 
					8a88690a20 | ||
| 
						 | 
					6e2c6a5916 | ||
| 
						 | 
					2c9fb32186 | ||
| 
						 | 
					01d96636a0 | ||
| 
						 | 
					9c5a42a7c9 | ||
| 
						 | 
					a172494938 | ||
| 
						 | 
					f8717682fb | ||
| 
						 | 
					af1210e2a3 | ||
| 
						 | 
					ab0e7714ce | ||
| 
						 | 
					fb4a5dce60 | ||
| 
						 | 
					71334c58b2 | ||
| 
						 | 
					888d454557 | ||
| 
						 | 
					dddd7ce07c | ||
| 
						 | 
					abddc4dd44 | ||
| 
						 | 
					921c58ee44 | ||
| 
						 | 
					7f45813c72 | ||
| 
						 | 
					0769f2e443 | ||
| 
						 | 
					5fe0b944ef | ||
| 
						 | 
					69b8227b27 | ||
| 
						 | 
					515d10b4fd | ||
| 
						 | 
					669e7536d9 | ||
| 
						 | 
					29dbbce762 | ||
| 
						 | 
					ea5981db97 | 
							
								
								
									
										14
									
								
								.devcontainer/devcontainer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								.devcontainer/devcontainer.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
{
 | 
			
		||||
	"name": "Node.js & TypeScript",
 | 
			
		||||
	"image": "mcr.microsoft.com/devcontainers/typescript-node:16-bullseye",
 | 
			
		||||
	// Features to add to the dev container. More info: https://containers.dev/implementors/features.
 | 
			
		||||
	// "features": {},
 | 
			
		||||
	// Use 'forwardPorts' to make a list of ports inside the container available locally.
 | 
			
		||||
	// "forwardPorts": [],
 | 
			
		||||
	// Use 'postCreateCommand' to run commands after the container is created.
 | 
			
		||||
	"postCreateCommand": "npm install && npm run build"
 | 
			
		||||
	// Configure tool-specific properties.
 | 
			
		||||
	// "customizations": {},
 | 
			
		||||
	// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
 | 
			
		||||
	// "remoteUser": "root"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								.github/workflows/check-dist.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/check-dist.yml
									
									
									
									
										vendored
									
									
								
							@@ -27,7 +27,6 @@ jobs:
 | 
			
		||||
        uses: actions/setup-node@v3
 | 
			
		||||
        with:
 | 
			
		||||
          node-version: 16.x
 | 
			
		||||
          cache: npm
 | 
			
		||||
      - name: Install dependencies
 | 
			
		||||
        run: npm ci
 | 
			
		||||
      - name: Rebuild the dist/ directory
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								.github/workflows/workflow.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/workflow.yml
									
									
									
									
										vendored
									
									
								
							@@ -25,7 +25,17 @@ jobs:
 | 
			
		||||
      uses: actions/setup-node@v3
 | 
			
		||||
      with:
 | 
			
		||||
        node-version: 16.x
 | 
			
		||||
        cache: npm
 | 
			
		||||
    - name: Determine npm cache directory
 | 
			
		||||
      id: npm-cache
 | 
			
		||||
      run: |
 | 
			
		||||
        echo "::set-output name=dir::$(npm config get cache)"
 | 
			
		||||
    - name: Restore npm cache
 | 
			
		||||
      uses: actions/cache@v3
 | 
			
		||||
      with:
 | 
			
		||||
        path: ${{ steps.npm-cache.outputs.dir }}
 | 
			
		||||
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
 | 
			
		||||
        restore-keys: |
 | 
			
		||||
          ${{ runner.os }}-node-
 | 
			
		||||
    - run: npm ci
 | 
			
		||||
    - name: Prettier Format Check
 | 
			
		||||
      run: npm run format-check
 | 
			
		||||
 
 | 
			
		||||
@@ -324,3 +324,113 @@ test("restore with cache found for restore key", async () => {
 | 
			
		||||
    );
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("restore with enabling save on any failure feature", async () => {
 | 
			
		||||
    const path = "node_modules";
 | 
			
		||||
    const key = "node-test";
 | 
			
		||||
    const restoreKey = "node-";
 | 
			
		||||
    testUtils.setInputs({
 | 
			
		||||
        path: path,
 | 
			
		||||
        key,
 | 
			
		||||
        restoreKeys: [restoreKey],
 | 
			
		||||
        saveOnAnyFailure: true
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const debugMock = jest.spyOn(core, "debug");
 | 
			
		||||
    const infoMock = jest.spyOn(core, "info");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
    const stateMock = jest.spyOn(core, "saveState");
 | 
			
		||||
    const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
 | 
			
		||||
    const restoreCacheMock = jest
 | 
			
		||||
        .spyOn(cache, "restoreCache")
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return Promise.resolve(restoreKey);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    expect(restoreCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [restoreKey]);
 | 
			
		||||
 | 
			
		||||
    expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
 | 
			
		||||
    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
 | 
			
		||||
 | 
			
		||||
    expect(debugMock).toHaveBeenCalledWith(
 | 
			
		||||
        `Exporting environment variable SAVE_CACHE_ON_ANY_FAILURE`
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    expect(infoMock).toHaveBeenCalledWith(
 | 
			
		||||
        `Input Variable SAVE_CACHE_ON_ANY_FAILURE is set to true, the cache will be saved despite of any failure in the build.`
 | 
			
		||||
    );
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("Fail restore when fail on cache miss is enabled and primary key not found", async () => {
 | 
			
		||||
    const path = "node_modules";
 | 
			
		||||
    const key = "node-test";
 | 
			
		||||
    const restoreKey = "node-";
 | 
			
		||||
    testUtils.setInputs({
 | 
			
		||||
        path: path,
 | 
			
		||||
        key,
 | 
			
		||||
        restoreKeys: [restoreKey],
 | 
			
		||||
        failOnCacheMiss: true
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
    const stateMock = jest.spyOn(core, "saveState");
 | 
			
		||||
    const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
 | 
			
		||||
    const restoreCacheMock = jest
 | 
			
		||||
        .spyOn(cache, "restoreCache")
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return Promise.resolve(undefined);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    expect(restoreCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [restoreKey]);
 | 
			
		||||
 | 
			
		||||
    expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
 | 
			
		||||
    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledWith(
 | 
			
		||||
        `Cache with the given input key ${key} is not found, hence exiting the workflow as the fail-on-cache-miss requirement is not met.`
 | 
			
		||||
    );
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("Fail restore when fail on cache miss is enabled and primary key doesn't match restored key", async () => {
 | 
			
		||||
    const path = "node_modules";
 | 
			
		||||
    const key = "node-test";
 | 
			
		||||
    const restoreKey = "node-";
 | 
			
		||||
    testUtils.setInputs({
 | 
			
		||||
        path: path,
 | 
			
		||||
        key,
 | 
			
		||||
        restoreKeys: [restoreKey],
 | 
			
		||||
        failOnCacheMiss: true
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
    const stateMock = jest.spyOn(core, "saveState");
 | 
			
		||||
    const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
 | 
			
		||||
    const restoreCacheMock = jest
 | 
			
		||||
        .spyOn(cache, "restoreCache")
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return Promise.resolve(restoreKey);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    expect(restoreCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [restoreKey]);
 | 
			
		||||
 | 
			
		||||
    expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
 | 
			
		||||
    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
 | 
			
		||||
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledWith(
 | 
			
		||||
        `Restored cache key doesn't match the given input key ${key}, hence exiting the workflow as the fail-on-cache-miss requirement is not met.`
 | 
			
		||||
    );
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										165
									
								
								__tests__/save-only.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								__tests__/save-only.test.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
import * as cache from "@actions/cache";
 | 
			
		||||
import * as core from "@actions/core";
 | 
			
		||||
 | 
			
		||||
import { Events, Inputs, RefKey } from "../src/constants";
 | 
			
		||||
import run from "../src/save-only";
 | 
			
		||||
import * as actionUtils from "../src/utils/actionUtils";
 | 
			
		||||
import * as testUtils from "../src/utils/testUtils";
 | 
			
		||||
 | 
			
		||||
jest.mock("@actions/core");
 | 
			
		||||
jest.mock("@actions/cache");
 | 
			
		||||
jest.mock("../src/utils/actionUtils");
 | 
			
		||||
 | 
			
		||||
beforeAll(() => {
 | 
			
		||||
    jest.spyOn(core, "getInput").mockImplementation((name, options) => {
 | 
			
		||||
        return jest.requireActual("@actions/core").getInput(name, options);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(actionUtils, "getCacheState").mockImplementation(() => {
 | 
			
		||||
        return jest.requireActual("../src/utils/actionUtils").getCacheState();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(actionUtils, "getInputAsArray").mockImplementation(
 | 
			
		||||
        (name, options) => {
 | 
			
		||||
            return jest
 | 
			
		||||
                .requireActual("../src/utils/actionUtils")
 | 
			
		||||
                .getInputAsArray(name, options);
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(actionUtils, "getInputAsInt").mockImplementation(
 | 
			
		||||
        (name, options) => {
 | 
			
		||||
            return jest
 | 
			
		||||
                .requireActual("../src/utils/actionUtils")
 | 
			
		||||
                .getInputAsInt(name, options);
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
 | 
			
		||||
        (key, cacheResult) => {
 | 
			
		||||
            return jest
 | 
			
		||||
                .requireActual("../src/utils/actionUtils")
 | 
			
		||||
                .isExactKeyMatch(key, cacheResult);
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(actionUtils, "isValidEvent").mockImplementation(() => {
 | 
			
		||||
        const actualUtils = jest.requireActual("../src/utils/actionUtils");
 | 
			
		||||
        return actualUtils.isValidEvent();
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
beforeEach(() => {
 | 
			
		||||
    process.env[Events.Key] = Events.Push;
 | 
			
		||||
    process.env[RefKey] = "refs/heads/feature-branch";
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
 | 
			
		||||
    jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
 | 
			
		||||
        () => true
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
afterEach(() => {
 | 
			
		||||
    testUtils.clearInputs();
 | 
			
		||||
    delete process.env[Events.Key];
 | 
			
		||||
    delete process.env[RefKey];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("save cache when save-only is required", async () => {
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
    const savedCacheKey = "Linux-node-";
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getInput")
 | 
			
		||||
        // Cache Entry State
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return savedCacheKey;
 | 
			
		||||
        })
 | 
			
		||||
        // Cache Key
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return primaryKey;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    const inputPath = "node_modules";
 | 
			
		||||
    testUtils.setInput(Inputs.Path, inputPath);
 | 
			
		||||
    testUtils.setInput(Inputs.UploadChunkSize, "4000000");
 | 
			
		||||
 | 
			
		||||
    const cacheId = 4;
 | 
			
		||||
    const saveCacheMock = jest
 | 
			
		||||
        .spyOn(cache, "saveCache")
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return Promise.resolve(cacheId);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledWith([inputPath], primaryKey, {
 | 
			
		||||
        uploadChunkSize: 4000000
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("save when save on any failure is true", async () => {
 | 
			
		||||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const savedCacheKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
    const primaryKey = "Linux-node-";
 | 
			
		||||
    const inputPath = "node_modules";
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getInput")
 | 
			
		||||
        // Cache Entry State
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return savedCacheKey;
 | 
			
		||||
        })
 | 
			
		||||
        // Cache Key
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return primaryKey;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    testUtils.setInput(Inputs.Path, inputPath);
 | 
			
		||||
    testUtils.setInput(Inputs.UploadChunkSize, "4000000");
 | 
			
		||||
    testUtils.setInput(Inputs.SaveOnAnyFailure, "true");
 | 
			
		||||
 | 
			
		||||
    const cacheId = 4;
 | 
			
		||||
    const saveCacheMock = jest
 | 
			
		||||
        .spyOn(cache, "saveCache")
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return Promise.resolve(cacheId);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("save with no primary key in input outputs warning", async () => {
 | 
			
		||||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const savedCacheKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
    jest.spyOn(core, "getState")
 | 
			
		||||
        // Cache Entry State
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return savedCacheKey;
 | 
			
		||||
        })
 | 
			
		||||
        // Cache Key
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return "";
 | 
			
		||||
        });
 | 
			
		||||
    const saveCacheMock = jest.spyOn(cache, "saveCache");
 | 
			
		||||
 | 
			
		||||
    await run();
 | 
			
		||||
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledWith(
 | 
			
		||||
        `Error retrieving key from inputs.`
 | 
			
		||||
    );
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										10
									
								
								action.yml
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								action.yml
									
									
									
									
									
								
							@@ -14,6 +14,14 @@ inputs:
 | 
			
		||||
  upload-chunk-size:
 | 
			
		||||
    description: 'The chunk size used to split up large files during upload, in bytes'
 | 
			
		||||
    required: false
 | 
			
		||||
  exit-on-cache-miss:
 | 
			
		||||
    description: 'Fail the workflow if the cache is not found for the primary key'
 | 
			
		||||
    required: false
 | 
			
		||||
    default: false
 | 
			
		||||
  save-on-any-failure:
 | 
			
		||||
    description: 'Save cache (on cache miss) despite of any failure during the workflow run'
 | 
			
		||||
    required: false
 | 
			
		||||
    default: false
 | 
			
		||||
outputs:
 | 
			
		||||
  cache-hit:
 | 
			
		||||
    description: 'A boolean value to indicate an exact match was found for the primary key'
 | 
			
		||||
@@ -21,7 +29,7 @@ runs:
 | 
			
		||||
  using: 'node16'
 | 
			
		||||
  main: 'dist/restore/index.js'
 | 
			
		||||
  post: 'dist/save/index.js'
 | 
			
		||||
  post-if: 'success()'
 | 
			
		||||
  post-if: (success() || (env.SAVE_CACHE_ON_ANY_FAILURE == 'yes'))
 | 
			
		||||
branding:
 | 
			
		||||
  icon: 'archive'
 | 
			
		||||
  color: 'gray-dark'
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								dist/restore/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								dist/restore/index.js
									
									
									
									
										vendored
									
									
								
							@@ -4964,13 +4964,15 @@ exports.checkBypass = checkBypass;
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
Object.defineProperty(exports, "__esModule", { value: true });
 | 
			
		||||
exports.RefKey = exports.Events = exports.State = exports.Outputs = exports.Inputs = void 0;
 | 
			
		||||
exports.RefKey = exports.Variables = exports.Events = exports.State = exports.Outputs = exports.Inputs = void 0;
 | 
			
		||||
var Inputs;
 | 
			
		||||
(function (Inputs) {
 | 
			
		||||
    Inputs["Key"] = "key";
 | 
			
		||||
    Inputs["Path"] = "path";
 | 
			
		||||
    Inputs["RestoreKeys"] = "restore-keys";
 | 
			
		||||
    Inputs["UploadChunkSize"] = "upload-chunk-size";
 | 
			
		||||
    Inputs["FailOnCacheMiss"] = "fail-on-cache-miss";
 | 
			
		||||
    Inputs["SaveOnAnyFailure"] = "save-on-any-failure";
 | 
			
		||||
})(Inputs = exports.Inputs || (exports.Inputs = {}));
 | 
			
		||||
var Outputs;
 | 
			
		||||
(function (Outputs) {
 | 
			
		||||
@@ -4987,6 +4989,10 @@ var Events;
 | 
			
		||||
    Events["Push"] = "push";
 | 
			
		||||
    Events["PullRequest"] = "pull_request";
 | 
			
		||||
})(Events = exports.Events || (exports.Events = {}));
 | 
			
		||||
var Variables;
 | 
			
		||||
(function (Variables) {
 | 
			
		||||
    Variables["SaveCacheOnAnyFailure"] = "SAVE_CACHE_ON_ANY_FAILURE";
 | 
			
		||||
})(Variables = exports.Variables || (exports.Variables = {}));
 | 
			
		||||
exports.RefKey = "GITHUB_REF";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -38489,16 +38495,17 @@ function getInputAsInt(name, options) {
 | 
			
		||||
}
 | 
			
		||||
exports.getInputAsInt = getInputAsInt;
 | 
			
		||||
function isCacheFeatureAvailable() {
 | 
			
		||||
    if (cache.isFeatureAvailable()) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    if (isGhes()) {
 | 
			
		||||
        logWarning(`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.
 | 
			
		||||
    if (!cache.isFeatureAvailable()) {
 | 
			
		||||
        if (isGhes()) {
 | 
			
		||||
            logWarning(`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)`);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            logWarning("An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions.");
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    logWarning("An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions.");
 | 
			
		||||
    return false;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
exports.isCacheFeatureAvailable = isCacheFeatureAvailable;
 | 
			
		||||
 | 
			
		||||
@@ -49007,7 +49014,17 @@ function run() {
 | 
			
		||||
                required: true
 | 
			
		||||
            });
 | 
			
		||||
            const cacheKey = yield cache.restoreCache(cachePaths, primaryKey, restoreKeys);
 | 
			
		||||
            //Check if user wants to save cache despite of failure in any previous job
 | 
			
		||||
            const saveCache = core.getBooleanInput(constants_1.Inputs.SaveOnAnyFailure);
 | 
			
		||||
            if (saveCache == true) {
 | 
			
		||||
                core.debug(`Exporting environment variable ${constants_1.Variables.SaveCacheOnAnyFailure}`);
 | 
			
		||||
                core.exportVariable(constants_1.Variables.SaveCacheOnAnyFailure, saveCache);
 | 
			
		||||
                core.info(`Input Variable ${constants_1.Variables.SaveCacheOnAnyFailure} is set to true, the cache will be saved despite of any failure in the build.`);
 | 
			
		||||
            }
 | 
			
		||||
            if (!cacheKey) {
 | 
			
		||||
                if (core.getBooleanInput(constants_1.Inputs.FailOnCacheMiss) == true) {
 | 
			
		||||
                    throw new Error(`Cache with the given input key ${primaryKey} is not found, hence exiting the workflow as the fail-on-cache-miss requirement is not met.`);
 | 
			
		||||
                }
 | 
			
		||||
                core.info(`Cache not found for input keys: ${[
 | 
			
		||||
                    primaryKey,
 | 
			
		||||
                    ...restoreKeys
 | 
			
		||||
@@ -49018,6 +49035,10 @@ function run() {
 | 
			
		||||
            utils.setCacheState(cacheKey);
 | 
			
		||||
            const isExactKeyMatch = utils.isExactKeyMatch(primaryKey, cacheKey);
 | 
			
		||||
            utils.setCacheHitOutput(isExactKeyMatch);
 | 
			
		||||
            if (!isExactKeyMatch &&
 | 
			
		||||
                core.getBooleanInput(constants_1.Inputs.FailOnCacheMiss) == true) {
 | 
			
		||||
                throw new Error(`Restored cache key doesn't match the given input key ${primaryKey}, hence exiting the workflow as the fail-on-cache-miss requirement is not met.`);
 | 
			
		||||
            }
 | 
			
		||||
            core.info(`Cache restored from key: ${cacheKey}`);
 | 
			
		||||
        }
 | 
			
		||||
        catch (error) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										61367
									
								
								dist/save-only/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61367
									
								
								dist/save-only/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										91
									
								
								dist/save/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										91
									
								
								dist/save/index.js
									
									
									
									
										vendored
									
									
								
							@@ -4964,13 +4964,15 @@ exports.checkBypass = checkBypass;
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
Object.defineProperty(exports, "__esModule", { value: true });
 | 
			
		||||
exports.RefKey = exports.Events = exports.State = exports.Outputs = exports.Inputs = void 0;
 | 
			
		||||
exports.RefKey = exports.Variables = exports.Events = exports.State = exports.Outputs = exports.Inputs = void 0;
 | 
			
		||||
var Inputs;
 | 
			
		||||
(function (Inputs) {
 | 
			
		||||
    Inputs["Key"] = "key";
 | 
			
		||||
    Inputs["Path"] = "path";
 | 
			
		||||
    Inputs["RestoreKeys"] = "restore-keys";
 | 
			
		||||
    Inputs["UploadChunkSize"] = "upload-chunk-size";
 | 
			
		||||
    Inputs["FailOnCacheMiss"] = "fail-on-cache-miss";
 | 
			
		||||
    Inputs["SaveOnAnyFailure"] = "save-on-any-failure";
 | 
			
		||||
})(Inputs = exports.Inputs || (exports.Inputs = {}));
 | 
			
		||||
var Outputs;
 | 
			
		||||
(function (Outputs) {
 | 
			
		||||
@@ -4987,6 +4989,10 @@ var Events;
 | 
			
		||||
    Events["Push"] = "push";
 | 
			
		||||
    Events["PullRequest"] = "pull_request";
 | 
			
		||||
})(Events = exports.Events || (exports.Events = {}));
 | 
			
		||||
var Variables;
 | 
			
		||||
(function (Variables) {
 | 
			
		||||
    Variables["SaveCacheOnAnyFailure"] = "SAVE_CACHE_ON_ANY_FAILURE";
 | 
			
		||||
})(Variables = exports.Variables || (exports.Variables = {}));
 | 
			
		||||
exports.RefKey = "GITHUB_REF";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -38489,16 +38495,17 @@ function getInputAsInt(name, options) {
 | 
			
		||||
}
 | 
			
		||||
exports.getInputAsInt = getInputAsInt;
 | 
			
		||||
function isCacheFeatureAvailable() {
 | 
			
		||||
    if (cache.isFeatureAvailable()) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    if (isGhes()) {
 | 
			
		||||
        logWarning(`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.
 | 
			
		||||
    if (!cache.isFeatureAvailable()) {
 | 
			
		||||
        if (isGhes()) {
 | 
			
		||||
            logWarning(`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)`);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            logWarning("An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions.");
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    logWarning("An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions.");
 | 
			
		||||
    return false;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
exports.isCacheFeatureAvailable = isCacheFeatureAvailable;
 | 
			
		||||
 | 
			
		||||
@@ -47304,6 +47311,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
 | 
			
		||||
const cache = __importStar(__webpack_require__(692));
 | 
			
		||||
const core = __importStar(__webpack_require__(470));
 | 
			
		||||
const constants_1 = __webpack_require__(196);
 | 
			
		||||
const save_only_1 = __webpack_require__(973);
 | 
			
		||||
const utils = __importStar(__webpack_require__(443));
 | 
			
		||||
// Catch and log any unhandled exceptions.  These exceptions can leak out of the uploadChunk method in
 | 
			
		||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
 | 
			
		||||
@@ -47321,7 +47329,9 @@ function run() {
 | 
			
		||||
            }
 | 
			
		||||
            const state = utils.getCacheState();
 | 
			
		||||
            // Inputs are re-evaluted before the post action, so we want the original key used for restore
 | 
			
		||||
            const primaryKey = core.getState(constants_1.State.CachePrimaryKey);
 | 
			
		||||
            const primaryKey = save_only_1.saveOnly === true
 | 
			
		||||
                ? core.getInput(constants_1.Inputs.Key)
 | 
			
		||||
                : core.getState(constants_1.State.CachePrimaryKey);
 | 
			
		||||
            if (!primaryKey) {
 | 
			
		||||
                utils.logWarning(`Error retrieving key from state.`);
 | 
			
		||||
                return;
 | 
			
		||||
@@ -47345,7 +47355,6 @@ function run() {
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
run();
 | 
			
		||||
exports.default = run;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -55215,7 +55224,67 @@ exports.safeTrimTrailingSeparator = safeTrimTrailingSeparator;
 | 
			
		||||
//# sourceMappingURL=internal-path-helper.js.map
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
/* 973 */,
 | 
			
		||||
/* 973 */
 | 
			
		||||
/***/ (function(__unusedmodule, exports, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
 | 
			
		||||
    if (k2 === undefined) k2 = k;
 | 
			
		||||
    var desc = Object.getOwnPropertyDescriptor(m, k);
 | 
			
		||||
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
 | 
			
		||||
      desc = { enumerable: true, get: function() { return m[k]; } };
 | 
			
		||||
    }
 | 
			
		||||
    Object.defineProperty(o, k2, desc);
 | 
			
		||||
}) : (function(o, m, k, k2) {
 | 
			
		||||
    if (k2 === undefined) k2 = k;
 | 
			
		||||
    o[k2] = m[k];
 | 
			
		||||
}));
 | 
			
		||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
 | 
			
		||||
    Object.defineProperty(o, "default", { enumerable: true, value: v });
 | 
			
		||||
}) : function(o, v) {
 | 
			
		||||
    o["default"] = v;
 | 
			
		||||
});
 | 
			
		||||
var __importStar = (this && this.__importStar) || function (mod) {
 | 
			
		||||
    if (mod && mod.__esModule) return mod;
 | 
			
		||||
    var result = {};
 | 
			
		||||
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
 | 
			
		||||
    __setModuleDefault(result, mod);
 | 
			
		||||
    return result;
 | 
			
		||||
};
 | 
			
		||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
 | 
			
		||||
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
 | 
			
		||||
    return new (P || (P = Promise))(function (resolve, reject) {
 | 
			
		||||
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
 | 
			
		||||
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
 | 
			
		||||
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
 | 
			
		||||
        step((generator = generator.apply(thisArg, _arguments || [])).next());
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
var __importDefault = (this && this.__importDefault) || function (mod) {
 | 
			
		||||
    return (mod && mod.__esModule) ? mod : { "default": mod };
 | 
			
		||||
};
 | 
			
		||||
Object.defineProperty(exports, "__esModule", { value: true });
 | 
			
		||||
exports.saveOnly = void 0;
 | 
			
		||||
const core = __importStar(__webpack_require__(470));
 | 
			
		||||
const constants_1 = __webpack_require__(196);
 | 
			
		||||
const save_1 = __importDefault(__webpack_require__(681));
 | 
			
		||||
const utils = __importStar(__webpack_require__(443));
 | 
			
		||||
function runSaveAction() {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
        if (!core.getInput(constants_1.Inputs.Key)) {
 | 
			
		||||
            utils.logWarning(`Error retrieving key from inputs.`);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        exports.saveOnly = true;
 | 
			
		||||
        yield (0, save_1.default)();
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
runSaveAction();
 | 
			
		||||
exports.default = runSaveAction;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
/* 974 */,
 | 
			
		||||
/* 975 */
 | 
			
		||||
/***/ (function(__unusedmodule, exports) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								examples.md
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								examples.md
									
									
									
									
									
								
							@@ -309,29 +309,14 @@ We cache the elements of the Cabal store separately, as the entirety of `~/.caba
 | 
			
		||||
For npm, cache files are stored in `~/.npm` on Posix, or `~\AppData\npm-cache` on Windows, but it's possible to use `npm config get cache` to find the path on any platform. See [the npm docs](https://docs.npmjs.com/cli/cache#cache) for more details.
 | 
			
		||||
 | 
			
		||||
If using `npm config` to retrieve the cache directory, ensure you run [actions/setup-node](https://github.com/actions/setup-node) first to ensure your `npm` version is correct.
 | 
			
		||||
After [deprecation](https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/) of save-state and set-output commands, the correct way to set output is using `${GITHUB_OUTPUT}`. For linux, we can use `${GITHUB_OUTPUT}` whereas for windows we need to use `${env:GITHUB_OUTPUT}` due to two different default shells in these two different OS ie `bash` and `pwsh` respectively.
 | 
			
		||||
 | 
			
		||||
>Note: It is not recommended to cache `node_modules`, as it can break across Node versions and won't work with `npm ci`
 | 
			
		||||
 | 
			
		||||
### **Get npm cache directory using same shell**
 | 
			
		||||
### Bash shell
 | 
			
		||||
```yaml
 | 
			
		||||
- name: Get npm cache directory
 | 
			
		||||
  id: npm-cache-dir
 | 
			
		||||
  shell: bash
 | 
			
		||||
  run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### PWSH shell
 | 
			
		||||
```yaml
 | 
			
		||||
- name: Get npm cache directory
 | 
			
		||||
  id: npm-cache-dir
 | 
			
		||||
  shell: pwsh
 | 
			
		||||
  run: echo "dir=$(npm config get cache)" >> ${env:GITHUB_OUTPUT}
 | 
			
		||||
```
 | 
			
		||||
`Get npm cache directory` step can then be used with `actions/cache` as shown below
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
  run: |
 | 
			
		||||
    echo "::set-output name=dir::$(npm config get cache)"
 | 
			
		||||
- uses: actions/cache@v3
 | 
			
		||||
  id: npm-cache # use this to check for `cache-hit` ==> if: steps.npm-cache.outputs.cache-hit != 'true'
 | 
			
		||||
  with:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6459
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6459
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										26
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								package.json
									
									
									
									
									
								
							@@ -5,7 +5,7 @@
 | 
			
		||||
  "description": "Cache dependencies and build outputs",
 | 
			
		||||
  "main": "dist/restore/index.js",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "tsc && ncc build -o dist/restore src/restore.ts && ncc build -o dist/save src/save.ts",
 | 
			
		||||
    "build": "tsc && ncc build -o dist/restore src/restore.ts && ncc build -o dist/save src/save.ts && ncc build -o dist/save-only src/save-only.ts",
 | 
			
		||||
    "test": "tsc --noEmit && jest --coverage",
 | 
			
		||||
    "lint": "eslint **/*.ts --cache",
 | 
			
		||||
    "format": "prettier --write **/*.ts",
 | 
			
		||||
@@ -29,23 +29,23 @@
 | 
			
		||||
    "@actions/io": "^1.1.2"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/jest": "^27.5.2",
 | 
			
		||||
    "@types/jest": "^27.5.0",
 | 
			
		||||
    "@types/nock": "^11.1.0",
 | 
			
		||||
    "@types/node": "^16.18.3",
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": "^5.45.0",
 | 
			
		||||
    "@typescript-eslint/parser": "^5.45.0",
 | 
			
		||||
    "@types/node": "^16.11.33",
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": "^5.22.0",
 | 
			
		||||
    "@typescript-eslint/parser": "^5.22.0",
 | 
			
		||||
    "@zeit/ncc": "^0.20.5",
 | 
			
		||||
    "eslint": "^8.28.0",
 | 
			
		||||
    "eslint": "^8.14.0",
 | 
			
		||||
    "eslint-config-prettier": "^8.5.0",
 | 
			
		||||
    "eslint-plugin-import": "^2.26.0",
 | 
			
		||||
    "eslint-plugin-jest": "^26.9.0",
 | 
			
		||||
    "eslint-plugin-prettier": "^4.2.1",
 | 
			
		||||
    "eslint-plugin-jest": "^26.1.5",
 | 
			
		||||
    "eslint-plugin-prettier": "^4.0.0",
 | 
			
		||||
    "eslint-plugin-simple-import-sort": "^7.0.0",
 | 
			
		||||
    "jest": "^28.1.3",
 | 
			
		||||
    "jest": "^28.0.3",
 | 
			
		||||
    "jest-circus": "^27.5.1",
 | 
			
		||||
    "nock": "^13.2.9",
 | 
			
		||||
    "prettier": "^2.8.0",
 | 
			
		||||
    "ts-jest": "^28.0.8",
 | 
			
		||||
    "typescript": "^4.9.3"
 | 
			
		||||
    "nock": "^13.2.4",
 | 
			
		||||
    "prettier": "^2.6.2",
 | 
			
		||||
    "ts-jest": "^28.0.2",
 | 
			
		||||
    "typescript": "^4.6.4"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								restore/action.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								restore/action.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
name: 'Restore Cache'
 | 
			
		||||
description: 'Restore Cache artifacts like dependencies and build outputs to improve workflow execution time'
 | 
			
		||||
author: 'GitHub'
 | 
			
		||||
inputs:
 | 
			
		||||
  path:
 | 
			
		||||
    description: 'A list of files, directories, and wildcard patterns to cache and restore'
 | 
			
		||||
    required: true
 | 
			
		||||
  key:
 | 
			
		||||
    description: 'An explicit key for restoring and saving the cache'
 | 
			
		||||
    required: true
 | 
			
		||||
  restore-keys:
 | 
			
		||||
    description: 'An ordered list of keys to use for restoring stale cache if no cache hit occurred for key. Note `cache-hit` returns false in this case.'
 | 
			
		||||
    required: false
 | 
			
		||||
  exit-on-cache-miss:
 | 
			
		||||
    description: 'Fail the workflow if the cache is not found for the primary key'
 | 
			
		||||
    required: false
 | 
			
		||||
    default: false
 | 
			
		||||
outputs:
 | 
			
		||||
  cache-hit:
 | 
			
		||||
    description: 'A boolean value to indicate an exact match was found for the primary key'
 | 
			
		||||
runs:
 | 
			
		||||
  using: 'node16'
 | 
			
		||||
  main: '../dist/restore/index.js'
 | 
			
		||||
branding:
 | 
			
		||||
  icon: 'archive'
 | 
			
		||||
  color: 'gray-dark'
 | 
			
		||||
  
 | 
			
		||||
							
								
								
									
										19
									
								
								save/action.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								save/action.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
name: 'Save Cache'
 | 
			
		||||
description: 'Save Cache artifacts like dependencies and build outputs to improve workflow execution time'
 | 
			
		||||
author: 'GitHub'
 | 
			
		||||
inputs:
 | 
			
		||||
  path:
 | 
			
		||||
    description: 'A list of files, directories, and wildcard patterns to cache and restore'
 | 
			
		||||
    required: true
 | 
			
		||||
  key:
 | 
			
		||||
    description: 'An explicit key for restoring and saving the cache'
 | 
			
		||||
    required: true
 | 
			
		||||
  upload-chunk-size:
 | 
			
		||||
    description: 'The chunk size used to split up large files during upload, in bytes'
 | 
			
		||||
    required: false
 | 
			
		||||
runs:
 | 
			
		||||
  using: 'node16'
 | 
			
		||||
  main: '../dist/save/index.js'
 | 
			
		||||
branding:
 | 
			
		||||
  icon: 'archive'
 | 
			
		||||
  color: 'gray-dark'
 | 
			
		||||
@@ -2,7 +2,9 @@ export enum Inputs {
 | 
			
		||||
    Key = "key",
 | 
			
		||||
    Path = "path",
 | 
			
		||||
    RestoreKeys = "restore-keys",
 | 
			
		||||
    UploadChunkSize = "upload-chunk-size"
 | 
			
		||||
    UploadChunkSize = "upload-chunk-size",
 | 
			
		||||
    FailOnCacheMiss = "fail-on-cache-miss",
 | 
			
		||||
    SaveOnAnyFailure = "save-on-any-failure"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum Outputs {
 | 
			
		||||
@@ -20,4 +22,8 @@ export enum Events {
 | 
			
		||||
    PullRequest = "pull_request"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum Variables {
 | 
			
		||||
    SaveCacheOnAnyFailure = "SAVE_CACHE_ON_ANY_FAILURE"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const RefKey = "GITHUB_REF";
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
import * as cache from "@actions/cache";
 | 
			
		||||
import * as core from "@actions/core";
 | 
			
		||||
 | 
			
		||||
import { Events, Inputs, State } from "./constants";
 | 
			
		||||
import { Events, Inputs, State, Variables } from "./constants";
 | 
			
		||||
import * as utils from "./utils/actionUtils";
 | 
			
		||||
 | 
			
		||||
async function run(): Promise<void> {
 | 
			
		||||
@@ -35,22 +35,46 @@ async function run(): Promise<void> {
 | 
			
		||||
            restoreKeys
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        //Check if user wants to save cache despite of failure in any previous job
 | 
			
		||||
        const saveCache = core.getBooleanInput(Inputs.SaveOnAnyFailure);
 | 
			
		||||
        if (saveCache == true) {
 | 
			
		||||
            core.debug(
 | 
			
		||||
                `Exporting environment variable ${Variables.SaveCacheOnAnyFailure}`
 | 
			
		||||
            );
 | 
			
		||||
            core.exportVariable(Variables.SaveCacheOnAnyFailure, saveCache);
 | 
			
		||||
            core.info(
 | 
			
		||||
                `Input Variable ${Variables.SaveCacheOnAnyFailure} is set to true, the cache will be saved despite of any failure in the build.`
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!cacheKey) {
 | 
			
		||||
            if (core.getBooleanInput(Inputs.FailOnCacheMiss) == true) {
 | 
			
		||||
                throw new Error(
 | 
			
		||||
                    `Cache with the given input key ${primaryKey} is not found, hence exiting the workflow as the fail-on-cache-miss requirement is not met.`
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
            core.info(
 | 
			
		||||
                `Cache not found for input keys: ${[
 | 
			
		||||
                    primaryKey,
 | 
			
		||||
                    ...restoreKeys
 | 
			
		||||
                ].join(", ")}`
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Store the matched cache key
 | 
			
		||||
        utils.setCacheState(cacheKey);
 | 
			
		||||
 | 
			
		||||
        const isExactKeyMatch = utils.isExactKeyMatch(primaryKey, cacheKey);
 | 
			
		||||
        utils.setCacheHitOutput(isExactKeyMatch);
 | 
			
		||||
 | 
			
		||||
        if (
 | 
			
		||||
            !isExactKeyMatch &&
 | 
			
		||||
            core.getBooleanInput(Inputs.FailOnCacheMiss) == true
 | 
			
		||||
        ) {
 | 
			
		||||
            throw new Error(
 | 
			
		||||
                `Restored cache key doesn't match the given input key ${primaryKey}, hence exiting the workflow as the fail-on-cache-miss requirement is not met.`
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        core.info(`Cache restored from key: ${cacheKey}`);
 | 
			
		||||
    } catch (error: unknown) {
 | 
			
		||||
        core.setFailed((error as Error).message);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								src/save-only.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/save-only.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
import * as core from "@actions/core";
 | 
			
		||||
 | 
			
		||||
import { Inputs } from "./constants";
 | 
			
		||||
import save from "./save";
 | 
			
		||||
import * as utils from "./utils/actionUtils";
 | 
			
		||||
 | 
			
		||||
async function runSaveAction(): Promise<void> {
 | 
			
		||||
    if (!core.getInput(Inputs.Key)) {
 | 
			
		||||
        utils.logWarning(`Error retrieving key from inputs.`);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    saveOnly = true;
 | 
			
		||||
 | 
			
		||||
    await save();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
runSaveAction();
 | 
			
		||||
 | 
			
		||||
export default runSaveAction;
 | 
			
		||||
export let saveOnly: boolean;
 | 
			
		||||
@@ -2,6 +2,7 @@ import * as cache from "@actions/cache";
 | 
			
		||||
import * as core from "@actions/core";
 | 
			
		||||
 | 
			
		||||
import { Events, Inputs, State } from "./constants";
 | 
			
		||||
import { saveOnly } from "./save-only";
 | 
			
		||||
import * as utils from "./utils/actionUtils";
 | 
			
		||||
 | 
			
		||||
// Catch and log any unhandled exceptions.  These exceptions can leak out of the uploadChunk method in
 | 
			
		||||
@@ -27,7 +28,11 @@ async function run(): Promise<void> {
 | 
			
		||||
        const state = utils.getCacheState();
 | 
			
		||||
 | 
			
		||||
        // Inputs are re-evaluted before the post action, so we want the original key used for restore
 | 
			
		||||
        const primaryKey = core.getState(State.CachePrimaryKey);
 | 
			
		||||
        const primaryKey =
 | 
			
		||||
            saveOnly === true
 | 
			
		||||
                ? core.getInput(Inputs.Key)
 | 
			
		||||
                : core.getState(State.CachePrimaryKey);
 | 
			
		||||
 | 
			
		||||
        if (!primaryKey) {
 | 
			
		||||
            utils.logWarning(`Error retrieving key from state.`);
 | 
			
		||||
            return;
 | 
			
		||||
@@ -56,6 +61,4 @@ async function run(): Promise<void> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
run();
 | 
			
		||||
 | 
			
		||||
export default run;
 | 
			
		||||
 
 | 
			
		||||
@@ -77,20 +77,19 @@ export function getInputAsInt(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isCacheFeatureAvailable(): boolean {
 | 
			
		||||
    if (cache.isFeatureAvailable()) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isGhes()) {
 | 
			
		||||
        logWarning(
 | 
			
		||||
            `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.
 | 
			
		||||
    if (!cache.isFeatureAvailable()) {
 | 
			
		||||
        if (isGhes()) {
 | 
			
		||||
            logWarning(
 | 
			
		||||
                `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)`
 | 
			
		||||
        );
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            logWarning(
 | 
			
		||||
                "An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions."
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    logWarning(
 | 
			
		||||
        "An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions."
 | 
			
		||||
    );
 | 
			
		||||
    return false;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,18 +13,28 @@ interface CacheInput {
 | 
			
		||||
    path: string;
 | 
			
		||||
    key: string;
 | 
			
		||||
    restoreKeys?: string[];
 | 
			
		||||
    failOnCacheMiss?: boolean;
 | 
			
		||||
    saveOnAnyFailure?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function setInputs(input: CacheInput): void {
 | 
			
		||||
    setInput(Inputs.Path, input.path);
 | 
			
		||||
    setInput(Inputs.Key, input.key);
 | 
			
		||||
    setInput(Inputs.SaveOnAnyFailure, "false");
 | 
			
		||||
    setInput(Inputs.FailOnCacheMiss, "false");
 | 
			
		||||
    input.restoreKeys &&
 | 
			
		||||
        setInput(Inputs.RestoreKeys, input.restoreKeys.join("\n"));
 | 
			
		||||
    input.failOnCacheMiss &&
 | 
			
		||||
        setInput(Inputs.FailOnCacheMiss, String(input.failOnCacheMiss));
 | 
			
		||||
    input.saveOnAnyFailure &&
 | 
			
		||||
        setInput(Inputs.SaveOnAnyFailure, String(input.saveOnAnyFailure));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function clearInputs(): void {
 | 
			
		||||
    delete process.env[getInputName(Inputs.Path)];
 | 
			
		||||
    delete process.env[getInputName(Inputs.Key)];
 | 
			
		||||
    delete process.env[getInputName(Inputs.RestoreKeys)];
 | 
			
		||||
    delete process.env[getInputName(Inputs.FailOnCacheMiss)];
 | 
			
		||||
    delete process.env[getInputName(Inputs.SaveOnAnyFailure)];
 | 
			
		||||
    delete process.env[getInputName(Inputs.UploadChunkSize)];
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ A cache today is immutable and cannot be updated. But some use cases require the
 | 
			
		||||
          restore-keys: |
 | 
			
		||||
            primes-${{ runner.os }}
 | 
			
		||||
  ```          
 | 
			
		||||
  Please note that this will create a new cache on every run and hence will consume the cache [quota](./README.md#cache-limits).
 | 
			
		||||
  Please note that this will create a new cache on every run and hence will consume the cache [quota](#cache-limits).
 | 
			
		||||
  
 | 
			
		||||
## Use cache across feature branches
 | 
			
		||||
Reusing cache across feature branches is not allowed today to provide cache [isolation](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache). However if both feature branches are from the default branch, a good way to achieve this is to ensure that the default branch has a cache. This cache will then be consumable by both feature branches.
 | 
			
		||||
@@ -80,4 +80,4 @@ jobs:
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
```
 | 
			
		||||
</details>
 | 
			
		||||
</details>
 | 
			
		||||
		Reference in New Issue
	
	Block a user