2020-05-14 17:27:38 -04:00
import * as cache from "@actions/cache" ;
2019-11-14 17:14:16 -05:00
import * as core from "@actions/core" ;
2020-05-14 17:27:38 -04:00
import { Events , Inputs , RefKey } from "../src/constants" ;
2019-11-14 17:14:16 -05:00
import run from "../src/save" ;
import * as actionUtils from "../src/utils/actionUtils" ;
import * as testUtils from "../src/utils/testUtils" ;
jest . mock ( "@actions/core" );
2020-05-14 17:27:38 -04:00
jest . mock ( "@actions/cache" );
2019-12-13 17:24:37 -05:00
jest . mock ( "../src/utils/actionUtils" );
2019-11-14 17:14:16 -05:00
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 ();
});
2020-06-02 10:21:03 -05:00
jest . spyOn ( actionUtils , "getInputAsArray" ). mockImplementation (
( name , options ) => {
return jest
. requireActual ( "../src/utils/actionUtils" )
. getInputAsArray ( name , options );
}
);
2020-10-02 09:59:55 -05:00
jest . spyOn ( actionUtils , "getInputAsInt" ). mockImplementation (
( name , options ) => {
return jest
. requireActual ( "../src/utils/actionUtils" )
. getInputAsInt ( name , options );
}
);
2019-11-14 17:14:16 -05:00
jest . spyOn ( actionUtils , "isExactKeyMatch" ). mockImplementation (
( key , cacheResult ) => {
return jest
. requireActual ( "../src/utils/actionUtils" )
. isExactKeyMatch ( key , cacheResult );
}
);
2019-11-21 14:37:54 -05:00
jest . spyOn ( actionUtils , "isValidEvent" ). mockImplementation (() => {
const actualUtils = jest . requireActual ( "../src/utils/actionUtils" );
return actualUtils . isValidEvent ();
});
2019-11-14 17:14:16 -05:00
});
2019-11-21 14:37:54 -05:00
beforeEach (() => {
process . env [ Events . Key ] = Events . Push ;
2020-04-17 15:46:46 -04:00
process . env [ RefKey ] = "refs/heads/feature-branch" ;
2020-09-29 10:23:21 -05:00
jest . spyOn ( actionUtils , "isGhes" ). mockImplementation (() => false );
2022-03-23 18:39:24 +05:30
jest . spyOn ( cache , "isAvailable" ). mockImplementation (() => true );
2019-11-21 14:37:54 -05:00
});
2019-11-14 17:14:16 -05:00
afterEach (() => {
testUtils . clearInputs ();
2019-11-21 14:37:54 -05:00
delete process . env [ Events . Key ];
2020-04-17 15:46:46 -04:00
delete process . env [ RefKey ];
2019-11-21 14:37:54 -05:00
});
test ( "save with invalid event outputs warning" , async () => {
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" );
const failedMock = jest . spyOn ( core , "setFailed" );
const invalidEvent = "commit_comment" ;
process . env [ Events . Key ] = invalidEvent ;
2020-04-17 15:46:46 -04:00
delete process . env [ RefKey ];
2019-11-21 14:37:54 -05:00
await run ();
expect ( logWarningMock ). toHaveBeenCalledWith (
2020-04-17 15:46:46 -04:00
`Event Validation Error: The event type ${ invalidEvent } is not supported because it's not tied to a branch or tag ref.`
2019-11-21 14:37:54 -05:00
);
expect ( failedMock ). toHaveBeenCalledTimes ( 0 );
2019-11-14 17:14:16 -05:00
});
test ( "save with no primary key in state outputs warning" , async () => {
2019-11-21 14:37:54 -05:00
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" );
2019-11-14 17:14:16 -05:00
const failedMock = jest . spyOn ( core , "setFailed" );
2020-05-14 17:27:38 -04:00
const savedCacheKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43" ;
2019-11-14 17:14:16 -05:00
jest . spyOn ( core , "getState" )
// Cache Entry State
. mockImplementationOnce (() => {
2020-05-14 17:27:38 -04:00
return savedCacheKey ;
2019-11-14 17:14:16 -05:00
})
// Cache Key State
. mockImplementationOnce (() => {
return "" ;
});
2020-05-14 17:27:38 -04:00
const saveCacheMock = jest . spyOn ( cache , "saveCache" );
2019-11-14 17:14:16 -05:00
await run ();
2020-05-14 17:27:38 -04:00
expect ( saveCacheMock ). toHaveBeenCalledTimes ( 0 );
2019-11-21 14:37:54 -05:00
expect ( logWarningMock ). toHaveBeenCalledWith (
2019-11-14 17:14:16 -05:00
`Error retrieving key from state.`
);
2019-11-21 14:37:54 -05:00
expect ( logWarningMock ). toHaveBeenCalledTimes ( 1 );
2019-11-14 17:14:16 -05:00
expect ( failedMock ). toHaveBeenCalledTimes ( 0 );
});
2022-03-23 18:39:24 +05:30
test ( "save without AC available should no=op" , async () => {
jest . spyOn ( cache , "isAvailable" ). mockImplementation (() => false );
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" );
const saveCacheMock = jest . spyOn ( cache , "saveCache" );
await run ();
expect ( saveCacheMock ). toHaveBeenCalledTimes ( 0 );
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 ( "save on ghes without AC available should no=op" , async () => {
2020-09-29 10:23:21 -05:00
jest . spyOn ( actionUtils , "isGhes" ). mockImplementation (() => true );
2022-03-23 18:39:24 +05:30
jest . spyOn ( cache , "isAvailable" ). mockImplementation (() => false );
2020-09-29 09:58:32 -05:00
2020-09-30 08:47:16 -05:00
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" );
2020-09-29 10:23:21 -05:00
const saveCacheMock = jest . spyOn ( cache , "saveCache" );
2020-09-29 09:58:32 -05:00
2020-09-29 10:23:21 -05:00
await run ();
2020-09-29 09:58:32 -05:00
2020-09-29 10:23:21 -05:00
expect ( saveCacheMock ). toHaveBeenCalledTimes ( 0 );
2020-09-30 08:47:16 -05:00
expect ( logWarningMock ). toHaveBeenCalledWith (
2022-03-23 18:39:24 +05:30
"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 10:23:21 -05:00
);
2020-09-29 09:58:32 -05:00
});
2022-03-23 18:39:24 +05:30
test ( "save on GHES with AC available" , async () => {
jest . spyOn ( actionUtils , "isGhes" ). mockImplementation (() => true );
const failedMock = jest . spyOn ( core , "setFailed" );
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43" ;
const savedCacheKey = "Linux-node-" ;
jest . spyOn ( core , "getState" )
// Cache Entry State
. mockImplementationOnce (() => {
return savedCacheKey ;
})
// Cache Key State
. 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 );
});
2019-11-14 17:14:16 -05:00
test ( "save with exact match returns early" , async () => {
const infoMock = jest . spyOn ( core , "info" );
const failedMock = jest . spyOn ( core , "setFailed" );
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43" ;
2020-05-14 17:27:38 -04:00
const savedCacheKey = primaryKey ;
2019-11-14 17:14:16 -05:00
jest . spyOn ( core , "getState" )
// Cache Entry State
. mockImplementationOnce (() => {
2020-05-14 17:27:38 -04:00
return savedCacheKey ;
2019-11-14 17:14:16 -05:00
})
// Cache Key State
. mockImplementationOnce (() => {
return primaryKey ;
});
2020-05-14 17:27:38 -04:00
const saveCacheMock = jest . spyOn ( cache , "saveCache" );
2019-11-14 17:14:16 -05:00
await run ();
2020-05-14 17:27:38 -04:00
expect ( saveCacheMock ). toHaveBeenCalledTimes ( 0 );
2019-11-14 17:14:16 -05:00
expect ( infoMock ). toHaveBeenCalledWith (
`Cache hit occurred on the primary key ${ primaryKey } , not saving cache.`
);
expect ( failedMock ). toHaveBeenCalledTimes ( 0 );
});
test ( "save with missing input outputs warning" , async () => {
2019-11-21 14:37:54 -05:00
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" );
2019-11-14 17:14:16 -05:00
const failedMock = jest . spyOn ( core , "setFailed" );
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43" ;
2020-05-14 17:27:38 -04:00
const savedCacheKey = "Linux-node-" ;
2019-11-14 17:14:16 -05:00
jest . spyOn ( core , "getState" )
// Cache Entry State
. mockImplementationOnce (() => {
2020-05-14 17:27:38 -04:00
return savedCacheKey ;
2019-11-14 17:14:16 -05:00
})
// Cache Key State
. mockImplementationOnce (() => {
return primaryKey ;
});
2020-05-14 17:27:38 -04:00
const saveCacheMock = jest . spyOn ( cache , "saveCache" );
2019-11-14 17:14:16 -05:00
await run ();
2020-05-14 17:27:38 -04:00
expect ( saveCacheMock ). toHaveBeenCalledTimes ( 0 );
2019-11-21 14:37:54 -05:00
expect ( logWarningMock ). toHaveBeenCalledWith (
2019-11-14 17:14:16 -05:00
"Input required and not supplied: path"
);
2019-11-21 14:37:54 -05:00
expect ( logWarningMock ). toHaveBeenCalledTimes ( 1 );
2019-11-14 17:14:16 -05:00
expect ( failedMock ). toHaveBeenCalledTimes ( 0 );
});
test ( "save with large cache outputs warning" , async () => {
2019-11-21 14:37:54 -05:00
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" );
2019-11-14 17:14:16 -05:00
const failedMock = jest . spyOn ( core , "setFailed" );
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43" ;
2020-05-14 17:27:38 -04:00
const savedCacheKey = "Linux-node-" ;
2019-11-14 17:14:16 -05:00
jest . spyOn ( core , "getState" )
// Cache Entry State
. mockImplementationOnce (() => {
2020-05-14 17:27:38 -04:00
return savedCacheKey ;
2019-11-14 17:14:16 -05:00
})
// Cache Key State
. mockImplementationOnce (() => {
return primaryKey ;
});
const inputPath = "node_modules" ;
testUtils . setInput ( Inputs . Path , inputPath );
2020-05-14 17:27:38 -04:00
const saveCacheMock = jest
. spyOn ( cache , "saveCache" )
. mockImplementationOnce (() => {
throw new Error (
"Cache size of ~6144 MB (6442450944 B) is over the 5GB limit, not saving cache."
);
});
2019-11-14 17:14:16 -05:00
await run ();
2020-05-14 17:27:38 -04:00
expect ( saveCacheMock ). toHaveBeenCalledTimes ( 1 );
2020-10-02 09:59:55 -05:00
expect ( saveCacheMock ). toHaveBeenCalledWith (
[ inputPath ],
primaryKey ,
expect . anything ()
);
2019-11-14 17:14:16 -05:00
2019-11-21 14:37:54 -05:00
expect ( logWarningMock ). toHaveBeenCalledTimes ( 1 );
expect ( logWarningMock ). toHaveBeenCalledWith (
2020-02-01 15:11:02 -06:00
"Cache size of ~6144 MB (6442450944 B) is over the 5GB limit, not saving cache."
2019-11-14 17:14:16 -05:00
);
expect ( failedMock ). toHaveBeenCalledTimes ( 0 );
});
2020-01-06 13:05:50 -05:00
test ( "save with reserve cache failure outputs warning" , async () => {
const infoMock = jest . spyOn ( core , "info" );
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" );
const failedMock = jest . spyOn ( core , "setFailed" );
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43" ;
2020-05-14 17:27:38 -04:00
const savedCacheKey = "Linux-node-" ;
2020-01-06 13:05:50 -05:00
jest . spyOn ( core , "getState" )
// Cache Entry State
. mockImplementationOnce (() => {
2020-05-14 17:27:38 -04:00
return savedCacheKey ;
2020-01-06 13:05:50 -05:00
})
// Cache Key State
. mockImplementationOnce (() => {
return primaryKey ;
});
const inputPath = "node_modules" ;
testUtils . setInput ( Inputs . Path , inputPath );
2020-05-14 17:27:38 -04:00
const saveCacheMock = jest
. spyOn ( cache , "saveCache" )
2020-01-06 13:05:50 -05:00
. mockImplementationOnce (() => {
2020-05-14 17:27:38 -04:00
const actualCache = jest . requireActual ( "@actions/cache" );
const error = new actualCache . ReserveCacheError (
`Unable to reserve cache with key ${ primaryKey } , another job may be creating this cache.`
);
throw error ;
2020-01-06 13:05:50 -05:00
});
await run ();
2020-05-14 17:27:38 -04:00
expect ( saveCacheMock ). toHaveBeenCalledTimes ( 1 );
2020-10-02 09:59:55 -05:00
expect ( saveCacheMock ). toHaveBeenCalledWith (
[ inputPath ],
primaryKey ,
expect . anything ()
);
2020-01-06 13:05:50 -05:00
expect ( infoMock ). toHaveBeenCalledWith (
`Unable to reserve cache with key ${ primaryKey } , another job may be creating this cache.`
);
expect ( logWarningMock ). toHaveBeenCalledTimes ( 0 );
expect ( failedMock ). toHaveBeenCalledTimes ( 0 );
});
2019-11-14 17:14:16 -05:00
test ( "save with server error outputs warning" , async () => {
2019-11-21 14:37:54 -05:00
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" );
2019-11-14 17:14:16 -05:00
const failedMock = jest . spyOn ( core , "setFailed" );
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43" ;
2020-05-14 17:27:38 -04:00
const savedCacheKey = "Linux-node-" ;
2019-11-14 17:14:16 -05:00
jest . spyOn ( core , "getState" )
// Cache Entry State
. mockImplementationOnce (() => {
2020-05-14 17:27:38 -04:00
return savedCacheKey ;
2019-11-14 17:14:16 -05:00
})
// Cache Key State
. mockImplementationOnce (() => {
return primaryKey ;
});
const inputPath = "node_modules" ;
testUtils . setInput ( Inputs . Path , inputPath );
const saveCacheMock = jest
2020-05-14 17:27:38 -04:00
. spyOn ( cache , "saveCache" )
2019-11-14 17:14:16 -05:00
. mockImplementationOnce (() => {
throw new Error ( "HTTP Error Occurred" );
});
await run ();
expect ( saveCacheMock ). toHaveBeenCalledTimes ( 1 );
2020-10-02 09:59:55 -05:00
expect ( saveCacheMock ). toHaveBeenCalledWith (
[ inputPath ],
primaryKey ,
expect . anything ()
);
2019-11-14 17:14:16 -05:00
2019-11-21 14:37:54 -05:00
expect ( logWarningMock ). toHaveBeenCalledTimes ( 1 );
expect ( logWarningMock ). toHaveBeenCalledWith ( "HTTP Error Occurred" );
2019-11-14 17:14:16 -05:00
expect ( failedMock ). toHaveBeenCalledTimes ( 0 );
});
test ( "save with valid inputs uploads a cache" , async () => {
const failedMock = jest . spyOn ( core , "setFailed" );
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43" ;
2020-05-14 17:27:38 -04:00
const savedCacheKey = "Linux-node-" ;
2019-11-14 17:14:16 -05:00
jest . spyOn ( core , "getState" )
// Cache Entry State
. mockImplementationOnce (() => {
2020-05-14 17:27:38 -04:00
return savedCacheKey ;
2019-11-14 17:14:16 -05:00
})
// Cache Key State
. mockImplementationOnce (() => {
return primaryKey ;
});
const inputPath = "node_modules" ;
testUtils . setInput ( Inputs . Path , inputPath );
2020-10-02 09:59:55 -05:00
testUtils . setInput ( Inputs . UploadChunkSize , "4000000" );
2019-11-14 17:14:16 -05:00
2020-01-06 13:05:50 -05:00
const cacheId = 4 ;
2020-05-14 17:27:38 -04:00
const saveCacheMock = jest
. spyOn ( cache , "saveCache" )
2020-01-06 13:05:50 -05:00
. mockImplementationOnce (() => {
return Promise . resolve ( cacheId );
});
2019-11-14 17:14:16 -05:00
await run ();
expect ( saveCacheMock ). toHaveBeenCalledTimes ( 1 );
2020-10-02 09:59:55 -05:00
expect ( saveCacheMock ). toHaveBeenCalledWith ([ inputPath ], primaryKey , {
uploadChunkSize : 4000000
});
2019-11-14 17:14:16 -05:00
expect ( failedMock ). toHaveBeenCalledTimes ( 0 );
});