mirror of
				https://github.com/actions/cache.git
				synced 2025-11-04 03:04:01 +00:00 
			
		
		
		
	Add read-only feature
When `read-only` is `true`, the cache is only restored and not saved. This allows for sharing the cache with multiple steps even if these steps may change them, and speeds them up regardless.
This commit is contained in:
		
							parent
							
								
									9c77c9dbfc
								
							
						
					
					
						commit
						b917253c33
					
				@ -308,3 +308,35 @@ test("restore with cache found for restore key", async () => {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
					    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test("restore with read-only with cache found for key", async () => {
 | 
				
			||||||
 | 
					    const path = "node_modules";
 | 
				
			||||||
 | 
					    const key = "node-test";
 | 
				
			||||||
 | 
					    testUtils.setInputs({
 | 
				
			||||||
 | 
					        path: path,
 | 
				
			||||||
 | 
					        key,
 | 
				
			||||||
 | 
					        readOnly: true
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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(key);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(restoreCacheMock).toHaveBeenCalledTimes(1);
 | 
				
			||||||
 | 
					    expect(restoreCacheMock).toHaveBeenCalledWith([path], key, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
 | 
				
			||||||
 | 
					    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
 | 
				
			||||||
 | 
					    expect(setCacheHitOutputMock).toHaveBeenCalledWith(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
 | 
				
			||||||
 | 
					    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -35,6 +35,14 @@ beforeAll(() => {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    jest.spyOn(actionUtils, "getInputAsBoolean").mockImplementation(
 | 
				
			||||||
 | 
					        (name, options) => {
 | 
				
			||||||
 | 
					            return jest
 | 
				
			||||||
 | 
					                .requireActual("../src/utils/actionUtils")
 | 
				
			||||||
 | 
					                .getInputAsBoolean(name, options);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
 | 
					    jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
 | 
				
			||||||
        (key, cacheResult) => {
 | 
					        (key, cacheResult) => {
 | 
				
			||||||
            return jest
 | 
					            return jest
 | 
				
			||||||
@ -338,3 +346,32 @@ test("save with valid inputs uploads a cache", async () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
					    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test("save with read-only does not upload cache", async () => {
 | 
				
			||||||
 | 
					    const infoMock = jest.spyOn(core, "info");
 | 
				
			||||||
 | 
					    const failedMock = jest.spyOn(core, "setFailed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
				
			||||||
 | 
					    const savedCacheKey = primaryKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    jest.spyOn(core, "getState")
 | 
				
			||||||
 | 
					        // Cache Entry State
 | 
				
			||||||
 | 
					        .mockImplementationOnce(() => {
 | 
				
			||||||
 | 
					            return savedCacheKey;
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        // Cache Key State
 | 
				
			||||||
 | 
					        .mockImplementationOnce(() => {
 | 
				
			||||||
 | 
					            return primaryKey;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    const saveCacheMock = jest.spyOn(cache, "saveCache");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    testUtils.setInput(Inputs.ReadOnly, "true");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(saveCacheMock).toHaveBeenCalledTimes(0);
 | 
				
			||||||
 | 
					    expect(infoMock).toHaveBeenCalledWith(
 | 
				
			||||||
 | 
					        "Cache running in read-only mode, not saving cache."
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,9 @@ inputs:
 | 
				
			|||||||
  upload-chunk-size:
 | 
					  upload-chunk-size:
 | 
				
			||||||
    description: 'The chunk size used to split up large files during upload, in bytes'
 | 
					    description: 'The chunk size used to split up large files during upload, in bytes'
 | 
				
			||||||
    required: false
 | 
					    required: false
 | 
				
			||||||
 | 
					  read-only:
 | 
				
			||||||
 | 
					    description: 'Set to true to never save the cache'
 | 
				
			||||||
 | 
					    required: false
 | 
				
			||||||
outputs:
 | 
					outputs:
 | 
				
			||||||
  cache-hit:
 | 
					  cache-hit:
 | 
				
			||||||
    description: 'A boolean value to indicate an exact match was found for the primary key'
 | 
					    description: 'A boolean value to indicate an exact match was found for the primary key'
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2327
									
								
								dist/restore/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2327
									
								
								dist/restore/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2331
									
								
								dist/save/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2331
									
								
								dist/save/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -2,7 +2,8 @@ export enum Inputs {
 | 
				
			|||||||
    Key = "key",
 | 
					    Key = "key",
 | 
				
			||||||
    Path = "path",
 | 
					    Path = "path",
 | 
				
			||||||
    RestoreKeys = "restore-keys",
 | 
					    RestoreKeys = "restore-keys",
 | 
				
			||||||
    UploadChunkSize = "upload-chunk-size"
 | 
					    UploadChunkSize = "upload-chunk-size",
 | 
				
			||||||
 | 
					    ReadOnly = "read-only"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export enum Outputs {
 | 
					export enum Outputs {
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,11 @@ async function run(): Promise<void> {
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (utils.getInputAsBoolean(Inputs.ReadOnly)) {
 | 
				
			||||||
 | 
					            core.info("Cache running in read-only mode, not saving cache.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!utils.isValidEvent()) {
 | 
					        if (!utils.isValidEvent()) {
 | 
				
			||||||
            utils.logWarning(
 | 
					            utils.logWarning(
 | 
				
			||||||
                `Event Validation Error: The event type ${
 | 
					                `Event Validation Error: The event type ${
 | 
				
			||||||
 | 
				
			|||||||
@ -74,3 +74,10 @@ export function getInputAsInt(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    return value;
 | 
					    return value;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getInputAsBoolean(
 | 
				
			||||||
 | 
					    name: string,
 | 
				
			||||||
 | 
					    options?: core.InputOptions
 | 
				
			||||||
 | 
					): boolean {
 | 
				
			||||||
 | 
					    return core.getInput(name, options) === "true";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,7 @@ interface CacheInput {
 | 
				
			|||||||
    path: string;
 | 
					    path: string;
 | 
				
			||||||
    key: string;
 | 
					    key: string;
 | 
				
			||||||
    restoreKeys?: string[];
 | 
					    restoreKeys?: string[];
 | 
				
			||||||
 | 
					    readOnly?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function setInputs(input: CacheInput): void {
 | 
					export function setInputs(input: CacheInput): void {
 | 
				
			||||||
@ -20,6 +21,7 @@ export function setInputs(input: CacheInput): void {
 | 
				
			|||||||
    setInput(Inputs.Key, input.key);
 | 
					    setInput(Inputs.Key, input.key);
 | 
				
			||||||
    input.restoreKeys &&
 | 
					    input.restoreKeys &&
 | 
				
			||||||
        setInput(Inputs.RestoreKeys, input.restoreKeys.join("\n"));
 | 
					        setInput(Inputs.RestoreKeys, input.restoreKeys.join("\n"));
 | 
				
			||||||
 | 
					    setInput(Inputs.ReadOnly, input.readOnly ? "true" : "false");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function clearInputs(): void {
 | 
					export function clearInputs(): void {
 | 
				
			||||||
@ -27,4 +29,5 @@ export function clearInputs(): void {
 | 
				
			|||||||
    delete process.env[getInputName(Inputs.Key)];
 | 
					    delete process.env[getInputName(Inputs.Key)];
 | 
				
			||||||
    delete process.env[getInputName(Inputs.RestoreKeys)];
 | 
					    delete process.env[getInputName(Inputs.RestoreKeys)];
 | 
				
			||||||
    delete process.env[getInputName(Inputs.UploadChunkSize)];
 | 
					    delete process.env[getInputName(Inputs.UploadChunkSize)];
 | 
				
			||||||
 | 
					    delete process.env[getInputName(Inputs.ReadOnly)];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user