2020-05-14 21:27:38 +00:00
import * as cache from "@actions/cache" ;
2019-11-06 18:41:45 +00:00
import * as core from "@actions/core" ;
2020-05-14 21:27:38 +00:00
import { Events , Inputs , RefKey } from "../src/constants" ;
2019-11-06 18:41:45 +00:00
import run from "../src/restore" ;
import * as actionUtils from "../src/utils/actionUtils" ;
import * as testUtils from "../src/utils/testUtils" ;
2019-12-13 22:24:37 +00:00
jest . mock ( "../src/utils/actionUtils" ) ;
2019-11-06 18:41:45 +00:00
beforeAll ( ( ) = > {
jest . spyOn ( actionUtils , "isExactKeyMatch" ) . mockImplementation (
( key , cacheResult ) = > {
const actualUtils = jest . requireActual ( "../src/utils/actionUtils" ) ;
return actualUtils . isExactKeyMatch ( key , cacheResult ) ;
}
) ;
2019-11-13 15:54:39 +00:00
jest . spyOn ( actionUtils , "isValidEvent" ) . mockImplementation ( ( ) = > {
const actualUtils = jest . requireActual ( "../src/utils/actionUtils" ) ;
return actualUtils . isValidEvent ( ) ;
} ) ;
2020-06-02 15:21:03 +00:00
jest . spyOn ( actionUtils , "getInputAsArray" ) . mockImplementation (
( name , options ) = > {
const actualUtils = jest . requireActual ( "../src/utils/actionUtils" ) ;
return actualUtils . getInputAsArray ( name , options ) ;
}
) ;
2019-11-06 18:41:45 +00:00
} ) ;
2019-11-13 15:54:39 +00:00
beforeEach ( ( ) = > {
process . env [ Events . Key ] = Events . Push ;
2020-04-17 19:46:46 +00:00
process . env [ RefKey ] = "refs/heads/feature-branch" ;
2020-09-29 15:23:21 +00:00
jest . spyOn ( actionUtils , "isGhes" ) . mockImplementation ( ( ) = > false ) ;
2022-03-23 13:09:24 +00:00
jest . spyOn ( cache , "isAvailable" ) . mockImplementation ( ( ) = > true ) ;
2019-11-13 15:54:39 +00:00
} ) ;
2019-11-06 18:41:45 +00:00
afterEach ( ( ) = > {
testUtils . clearInputs ( ) ;
2019-11-13 15:54:39 +00:00
delete process . env [ Events . Key ] ;
2020-04-17 19:46:46 +00:00
delete process . env [ RefKey ] ;
2019-11-13 15:54:39 +00:00
} ) ;
2019-11-21 19:37:54 +00:00
test ( "restore with invalid event outputs warning" , async ( ) = > {
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" ) ;
2019-11-13 15:54:39 +00:00
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const invalidEvent = "commit_comment" ;
process . env [ Events . Key ] = invalidEvent ;
2020-04-17 19:46:46 +00:00
delete process . env [ RefKey ] ;
2019-11-13 15:54:39 +00:00
await run ( ) ;
2019-11-21 19:37:54 +00:00
expect ( logWarningMock ) . toHaveBeenCalledWith (
2020-04-17 19:46:46 +00:00
` Event Validation Error: The event type ${ invalidEvent } is not supported because it's not tied to a branch or tag ref. `
2019-11-13 15:54:39 +00:00
) ;
2019-11-21 19:37:54 +00:00
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
2019-11-06 18:41:45 +00:00
} ) ;
2022-03-23 13:09:24 +00:00
test ( "restore without AC available should no-op" , async ( ) = > {
jest . spyOn ( actionUtils , "isGhes" ) . mockImplementation ( ( ) = > false ) ;
jest . spyOn ( cache , "isAvailable" ) . mockImplementation ( ( ) = > false ) ;
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" ) ;
const restoreCacheMock = jest . spyOn ( cache , "restoreCache" ) ;
const setCacheHitOutputMock = jest . spyOn ( actionUtils , "setCacheHitOutput" ) ;
await run ( ) ;
expect ( restoreCacheMock ) . toHaveBeenCalledTimes ( 0 ) ;
expect ( setCacheHitOutputMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( setCacheHitOutputMock ) . toHaveBeenCalledWith ( false ) ;
expect ( logWarningMock ) . toHaveBeenCalledWith (
"Something is going wrong with ArtifactCache service which supports cache actions. Please check https://www.githubstatus.com/ for any ongoing issue in actions."
) ;
} ) ;
test ( "restore on GHES without AC available should no-op" , async ( ) = > {
2020-09-29 15:23:21 +00:00
jest . spyOn ( actionUtils , "isGhes" ) . mockImplementation ( ( ) = > true ) ;
2022-03-23 13:09:24 +00:00
jest . spyOn ( cache , "isAvailable" ) . mockImplementation ( ( ) = > false ) ;
2020-09-29 14:58:32 +00:00
2020-09-30 13:47:16 +00:00
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" ) ;
2020-09-29 15:23:21 +00:00
const restoreCacheMock = jest . spyOn ( cache , "restoreCache" ) ;
const setCacheHitOutputMock = jest . spyOn ( actionUtils , "setCacheHitOutput" ) ;
2020-09-29 14:58:32 +00:00
2020-09-29 15:23:21 +00:00
await run ( ) ;
2020-09-29 14:58:32 +00:00
2020-09-29 15:23:21 +00:00
expect ( restoreCacheMock ) . toHaveBeenCalledTimes ( 0 ) ;
expect ( setCacheHitOutputMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( setCacheHitOutputMock ) . toHaveBeenCalledWith ( false ) ;
2020-09-30 13:47:16 +00:00
expect ( logWarningMock ) . toHaveBeenCalledWith (
2022-03-23 13:09:24 +00:00
"Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if ArtifactCache service is enabled or not."
2020-09-29 15:23:21 +00:00
) ;
2020-09-29 14:58:32 +00:00
} ) ;
2022-03-23 13:09:24 +00:00
test ( "restore on GHES with AC available " , async ( ) = > {
jest . spyOn ( actionUtils , "isGhes" ) . mockImplementation ( ( ) = > true ) ;
const path = "node_modules" ;
const key = "node-test" ;
testUtils . setInputs ( {
path : path ,
key
} ) ;
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 ) ;
} ) ;
2019-11-06 18:41:45 +00:00
test ( "restore with no path should fail" , async ( ) = > {
const failedMock = jest . spyOn ( core , "setFailed" ) ;
2020-05-14 21:27:38 +00:00
const restoreCacheMock = jest . spyOn ( cache , "restoreCache" ) ;
2019-11-06 18:41:45 +00:00
await run ( ) ;
2020-05-14 21:27:38 +00:00
expect ( restoreCacheMock ) . toHaveBeenCalledTimes ( 0 ) ;
2020-03-20 20:02:11 +00:00
// this input isn't necessary for restore b/c tarball contains entries relative to workspace
expect ( failedMock ) . not . toHaveBeenCalledWith (
2019-11-06 18:41:45 +00:00
"Input required and not supplied: path"
) ;
} ) ;
test ( "restore with no key" , async ( ) = > {
testUtils . setInput ( Inputs . Path , "node_modules" ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
2020-05-14 21:27:38 +00:00
const restoreCacheMock = jest . spyOn ( cache , "restoreCache" ) ;
2019-11-06 18:41:45 +00:00
await run ( ) ;
2020-05-14 21:27:38 +00:00
expect ( restoreCacheMock ) . toHaveBeenCalledTimes ( 0 ) ;
2019-11-06 18:41:45 +00:00
expect ( failedMock ) . toHaveBeenCalledWith (
"Input required and not supplied: key"
) ;
} ) ;
test ( "restore with too many keys should fail" , async ( ) = > {
2020-05-14 21:27:38 +00:00
const path = "node_modules" ;
2019-11-06 18:41:45 +00:00
const key = "node-test" ;
const restoreKeys = [ . . . Array ( 20 ) . keys ( ) ] . map ( x = > x . toString ( ) ) ;
testUtils . setInputs ( {
2020-05-14 21:27:38 +00:00
path : path ,
2019-11-06 18:41:45 +00:00
key ,
restoreKeys
} ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
2020-05-14 21:27:38 +00:00
const restoreCacheMock = jest . spyOn ( cache , "restoreCache" ) ;
2019-11-06 18:41:45 +00:00
await run ( ) ;
2020-05-14 21:27:38 +00:00
expect ( restoreCacheMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( restoreCacheMock ) . toHaveBeenCalledWith ( [ path ] , key , restoreKeys ) ;
2019-11-06 18:41:45 +00:00
expect ( failedMock ) . toHaveBeenCalledWith (
` Key Validation Error: Keys are limited to a maximum of 10. `
) ;
} ) ;
test ( "restore with large key should fail" , async ( ) = > {
2020-05-14 21:27:38 +00:00
const path = "node_modules" ;
2019-11-06 18:41:45 +00:00
const key = "foo" . repeat ( 512 ) ; // Over the 512 character limit
testUtils . setInputs ( {
2020-05-14 21:27:38 +00:00
path : path ,
2019-11-06 18:41:45 +00:00
key
} ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
2020-05-14 21:27:38 +00:00
const restoreCacheMock = jest . spyOn ( cache , "restoreCache" ) ;
2019-11-06 18:41:45 +00:00
await run ( ) ;
2020-05-14 21:27:38 +00:00
expect ( restoreCacheMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( restoreCacheMock ) . toHaveBeenCalledWith ( [ path ] , key , [ ] ) ;
2019-11-06 18:41:45 +00:00
expect ( failedMock ) . toHaveBeenCalledWith (
` Key Validation Error: ${ key } cannot be larger than 512 characters. `
) ;
} ) ;
test ( "restore with invalid key should fail" , async ( ) = > {
2020-05-14 21:27:38 +00:00
const path = "node_modules" ;
2019-11-06 18:41:45 +00:00
const key = "comma,comma" ;
testUtils . setInputs ( {
2020-05-14 21:27:38 +00:00
path : path ,
2019-11-06 18:41:45 +00:00
key
} ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
2020-05-14 21:27:38 +00:00
const restoreCacheMock = jest . spyOn ( cache , "restoreCache" ) ;
2019-11-06 18:41:45 +00:00
await run ( ) ;
2020-05-14 21:27:38 +00:00
expect ( restoreCacheMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( restoreCacheMock ) . toHaveBeenCalledWith ( [ path ] , key , [ ] ) ;
2019-11-06 18:41:45 +00:00
expect ( failedMock ) . toHaveBeenCalledWith (
` Key Validation Error: ${ key } cannot contain commas. `
) ;
} ) ;
test ( "restore with no cache found" , async ( ) = > {
2020-05-14 21:27:38 +00:00
const path = "node_modules" ;
2019-11-06 18:41:45 +00:00
const key = "node-test" ;
testUtils . setInputs ( {
2020-05-14 21:27:38 +00:00
path : path ,
2019-11-06 18:41:45 +00:00
key
} ) ;
const infoMock = jest . spyOn ( core , "info" ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const stateMock = jest . spyOn ( core , "saveState" ) ;
2020-05-14 21:27:38 +00:00
const restoreCacheMock = jest
. spyOn ( cache , "restoreCache" )
. mockImplementationOnce ( ( ) = > {
return Promise . resolve ( undefined ) ;
} ) ;
2019-11-06 18:41:45 +00:00
await run ( ) ;
2020-05-14 21:27:38 +00:00
expect ( restoreCacheMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( restoreCacheMock ) . toHaveBeenCalledWith ( [ path ] , key , [ ] ) ;
2019-11-06 18:41:45 +00:00
expect ( stateMock ) . toHaveBeenCalledWith ( "CACHE_KEY" , key ) ;
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
expect ( infoMock ) . toHaveBeenCalledWith (
2020-02-25 19:16:36 +00:00
` Cache not found for input keys: ${ key } `
2019-11-06 18:41:45 +00:00
) ;
} ) ;
test ( "restore with server error should fail" , async ( ) = > {
2020-05-14 21:27:38 +00:00
const path = "node_modules" ;
2019-11-06 18:41:45 +00:00
const key = "node-test" ;
testUtils . setInputs ( {
2020-05-14 21:27:38 +00:00
path : path ,
2019-11-06 18:41:45 +00:00
key
} ) ;
2019-11-21 19:37:54 +00:00
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" ) ;
2019-11-06 18:41:45 +00:00
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const stateMock = jest . spyOn ( core , "saveState" ) ;
2020-05-14 21:27:38 +00:00
const restoreCacheMock = jest
. spyOn ( cache , "restoreCache" )
. mockImplementationOnce ( ( ) = > {
throw new Error ( "HTTP Error Occurred" ) ;
} ) ;
2019-11-06 18:41:45 +00:00
const setCacheHitOutputMock = jest . spyOn ( actionUtils , "setCacheHitOutput" ) ;
await run ( ) ;
2020-05-14 21:27:38 +00:00
expect ( restoreCacheMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( restoreCacheMock ) . toHaveBeenCalledWith ( [ path ] , key , [ ] ) ;
2019-11-06 18:41:45 +00:00
expect ( stateMock ) . toHaveBeenCalledWith ( "CACHE_KEY" , key ) ;
2019-11-21 19:37:54 +00:00
expect ( logWarningMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( logWarningMock ) . toHaveBeenCalledWith ( "HTTP Error Occurred" ) ;
2019-11-06 18:41:45 +00:00
expect ( setCacheHitOutputMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( setCacheHitOutputMock ) . toHaveBeenCalledWith ( false ) ;
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
} ) ;
test ( "restore with restore keys and no cache found" , async ( ) = > {
2020-05-14 21:27:38 +00:00
const path = "node_modules" ;
2019-11-06 18:41:45 +00:00
const key = "node-test" ;
const restoreKey = "node-" ;
testUtils . setInputs ( {
2020-05-14 21:27:38 +00:00
path : path ,
2019-11-06 18:41:45 +00:00
key ,
restoreKeys : [ restoreKey ]
} ) ;
const infoMock = jest . spyOn ( core , "info" ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const stateMock = jest . spyOn ( core , "saveState" ) ;
2020-05-14 21:27:38 +00:00
const restoreCacheMock = jest
. spyOn ( cache , "restoreCache" )
. mockImplementationOnce ( ( ) = > {
return Promise . resolve ( undefined ) ;
} ) ;
2019-11-06 18:41:45 +00:00
await run ( ) ;
2020-05-14 21:27:38 +00:00
expect ( restoreCacheMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( restoreCacheMock ) . toHaveBeenCalledWith ( [ path ] , key , [ restoreKey ] ) ;
2019-11-06 18:41:45 +00:00
expect ( stateMock ) . toHaveBeenCalledWith ( "CACHE_KEY" , key ) ;
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
expect ( infoMock ) . toHaveBeenCalledWith (
2020-02-25 19:16:36 +00:00
` Cache not found for input keys: ${ key } , ${ restoreKey } `
2019-11-06 18:41:45 +00:00
) ;
} ) ;
2020-05-14 21:27:38 +00:00
test ( "restore with cache found for key" , async ( ) = > {
const path = "node_modules" ;
2019-11-06 18:41:45 +00:00
const key = "node-test" ;
testUtils . setInputs ( {
2020-05-14 21:27:38 +00:00
path : path ,
2019-11-06 18:41:45 +00:00
key
} ) ;
const infoMock = jest . spyOn ( core , "info" ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const stateMock = jest . spyOn ( core , "saveState" ) ;
const setCacheHitOutputMock = jest . spyOn ( actionUtils , "setCacheHitOutput" ) ;
2020-05-14 21:27:38 +00:00
const restoreCacheMock = jest
. spyOn ( cache , "restoreCache" )
. mockImplementationOnce ( ( ) = > {
return Promise . resolve ( key ) ;
} ) ;
2020-04-22 20:36:34 +00:00
2019-11-06 18:41:45 +00:00
await run ( ) ;
2020-05-14 21:27:38 +00:00
expect ( restoreCacheMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( restoreCacheMock ) . toHaveBeenCalledWith ( [ path ] , key , [ ] ) ;
2019-11-13 15:54:39 +00:00
expect ( stateMock ) . toHaveBeenCalledWith ( "CACHE_KEY" , key ) ;
2019-11-06 18:41:45 +00:00
expect ( setCacheHitOutputMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( setCacheHitOutputMock ) . toHaveBeenCalledWith ( true ) ;
expect ( infoMock ) . toHaveBeenCalledWith ( ` Cache restored from key: ${ key } ` ) ;
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
} ) ;
test ( "restore with cache found for restore key" , async ( ) = > {
2020-05-14 21:27:38 +00:00
const path = "node_modules" ;
2019-11-06 18:41:45 +00:00
const key = "node-test" ;
const restoreKey = "node-" ;
testUtils . setInputs ( {
2020-05-14 21:27:38 +00:00
path : path ,
2019-11-06 18:41:45 +00:00
key ,
restoreKeys : [ restoreKey ]
} ) ;
const infoMock = jest . spyOn ( core , "info" ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const stateMock = jest . spyOn ( core , "saveState" ) ;
const setCacheHitOutputMock = jest . spyOn ( actionUtils , "setCacheHitOutput" ) ;
2020-05-14 21:27:38 +00:00
const restoreCacheMock = jest
. spyOn ( cache , "restoreCache" )
. mockImplementationOnce ( ( ) = > {
return Promise . resolve ( restoreKey ) ;
} ) ;
2019-11-06 18:41:45 +00:00
await run ( ) ;
2020-05-14 21:27:38 +00:00
expect ( restoreCacheMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( restoreCacheMock ) . toHaveBeenCalledWith ( [ path ] , key , [ restoreKey ] ) ;
2019-11-06 18:41:45 +00:00
2020-05-14 21:27:38 +00:00
expect ( stateMock ) . toHaveBeenCalledWith ( "CACHE_KEY" , key ) ;
2019-11-06 18:41:45 +00:00
expect ( setCacheHitOutputMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( setCacheHitOutputMock ) . toHaveBeenCalledWith ( false ) ;
expect ( infoMock ) . toHaveBeenCalledWith (
` Cache restored from key: ${ restoreKey } `
) ;
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
} ) ;