mirror of
				https://github.com/actions/cache.git
				synced 2025-11-04 07:38:37 +08:00 
			
		
		
		
	Allow refreshing cache also with granular save.
This commit is contained in:
		
							parent
							
								
									34ae092a8c
								
							
						
					
					
						commit
						d35302b225
					
				| 
						 | 
				
			
			@ -4,7 +4,7 @@ import nock from "nock";
 | 
			
		|||
 | 
			
		||||
import { Events, Inputs, RefKey } from "../src/constants";
 | 
			
		||||
import { saveImpl } from "../src/saveImpl";
 | 
			
		||||
import { StateProvider } from "../src/stateProvider";
 | 
			
		||||
import { NullStateProvider, StateProvider } from "../src/stateProvider";
 | 
			
		||||
import * as actionUtils from "../src/utils/actionUtils";
 | 
			
		||||
import * as testUtils from "../src/utils/testUtils";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -471,7 +471,80 @@ test("save with cache hit and refresh-cache will try to delete and re-create ent
 | 
			
		|||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return Promise.resolve(cacheId);
 | 
			
		||||
        });
 | 
			
		||||
    await run(new StateProvider());
 | 
			
		||||
    await saveImpl(new StateProvider());
 | 
			
		||||
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledWith(
 | 
			
		||||
        [inputPath],
 | 
			
		||||
        primaryKey,
 | 
			
		||||
        {
 | 
			
		||||
            uploadChunkSize: 4000000
 | 
			
		||||
        },
 | 
			
		||||
        false
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(infoMock).toHaveBeenCalledTimes(3);
 | 
			
		||||
 | 
			
		||||
    expect(infoMock).toHaveBeenNthCalledWith(
 | 
			
		||||
        1,
 | 
			
		||||
        `Cache hit occurred on the primary key ${primaryKey}, attempting to refresh the contents of the cache.`
 | 
			
		||||
    );
 | 
			
		||||
    expect(infoMock).toHaveBeenNthCalledWith(
 | 
			
		||||
        2,
 | 
			
		||||
        `Succesfully deleted cache with key: ${primaryKey}`
 | 
			
		||||
    );
 | 
			
		||||
    expect(infoMock).toHaveBeenNthCalledWith(
 | 
			
		||||
        3,
 | 
			
		||||
        `Cache saved with key: ${primaryKey}`
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("Granular save will use lookup to determine if cache needs to be updated or (not) saved.", async () => {
 | 
			
		||||
    process.env["GITHUB_REPOSITORY"] = "owner/repo";
 | 
			
		||||
    process.env["GITHUB_TOKEN"] =
 | 
			
		||||
        "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";
 | 
			
		||||
    process.env["GITHUB_ACTION"] = "__owner___run-repo";
 | 
			
		||||
 | 
			
		||||
    const infoMock = jest.spyOn(core, "info");
 | 
			
		||||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = testUtils.successCacheKey;
 | 
			
		||||
 | 
			
		||||
    const inputPath = "node_modules";
 | 
			
		||||
    testUtils.setInput(Inputs.Key, primaryKey);
 | 
			
		||||
    testUtils.setInput(Inputs.RefreshCache, "true");
 | 
			
		||||
    testUtils.setInput(Inputs.Path, inputPath);
 | 
			
		||||
    testUtils.setInput(Inputs.UploadChunkSize, "4000000");
 | 
			
		||||
 | 
			
		||||
    const restoreCacheMock = jest
 | 
			
		||||
        .spyOn(cache, "restoreCache")
 | 
			
		||||
        .mockImplementation(() => {
 | 
			
		||||
            return Promise.resolve(primaryKey);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    const cacheId = 4;
 | 
			
		||||
    const saveCacheMock = jest
 | 
			
		||||
        .spyOn(cache, "saveCache")
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return Promise.resolve(cacheId);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    await saveImpl(new NullStateProvider());
 | 
			
		||||
 | 
			
		||||
    expect(restoreCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(restoreCacheMock).toHaveBeenCalledWith(
 | 
			
		||||
        [inputPath],
 | 
			
		||||
        primaryKey,
 | 
			
		||||
        [],
 | 
			
		||||
        {
 | 
			
		||||
            lookupOnly: true
 | 
			
		||||
        },
 | 
			
		||||
        false
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledWith(
 | 
			
		||||
| 
						 | 
				
			
			@ -524,7 +597,7 @@ test("save with cache hit and refresh-cache will throw a warning if there's no G
 | 
			
		|||
        });
 | 
			
		||||
 | 
			
		||||
    const saveCacheMock = jest.spyOn(cache, "saveCache");
 | 
			
		||||
    await run(new StateProvider());
 | 
			
		||||
    await saveImpl(new StateProvider());
 | 
			
		||||
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledWith(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -111,6 +111,45 @@ test("save with valid inputs uploads a cache", async () => {
 | 
			
		|||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("Granular save with refreshCache is able to save cache", async () => {
 | 
			
		||||
    process.env["GITHUB_REPOSITORY"] = "owner/repo";
 | 
			
		||||
    process.env["GITHUB_TOKEN"] =
 | 
			
		||||
        "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";
 | 
			
		||||
    process.env["GITHUB_ACTION"] = "__owner___run-repo";
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
 | 
			
		||||
    const inputPath = "node_modules";
 | 
			
		||||
    process.env.CACHE_RESTORE_ONLY_MATCHED_KEY = primaryKey;
 | 
			
		||||
    testUtils.setInput(Inputs.Key, primaryKey);
 | 
			
		||||
    testUtils.setInput(Inputs.RefreshCache, "true");
 | 
			
		||||
    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 saveOnlyRun();
 | 
			
		||||
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledWith(
 | 
			
		||||
        [inputPath],
 | 
			
		||||
        primaryKey,
 | 
			
		||||
        {
 | 
			
		||||
            uploadChunkSize: 4000000
 | 
			
		||||
        },
 | 
			
		||||
        false
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("save failing logs the warning message", async () => {
 | 
			
		||||
    const warningMock = jest.spyOn(core, "warning");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								dist/save-only/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								dist/save-only/index.js
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -77561,8 +77561,16 @@ function saveImpl(stateProvider) {
 | 
			
		|||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            const refreshCache = utils.getInputAsBool(constants_1.Inputs.RefreshCache, { required: false });
 | 
			
		||||
            // If matched restore key is same as primary key, either try to refresh the cache, or just notify and do not save (NO-OP in case of SaveOnly action)
 | 
			
		||||
            const restoredKey = stateProvider.getCacheState();
 | 
			
		||||
            // If matched restore key is same as primary key, either try to refresh the cache, or just notify and do not save.
 | 
			
		||||
            let restoredKey = stateProvider.getCacheState();
 | 
			
		||||
            if (refreshCache && !restoredKey) {
 | 
			
		||||
                // If getCacheState didn't give us a key, we're likely using granular actions. Do a lookup to see if we need to refresh or just do a regular save.
 | 
			
		||||
                const cachePaths = utils.getInputAsArray(constants_1.Inputs.Path, {
 | 
			
		||||
                    required: true
 | 
			
		||||
                });
 | 
			
		||||
                const enableCrossOsArchive = utils.getInputAsBool(constants_1.Inputs.EnableCrossOsArchive);
 | 
			
		||||
                restoredKey = yield cache.restoreCache(cachePaths, primaryKey, [], { lookupOnly: true }, enableCrossOsArchive);
 | 
			
		||||
            }
 | 
			
		||||
            if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
 | 
			
		||||
                const { GITHUB_TOKEN, GITHUB_REPOSITORY } = process.env || null;
 | 
			
		||||
                if (GITHUB_TOKEN && GITHUB_REPOSITORY && refreshCache === true) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								dist/save/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								dist/save/index.js
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -77561,8 +77561,16 @@ function saveImpl(stateProvider) {
 | 
			
		|||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            const refreshCache = utils.getInputAsBool(constants_1.Inputs.RefreshCache, { required: false });
 | 
			
		||||
            // If matched restore key is same as primary key, either try to refresh the cache, or just notify and do not save (NO-OP in case of SaveOnly action)
 | 
			
		||||
            const restoredKey = stateProvider.getCacheState();
 | 
			
		||||
            // If matched restore key is same as primary key, either try to refresh the cache, or just notify and do not save.
 | 
			
		||||
            let restoredKey = stateProvider.getCacheState();
 | 
			
		||||
            if (refreshCache && !restoredKey) {
 | 
			
		||||
                // If getCacheState didn't give us a key, we're likely using granular actions. Do a lookup to see if we need to refresh or just do a regular save.
 | 
			
		||||
                const cachePaths = utils.getInputAsArray(constants_1.Inputs.Path, {
 | 
			
		||||
                    required: true
 | 
			
		||||
                });
 | 
			
		||||
                const enableCrossOsArchive = utils.getInputAsBool(constants_1.Inputs.EnableCrossOsArchive);
 | 
			
		||||
                restoredKey = yield cache.restoreCache(cachePaths, primaryKey, [], { lookupOnly: true }, enableCrossOsArchive);
 | 
			
		||||
            }
 | 
			
		||||
            if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
 | 
			
		||||
                const { GITHUB_TOKEN, GITHUB_REPOSITORY } = process.env || null;
 | 
			
		||||
                if (GITHUB_TOKEN && GITHUB_REPOSITORY && refreshCache === true) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,7 +82,6 @@ export async function restoreImpl(
 | 
			
		|||
        } else {
 | 
			
		||||
            core.info(`Cache restored from key: ${cacheKey}`);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return cacheKey;
 | 
			
		||||
    } catch (error: unknown) {
 | 
			
		||||
        core.setFailed((error as Error).message);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,10 +48,26 @@ export async function saveImpl(
 | 
			
		|||
            { required: false }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // If matched restore key is same as primary key, either try to refresh the cache, or just notify and do not save (NO-OP in case of SaveOnly action)
 | 
			
		||||
        // If matched restore key is same as primary key, either try to refresh the cache, or just notify and do not save.
 | 
			
		||||
 | 
			
		||||
        const restoredKey = stateProvider.getCacheState();
 | 
			
		||||
        let restoredKey = stateProvider.getCacheState();
 | 
			
		||||
 | 
			
		||||
        if (refreshCache && !restoredKey) {
 | 
			
		||||
            // If getCacheState didn't give us a key, we're likely using granular actions. Do a lookup to see if we need to refresh or just do a regular save.
 | 
			
		||||
            const cachePaths = utils.getInputAsArray(Inputs.Path, {
 | 
			
		||||
                required: true
 | 
			
		||||
            });
 | 
			
		||||
            const enableCrossOsArchive = utils.getInputAsBool(
 | 
			
		||||
                Inputs.EnableCrossOsArchive
 | 
			
		||||
            );
 | 
			
		||||
            restoredKey = await cache.restoreCache(
 | 
			
		||||
                cachePaths,
 | 
			
		||||
                primaryKey,
 | 
			
		||||
                [],
 | 
			
		||||
                { lookupOnly: true },
 | 
			
		||||
                enableCrossOsArchive
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
 | 
			
		||||
            const { GITHUB_TOKEN, GITHUB_REPOSITORY } = process.env || null;
 | 
			
		||||
            if (GITHUB_TOKEN && GITHUB_REPOSITORY && refreshCache === true) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user