Compare commits

..

68 Commits

Author SHA1 Message Date
a8dcf7856e adding save-only and restore-only entry points 2022-12-08 10:35:19 +00:00
d463e30c26 test 2022-12-08 08:24:08 +00:00
790b78c6b6 removing required
removing required
2022-12-07 17:25:00 +00:00
7520a6a3a9 altering require 2022-12-07 17:22:59 +00:00
a5fbe79711 adding outputs 2022-12-07 17:07:30 +00:00
66ef8a0951 Merge pull request #1018 from actions/bishal/outputter
Update save with a wrapper layer
2022-12-07 17:03:07 +05:30
657c52f11e fix merge 2022-12-06 18:45:12 +00:00
34e917cb7d Merge branch '700-actionscache-granular-cache-control' into bishal/outputter 2022-12-06 18:42:19 +00:00
ac8fc97c06 update save as well 2022-12-06 18:26:58 +00:00
86712a0733 dist 2022-12-06 10:10:52 +00:00
d6e98d9302 Calling methods from same file 2022-12-06 10:08:26 +00:00
a76826ef46 Removed commented lines 2022-12-06 10:07:30 +00:00
e02e5113ed Removed return type in promise 2022-12-06 10:03:48 +00:00
85ae5bbcea Fixed breaking test case 2022-12-06 09:36:37 +00:00
cce93fb2c7 Generated dist 2022-12-06 08:23:10 +00:00
e3d8fb0b34 Merge pull request #1016 from actions/bishal/outputter
Refactor setting output and state into a generic outputter
2022-12-05 18:10:52 +05:30
d95c048983 refactor into a generic outputter 2022-12-05 11:36:14 +00:00
706c369cf1 Merge branch 'main' into 700-actionscache-granular-cache-control 2022-12-05 12:24:53 +05:30
a57932faba Merge pull request #1014 from jongwooo/chore/use-built-in-cache-action
chore: Use built-in cache action to cache dependencies
2022-12-05 12:24:26 +05:30
04b13caea4 chore: Use built-in cache action to cache dependencies
Signed-off-by: jongwooo <jongwooo.han@gmail.com>
2022-12-05 15:31:51 +09:00
941bc71a24 Merge pull request #1004 from jongwooo/chore/use-cache-in-check-dist
Use cache in check-dist.yml
2022-12-05 07:56:20 +05:30
08d8639046 Merge branch 'main' into chore/use-cache-in-check-dist 2022-12-03 23:00:34 +09:00
a2f324eeb7 Merge pull request #1013 from jongwooo/refactor/use-early-return-pattern-to-avoid-nested-conditions
refactor: Use early return pattern to avoid nested conditions
2022-12-02 16:12:03 +05:30
11ab7ccfa2 Reverted custom asks implemented and added wrapper 2022-12-02 10:14:43 +00:00
35f4702f6c refactor: Use early return pattern to avoid nested conditions
Signed-off-by: jongwooo <jongwooo.han@gmail.com>
2022-12-02 18:12:53 +09:00
4b5f33df54 Updated new actions' input descriptions 2022-12-01 08:27:08 +00:00
e050ebdd63 chore: Use setup-node action to cache dependencies 2022-11-30 20:36:12 +09:00
0d47d164e9 Merge branch 'main' into chore/use-cache-in-check-dist 2022-11-30 20:33:28 +09:00
56a0133650 Merge branch 'main' into 700-actionscache-granular-cache-control 2022-11-30 16:20:50 +05:30
19446b165a Slight modification for test cases check 2022-11-30 10:47:09 +00:00
e2d614414f Merge pull request #1007 from actions/phantsure/npm-fix
Fix npm vulnerability
2022-11-30 01:14:39 -08:00
532752012e Change with new dependencies 2022-11-30 08:47:34 +00:00
8a88690a20 Fixed test cases issues 2022-11-30 08:38:59 +00:00
b26da1fc31 Fix license 2022-11-30 08:38:44 +00:00
ce61cc4d24 Fix license test 2022-11-30 08:35:05 +00:00
6e2c6a5916 Formatted document 2022-11-30 08:30:16 +00:00
2c9fb32186 Merge branch 'main' into 700-actionscache-granular-cache-control 2022-11-30 13:57:39 +05:30
01d96636a0 Some cleanup 2022-11-30 08:26:50 +00:00
268ae08cbc Fix npm vulnerability 2022-11-30 08:23:43 +00:00
9c5a42a7c9 Added test cases 2022-11-30 08:11:55 +00:00
b4ac56fa43 Merge pull request #1005 from actions/revert-998-dependabot/npm_and_yarn/minimatch-3.1.2
Revert "Bump minimatch from 3.0.4 to 3.1.2"
2022-11-30 13:13:30 +05:30
24f54d74c0 Revert "Bump minimatch from 3.0.4 to 3.1.2" 2022-11-30 12:04:53 +05:30
8d99052cbc Merge pull request #998 from actions/dependabot/npm_and_yarn/minimatch-3.1.2
Bump minimatch from 3.0.4 to 3.1.2
2022-11-30 12:02:37 +05:30
58a0402e7d Merge branch 'main' into dependabot/npm_and_yarn/minimatch-3.1.2 2022-11-30 11:19:36 +05:30
7920f570b8 Use cache in check-dist.yml
Signed-off-by: jongwooo <jongwooo.han@gmail.com>
2022-11-30 01:03:16 +09:00
a172494938 Reverted wrapper changes 2022-11-29 10:56:53 +00:00
f8717682fb Impl separated 2022-11-29 09:55:41 +00:00
af1210e2a3 test 2022-11-29 09:51:53 +00:00
ab0e7714ce new try 2022-11-29 09:39:21 +00:00
fb4a5dce60 test 2022-11-29 09:33:03 +00:00
71334c58b2 Test 2022-11-29 09:06:10 +00:00
888d454557 experimenting 2022-11-29 09:03:19 +00:00
dddd7ce07c added debug logs 2022-11-29 08:26:52 +00:00
abddc4dd44 Merge remote-tracking branch 'origin/master' into 700-actionscache-granular-cache-control 2022-11-29 08:08:32 +00:00
921c58ee44 Changed logs to warnings 2022-11-29 08:06:41 +00:00
7f45813c72 Adding wrapper class 2022-11-29 08:02:27 +00:00
0769f2e443 Merge branch 'main' into master 2022-11-28 23:50:15 -08:00
f8116c8945 Bug fix in PR assignee workflow 2022-11-29 13:19:00 +05:30
5fe0b944ef Updated variable name 2022-11-29 07:48:11 +00:00
2a6cd14175 Add assignee to PR automatically 2022-11-29 13:16:11 +05:30
651d82954c Change pull_request to pull_request_target for PR review 2022-11-28 16:18:36 +05:30
cfa1b7695d Bump minimatch from 3.0.4 to 3.1.2
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.0.4 to 3.1.2.
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 10:27:26 +00:00
fa8856311e Merge pull request #997 from actions/vsvipul/change-assignee-logic
Add oncall logic to assign issues and PRs
2022-11-28 02:26:51 -08:00
69b8227b27 Basic implementation 2022-11-25 09:16:56 +00:00
515d10b4fd Merge pull request #746 from actions/revert-173-add-stack-example
Revert "Add example for Haskell Stack"
2022-02-22 12:44:25 +05:30
669e7536d9 Revert "Add example for Haskell Stack" 2022-02-22 12:17:37 +05:30
29dbbce762 Merge pull request #173 from malob/add-stack-example
Add example for Haskell Stack
2022-02-22 12:11:06 +05:30
ea5981db97 Add example for Haskell Stack 2022-02-21 14:59:28 -08:00
25 changed files with 129639 additions and 6191 deletions

View 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"
}

View File

@ -1,6 +1,6 @@
name: Add Reviewer PR
on:
pull_request:
pull_request_target:
types: [opened]
jobs:
run-action:
@ -11,6 +11,10 @@ jobs:
run: |
echo "CURRENT=$(curl --request GET 'https://api.pagerduty.com/oncalls?include[]=users&schedule_ids[]=P5VG2BX&earliest=true' --header 'Authorization: Token token=${{ secrets.PAGERDUTY_TOKEN }}' --header 'Accept: application/vnd.pagerduty+json;version=2' --header 'Content-Type: application/json' | jq -r '.oncalls[].user.name')" >> $GITHUB_OUTPUT
- name: add_reviewer
- name: Request Review
run: |
curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN}}" https://api.github.com/repos/${{github.repository}}/pulls/${{ github.event.pull_request.number}}/requested_reviewers -d '{"reviewers":["${{steps.oncall.outputs.CURRENT}}"]}'
curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN}}" https://api.github.com/repos/${{github.repository}}/pulls/${{ github.event.pull_request.number}}/requested_reviewers -d '{"reviewers":["${{steps.oncall.outputs.CURRENT}}"]}'
- name: Add Assignee
run: |
curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN}}" https://api.github.com/repos/${{github.repository}}/issues/${{ github.event.pull_request.number}}/assignees -d '{"assignees":["${{steps.oncall.outputs.CURRENT}}"]}'

View File

@ -27,6 +27,7 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: npm
- name: Install dependencies
run: npm ci
- name: Rebuild the dist/ directory

View File

@ -25,17 +25,7 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: 16.x
- 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-
cache: npm
- run: npm ci
- name: Prettier Format Check
run: npm run format-check

View File

@ -102,7 +102,7 @@ test("restore on GHES with AC available ", async () => {
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 setCacheHitOutputMock = jest.spyOn(core, "setOutput");
const restoreCacheMock = jest
.spyOn(cache, "restoreCache")
.mockImplementationOnce(() => {
@ -116,7 +116,7 @@ test("restore on GHES with AC available ", async () => {
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
expect(setCacheHitOutputMock).toHaveBeenCalledWith(true);
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
expect(failedMock).toHaveBeenCalledTimes(0);
@ -270,7 +270,7 @@ test("restore with cache found for key", async () => {
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 setCacheHitOutputMock = jest.spyOn(core, "setOutput");
const restoreCacheMock = jest
.spyOn(cache, "restoreCache")
.mockImplementationOnce(() => {
@ -284,7 +284,7 @@ test("restore with cache found for key", async () => {
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
expect(setCacheHitOutputMock).toHaveBeenCalledWith(true);
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
expect(failedMock).toHaveBeenCalledTimes(0);
@ -303,7 +303,7 @@ test("restore with cache found for restore key", async () => {
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 setCacheHitOutputMock = jest.spyOn(core, "setOutput");
const restoreCacheMock = jest
.spyOn(cache, "restoreCache")
.mockImplementationOnce(() => {
@ -317,8 +317,7 @@ test("restore with cache found for restore key", async () => {
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
expect(infoMock).toHaveBeenCalledWith(
`Cache restored from key: ${restoreKey}`
);

View File

@ -21,7 +21,7 @@ runs:
using: 'node16'
main: 'dist/restore/index.js'
post: 'dist/save/index.js'
post-if: 'success()'
post-if: success()
branding:
icon: 'archive'
color: 'gray-dark'

61377
dist/restore-only/index.js vendored Normal file

File diff suppressed because one or more lines are too long

5587
dist/restore/index.js vendored

File diff suppressed because it is too large Load Diff

61382
dist/save-only/index.js vendored Normal file

File diff suppressed because one or more lines are too long

431
dist/save/index.js vendored
View File

@ -1892,10 +1892,10 @@ function serial(list, iterator, callback)
module.exports = minimatch
minimatch.Minimatch = Minimatch
var path = { sep: '/' }
try {
path = __webpack_require__(622)
} catch (er) {}
var path = (function () { try { return __webpack_require__(622) } catch (e) {}}()) || {
sep: '/'
}
minimatch.sep = path.sep
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
var expand = __webpack_require__(306)
@ -1947,43 +1947,64 @@ function filter (pattern, options) {
}
function ext (a, b) {
a = a || {}
b = b || {}
var t = {}
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
Object.keys(a).forEach(function (k) {
t[k] = a[k]
})
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
return t
}
minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return minimatch
if (!def || typeof def !== 'object' || !Object.keys(def).length) {
return minimatch
}
var orig = minimatch
var m = function minimatch (p, pattern, options) {
return orig.minimatch(p, pattern, ext(def, options))
return orig(p, pattern, ext(def, options))
}
m.Minimatch = function Minimatch (pattern, options) {
return new orig.Minimatch(pattern, ext(def, options))
}
m.Minimatch.defaults = function defaults (options) {
return orig.defaults(ext(def, options)).Minimatch
}
m.filter = function filter (pattern, options) {
return orig.filter(pattern, ext(def, options))
}
m.defaults = function defaults (options) {
return orig.defaults(ext(def, options))
}
m.makeRe = function makeRe (pattern, options) {
return orig.makeRe(pattern, ext(def, options))
}
m.braceExpand = function braceExpand (pattern, options) {
return orig.braceExpand(pattern, ext(def, options))
}
m.match = function (list, pattern, options) {
return orig.match(list, pattern, ext(def, options))
}
return m
}
Minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return Minimatch
return minimatch.defaults(def).Minimatch
}
function minimatch (p, pattern, options) {
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
assertValidPattern(pattern)
if (!options) options = {}
@ -1992,9 +2013,6 @@ function minimatch (p, pattern, options) {
return false
}
// "" only matches ""
if (pattern.trim() === '') return p === ''
return new Minimatch(pattern, options).match(p)
}
@ -2003,15 +2021,14 @@ function Minimatch (pattern, options) {
return new Minimatch(pattern, options)
}
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
assertValidPattern(pattern)
if (!options) options = {}
pattern = pattern.trim()
// windows support: need to use /, not \
if (path.sep !== '/') {
if (!options.allowWindowsEscape && path.sep !== '/') {
pattern = pattern.split(path.sep).join('/')
}
@ -2022,6 +2039,7 @@ function Minimatch (pattern, options) {
this.negate = false
this.comment = false
this.empty = false
this.partial = !!options.partial
// make the set of regexps etc.
this.make()
@ -2031,9 +2049,6 @@ Minimatch.prototype.debug = function () {}
Minimatch.prototype.make = make
function make () {
// don't do it more than once.
if (this._made) return
var pattern = this.pattern
var options = this.options
@ -2053,7 +2068,7 @@ function make () {
// step 2: expand braces
var set = this.globSet = this.braceExpand()
if (options.debug) this.debug = console.error
if (options.debug) this.debug = function debug() { console.error.apply(console, arguments) }
this.debug(this.pattern, set)
@ -2133,12 +2148,11 @@ function braceExpand (pattern, options) {
pattern = typeof pattern === 'undefined'
? this.pattern : pattern
if (typeof pattern === 'undefined') {
throw new TypeError('undefined pattern')
}
assertValidPattern(pattern)
if (options.nobrace ||
!pattern.match(/\{.*\}/)) {
// Thanks to Yeting Li <https://github.com/yetingli> for
// improving this regexp to avoid a ReDOS vulnerability.
if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
// shortcut. no need to expand.
return [pattern]
}
@ -2146,6 +2160,17 @@ function braceExpand (pattern, options) {
return expand(pattern)
}
var MAX_PATTERN_LENGTH = 1024 * 64
var assertValidPattern = function (pattern) {
if (typeof pattern !== 'string') {
throw new TypeError('invalid pattern')
}
if (pattern.length > MAX_PATTERN_LENGTH) {
throw new TypeError('pattern is too long')
}
}
// parse a component of the expanded set.
// At this point, no pattern may contain "/" in it
// so we're going to return a 2d array, where each entry is the full
@ -2160,14 +2185,17 @@ function braceExpand (pattern, options) {
Minimatch.prototype.parse = parse
var SUBPARSE = {}
function parse (pattern, isSub) {
if (pattern.length > 1024 * 64) {
throw new TypeError('pattern is too long')
}
assertValidPattern(pattern)
var options = this.options
// shortcuts
if (!options.noglobstar && pattern === '**') return GLOBSTAR
if (pattern === '**') {
if (!options.noglobstar)
return GLOBSTAR
else
pattern = '*'
}
if (pattern === '') return ''
var re = ''
@ -2223,10 +2251,12 @@ function parse (pattern, isSub) {
}
switch (c) {
case '/':
/* istanbul ignore next */
case '/': {
// completely not allowed, even escaped.
// Should already be path-split by now.
return false
}
case '\\':
clearStateChar()
@ -2345,25 +2375,23 @@ function parse (pattern, isSub) {
// handle the case where we left a class open.
// "[z-a]" is valid, equivalent to "\[z-a\]"
if (inClass) {
// split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that
// were passed through as-is
// TODO: It would probably be faster to determine this
// without a try/catch and a new RegExp, but it's tricky
// to do safely. For now, this is safe and works.
var cs = pattern.substring(classStart + 1, i)
try {
RegExp('[' + cs + ']')
} catch (er) {
// not a valid class!
var sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
hasMagic = hasMagic || sp[1]
inClass = false
continue
}
// split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that
// were passed through as-is
// TODO: It would probably be faster to determine this
// without a try/catch and a new RegExp, but it's tricky
// to do safely. For now, this is safe and works.
var cs = pattern.substring(classStart + 1, i)
try {
RegExp('[' + cs + ']')
} catch (er) {
// not a valid class!
var sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
hasMagic = hasMagic || sp[1]
inClass = false
continue
}
// finish up the class.
@ -2447,9 +2475,7 @@ function parse (pattern, isSub) {
// something that could conceivably capture a dot
var addPatternStart = false
switch (re.charAt(0)) {
case '.':
case '[':
case '(': addPatternStart = true
case '[': case '.': case '(': addPatternStart = true
}
// Hack to work around lack of negative lookbehind in JS
@ -2511,7 +2537,7 @@ function parse (pattern, isSub) {
var flags = options.nocase ? 'i' : ''
try {
var regExp = new RegExp('^' + re + '$', flags)
} catch (er) {
} catch (er) /* istanbul ignore next - should be impossible */ {
// If it was an invalid regular expression, then it can't match
// anything. This trick looks for a character after the end of
// the string, which is of course impossible, except in multi-line
@ -2569,7 +2595,7 @@ function makeRe () {
try {
this.regexp = new RegExp(re, flags)
} catch (ex) {
} catch (ex) /* istanbul ignore next - should be impossible */ {
this.regexp = false
}
return this.regexp
@ -2587,8 +2613,8 @@ minimatch.match = function (list, pattern, options) {
return list
}
Minimatch.prototype.match = match
function match (f, partial) {
Minimatch.prototype.match = function match (f, partial) {
if (typeof partial === 'undefined') partial = this.partial
this.debug('match', f, this.pattern)
// short-circuit in the case of busted things.
// comments, etc.
@ -2670,6 +2696,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// should be impossible.
// some invalid regexp stuff in the set.
/* istanbul ignore if */
if (p === false) return false
if (p === GLOBSTAR) {
@ -2743,6 +2770,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// no match was found.
// However, in partial mode, we can't say this is necessarily over.
// If there's more *pattern* left, then
/* istanbul ignore if */
if (partial) {
// ran out of file
this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
@ -2756,11 +2784,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// patterns with magic have been turned into regexps.
var hit
if (typeof p === 'string') {
if (options.nocase) {
hit = f.toLowerCase() === p.toLowerCase()
} else {
hit = f === p
}
hit = f === p
this.debug('string match', p, f, hit)
} else {
hit = f.match(p)
@ -2791,16 +2815,16 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// this is ok if we're doing the match as part of
// a glob fs traversal.
return partial
} else if (pi === pl) {
} else /* istanbul ignore else */ if (pi === pl) {
// ran out of pattern, still have file left.
// this is only acceptable if we're on the very last
// empty segment of a file with a trailing slash.
// a/* should match a/b/
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')
return emptyFileEnd
return (fi === fl - 1) && (file[fi] === '')
}
// should be unreachable.
/* istanbul ignore next */
throw new Error('wtf?')
}
@ -4951,6 +4975,8 @@ var Inputs;
var Outputs;
(function (Outputs) {
Outputs["CacheHit"] = "cache-hit";
Outputs["Key"] = "key";
Outputs["MatchedKey"] = "matched-key";
})(Outputs = exports.Outputs || (exports.Outputs = {}));
var State;
(function (State) {
@ -9320,7 +9346,76 @@ function expand(str, isTop) {
/***/ }),
/* 307 */,
/* 308 */,
/* 309 */,
/* 309 */
/***/ (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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NullStateProvider = exports.StateProvider = void 0;
const core = __importStar(__webpack_require__(470));
const constants_1 = __webpack_require__(196);
class StateProviderBase {
constructor() {
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
this.setState = (key, value) => { };
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.getState = (key) => "";
}
getCacheState() {
const cacheKey = this.getState(constants_1.State.CacheMatchedKey);
if (cacheKey) {
core.debug(`Cache state/key: ${cacheKey}`);
return cacheKey;
}
return undefined;
}
}
class StateProvider extends StateProviderBase {
constructor() {
super(...arguments);
//setOutput = core.setOutput;
this.setState = core.saveState;
this.getState = core.getState;
}
}
exports.StateProvider = StateProvider;
class NullStateProvider extends StateProviderBase {
constructor() {
super(...arguments);
//setOutput = core.setOutput;
this.setState = core.setOutput;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.getState = (key) => "";
}
}
exports.NullStateProvider = NullStateProvider;
/***/ }),
/* 310 */,
/* 311 */,
/* 312 */
@ -38398,7 +38493,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isCacheFeatureAvailable = exports.getInputAsInt = exports.getInputAsArray = exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = exports.isGhes = void 0;
exports.isCacheFeatureAvailable = exports.getInputAsInt = exports.getInputAsArray = exports.isValidEvent = exports.logWarning = exports.setCacheHitOutput = exports.isExactKeyMatch = exports.isGhes = void 0;
const cache = __importStar(__webpack_require__(692));
const core = __importStar(__webpack_require__(470));
const constants_1 = __webpack_require__(196);
@ -38414,29 +38509,10 @@ function isExactKeyMatch(key, cacheKey) {
}) === 0);
}
exports.isExactKeyMatch = isExactKeyMatch;
function setCacheState(state) {
core.saveState(constants_1.State.CacheMatchedKey, state);
}
exports.setCacheState = setCacheState;
function setCacheHitOutput(isCacheHit) {
core.setOutput(constants_1.Outputs.CacheHit, isCacheHit.toString());
}
exports.setCacheHitOutput = setCacheHitOutput;
function setOutputAndState(key, cacheKey) {
setCacheHitOutput(isExactKeyMatch(key, cacheKey));
// Store the matched cache key if it exists
cacheKey && setCacheState(cacheKey);
}
exports.setOutputAndState = setOutputAndState;
function getCacheState() {
const cacheKey = core.getState(constants_1.State.CacheMatchedKey);
if (cacheKey) {
core.debug(`Cache state/key: ${cacheKey}`);
return cacheKey;
}
return undefined;
}
exports.getCacheState = getCacheState;
function logWarning(message) {
const warningPrefix = "[warning]";
core.info(`${warningPrefix}${message}`);
@ -38465,17 +38541,16 @@ function getInputAsInt(name, options) {
}
exports.getInputAsInt = getInputAsInt;
function isCacheFeatureAvailable() {
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.
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.
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;
}
return true;
logWarning("An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions.");
return false;
}
exports.isCacheFeatureAvailable = isCacheFeatureAvailable;
@ -40869,7 +40944,96 @@ Object.defineProperty(exports, "toPlatformPath", { enumerable: true, get: functi
//# sourceMappingURL=core.js.map
/***/ }),
/* 471 */,
/* 471 */
/***/ (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());
});
};
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 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
// throw an uncaught exception. Instead of failing this action, just warn.
process.on("uncaughtException", e => utils.logWarning(e.message));
function saveImpl(stateProvider) {
return __awaiter(this, void 0, void 0, function* () {
try {
if (!utils.isCacheFeatureAvailable()) {
return;
}
if (!utils.isValidEvent()) {
utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported because it's not tied to a branch or tag ref.`);
return;
}
// If restore has stored a primary key in state, reuse that
// Else re-evaluate from inputs
const primaryKey = stateProvider.getState(constants_1.State.CachePrimaryKey) ||
core.getInput(constants_1.Inputs.Key);
if (!primaryKey) {
utils.logWarning(`Error retrieving key from state.`);
return;
}
// If matched restore key is same as primary key, then do not save cache
// NO-OP in case of SaveOnly action
const state = stateProvider.getCacheState();
if (utils.isExactKeyMatch(primaryKey, state)) {
core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`);
return;
}
const cachePaths = utils.getInputAsArray(constants_1.Inputs.Path, {
required: true
});
const cacheId = yield cache.saveCache(cachePaths, primaryKey, {
uploadChunkSize: utils.getInputAsInt(constants_1.Inputs.UploadChunkSize)
});
if (cacheId != -1) {
core.info(`Cache saved with key: ${primaryKey}`);
}
}
catch (error) {
utils.logWarning(error.message);
}
});
}
exports.default = saveImpl;
/***/ }),
/* 472 */,
/* 473 */,
/* 474 */,
@ -47245,29 +47409,6 @@ exports.default = _default;
"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) {
@ -47277,49 +47418,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
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 });
const cache = __importStar(__webpack_require__(692));
const core = __importStar(__webpack_require__(470));
const constants_1 = __webpack_require__(196);
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
// throw an uncaught exception. Instead of failing this action, just warn.
process.on("uncaughtException", e => utils.logWarning(e.message));
const saveImpl_1 = __importDefault(__webpack_require__(471));
const stateProvider_1 = __webpack_require__(309);
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
if (!utils.isCacheFeatureAvailable()) {
return;
}
if (!utils.isValidEvent()) {
utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported because it's not tied to a branch or tag ref.`);
return;
}
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);
if (!primaryKey) {
utils.logWarning(`Error retrieving key from state.`);
return;
}
if (utils.isExactKeyMatch(primaryKey, state)) {
core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`);
return;
}
const cachePaths = utils.getInputAsArray(constants_1.Inputs.Path, {
required: true
});
const cacheId = yield cache.saveCache(cachePaths, primaryKey, {
uploadChunkSize: utils.getInputAsInt(constants_1.Inputs.UploadChunkSize)
});
if (cacheId != -1) {
core.info(`Cache saved with key: ${primaryKey}`);
}
}
catch (error) {
utils.logWarning(error.message);
}
yield (0, saveImpl_1.default)(new stateProvider_1.StateProvider());
});
}
run();

6516
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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/restore-only src/restoreOnly.ts && ncc build -o dist/save-only src/saveOnly.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.0",
"@types/jest": "^27.5.2",
"@types/nock": "^11.1.0",
"@types/node": "^16.11.33",
"@typescript-eslint/eslint-plugin": "^5.22.0",
"@typescript-eslint/parser": "^5.22.0",
"@types/node": "^16.18.3",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
"@zeit/ncc": "^0.20.5",
"eslint": "^8.14.0",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jest": "^26.1.5",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-jest": "^26.9.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-simple-import-sort": "^7.0.0",
"jest": "^28.0.3",
"jest": "^28.1.3",
"jest-circus": "^27.5.1",
"nock": "^13.2.4",
"prettier": "^2.6.2",
"ts-jest": "^28.0.2",
"typescript": "^4.6.4"
"nock": "^13.2.9",
"prettier": "^2.8.0",
"ts-jest": "^28.0.8",
"typescript": "^4.9.3"
}
}

27
restore-only/action.yml Normal file
View File

@ -0,0 +1,27 @@
name: 'Restore Only Cache'
description: 'Restore Cache artifacts like dependencies and build outputs to improve workflow execution time'
author: 'GitHub'
inputs:
path:
description: 'The same list of files, directories, and wildcard patterns to restore cache that were used while saving it'
required: true
key:
description: 'An explicit key for restoring 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
outputs:
cache-hit:
description: 'A boolean value to indicate an exact match was found for the primary key'
key:
description: 'Key passed in the input to use in subsequent steps of the workflow'
matched-key:
description: 'Cache key restored'
runs:
using: 'node16'
main: '../dist/restore-only/index.js'
branding:
icon: 'archive'
color: 'gray-dark'

27
restore/action.yml Normal file
View 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: 'The same list of files, directories, and wildcard patterns to restore cache that were used while saving it'
required: true
key:
description: 'An explicit key for restoring 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
outputs:
cache-hit:
description: 'A boolean value to indicate an exact match was found for the primary key'
key:
description: 'Key passed in the input to use in subsequent steps of the workflow'
matched-key:
description: 'Cache key restored'
runs:
using: 'node16'
main: '../dist/restore/index.js'
branding:
icon: 'archive'
color: 'gray-dark'

22
save-only/action.yml Normal file
View File

@ -0,0 +1,22 @@
name: 'Save Only 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'
required: true
key:
description: 'An explicit key for saving the cache'
required: true
upload-chunk-size:
description: 'The chunk size used to split up large files during upload, in bytes'
required: false
matched-key:
description: 'Cache key restored from the restore action'
required: false
runs:
using: 'node16'
main: '../dist/save-only/index.js'
branding:
icon: 'archive'
color: 'gray-dark'

22
save/action.yml Normal file
View File

@ -0,0 +1,22 @@
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'
required: true
key:
description: 'An explicit key for saving the cache'
required: true
upload-chunk-size:
description: 'The chunk size used to split up large files during upload, in bytes'
required: false
matched-key:
description: 'Cache key restored from the restore action'
required: false
runs:
using: 'node16'
main: '../dist/save/index.js'
branding:
icon: 'archive'
color: 'gray-dark'

View File

@ -6,7 +6,9 @@ export enum Inputs {
}
export enum Outputs {
CacheHit = "cache-hit"
CacheHit = "cache-hit",
Key = "key",
MatchedKey = "matched-key"
}
export enum State {

View File

@ -1,60 +1,8 @@
import * as cache from "@actions/cache";
import * as core from "@actions/core";
import { Events, Inputs, State } from "./constants";
import * as utils from "./utils/actionUtils";
import { StateProvider } from "./stateProvider";
import restoreImpl from "./restoreImpl";
async function run(): Promise<void> {
try {
if (!utils.isCacheFeatureAvailable()) {
utils.setCacheHitOutput(false);
return;
}
// Validate inputs, this can cause task failure
if (!utils.isValidEvent()) {
utils.logWarning(
`Event Validation Error: The event type ${
process.env[Events.Key]
} is not supported because it's not tied to a branch or tag ref.`
);
return;
}
const primaryKey = core.getInput(Inputs.Key, { required: true });
core.saveState(State.CachePrimaryKey, primaryKey);
const restoreKeys = utils.getInputAsArray(Inputs.RestoreKeys);
const cachePaths = utils.getInputAsArray(Inputs.Path, {
required: true
});
const cacheKey = await cache.restoreCache(
cachePaths,
primaryKey,
restoreKeys
);
if (!cacheKey) {
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);
core.info(`Cache restored from key: ${cacheKey}`);
} catch (error: unknown) {
core.setFailed((error as Error).message);
}
await restoreImpl(new StateProvider());
}
run();

70
src/restoreImpl.ts Normal file
View File

@ -0,0 +1,70 @@
import * as cache from "@actions/cache";
import * as core from "@actions/core";
import { Events, Inputs, Outputs, State } from "./constants";
import { IStateProvider } from "./stateProvider";
import * as utils from "./utils/actionUtils";
async function restoreImpl(
stateProvider: IStateProvider
): Promise<string | undefined> {
try {
if (!utils.isCacheFeatureAvailable()) {
utils.setCacheHitOutput(false);
return;
}
// Validate inputs, this can cause task failure
if (!utils.isValidEvent()) {
utils.logWarning(
`Event Validation Error: The event type ${
process.env[Events.Key]
} is not supported because it's not tied to a branch or tag ref.`
);
return;
}
const primaryKey = core.getInput(Inputs.Key, { required: true });
stateProvider.setState(State.CachePrimaryKey, primaryKey);
const restoreKeys = utils.getInputAsArray(Inputs.RestoreKeys);
const cachePaths = utils.getInputAsArray(Inputs.Path, {
required: true
});
const cacheKey = await cache.restoreCache(
cachePaths,
primaryKey,
restoreKeys
);
if (!cacheKey) {
core.info(
`Cache not found for input keys: ${[
primaryKey,
...restoreKeys
].join(", ")}`
);
return;
}
// Store the matched cache key in states
stateProvider.setState(State.CacheMatchedKey, cacheKey);
core.debug("setState: " + State.CacheMatchedKey + " " + cacheKey);
const isExactKeyMatch = utils.isExactKeyMatch(
core.getInput(Inputs.Key, { required: true }),
cacheKey
);
core.setOutput(Outputs.CacheHit, isExactKeyMatch.toString());
core.info(`Cache restored from key: ${cacheKey}`);
return cacheKey;
} catch (error: unknown) {
core.setFailed((error as Error).message);
}
}
export default restoreImpl;

10
src/restoreOnly.ts Normal file
View File

@ -0,0 +1,10 @@
import restoreImpl from "./restoreImpl";
import { NullStateProvider } from "./stateProvider";
async function run(): Promise<void> {
await restoreImpl(new NullStateProvider());
}
run();
export default run;

View File

@ -1,59 +1,8 @@
import * as cache from "@actions/cache";
import * as core from "@actions/core";
import { Events, Inputs, State } from "./constants";
import * as utils from "./utils/actionUtils";
// 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
// throw an uncaught exception. Instead of failing this action, just warn.
process.on("uncaughtException", e => utils.logWarning(e.message));
import saveImpl from "./saveImpl";
import { StateProvider } from "./stateProvider";
async function run(): Promise<void> {
try {
if (!utils.isCacheFeatureAvailable()) {
return;
}
if (!utils.isValidEvent()) {
utils.logWarning(
`Event Validation Error: The event type ${
process.env[Events.Key]
} is not supported because it's not tied to a branch or tag ref.`
);
return;
}
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);
if (!primaryKey) {
utils.logWarning(`Error retrieving key from state.`);
return;
}
if (utils.isExactKeyMatch(primaryKey, state)) {
core.info(
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
);
return;
}
const cachePaths = utils.getInputAsArray(Inputs.Path, {
required: true
});
const cacheId = await cache.saveCache(cachePaths, primaryKey, {
uploadChunkSize: utils.getInputAsInt(Inputs.UploadChunkSize)
});
if (cacheId != -1) {
core.info(`Cache saved with key: ${primaryKey}`);
}
} catch (error: unknown) {
utils.logWarning((error as Error).message);
}
await saveImpl(new StateProvider());
}
run();

65
src/saveImpl.ts Normal file
View File

@ -0,0 +1,65 @@
import * as cache from "@actions/cache";
import * as core from "@actions/core";
import { Events, Inputs, State } from "./constants";
import { IStateProvider } from "./stateProvider";
import * as utils from "./utils/actionUtils";
// 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
// throw an uncaught exception. Instead of failing this action, just warn.
process.on("uncaughtException", e => utils.logWarning(e.message));
async function saveImpl(stateProvider: IStateProvider): Promise<void> {
try {
if (!utils.isCacheFeatureAvailable()) {
return;
}
if (!utils.isValidEvent()) {
utils.logWarning(
`Event Validation Error: The event type ${
process.env[Events.Key]
} is not supported because it's not tied to a branch or tag ref.`
);
return;
}
// If restore has stored a primary key in state, reuse that
// Else re-evaluate from inputs
const primaryKey =
stateProvider.getState(State.CachePrimaryKey) ||
core.getInput(Inputs.Key);
if (!primaryKey) {
utils.logWarning(`Error retrieving key from state.`);
return;
}
// If matched restore key is same as primary key, then do not save cache
// NO-OP in case of SaveOnly action
const state = stateProvider.getCacheState();
if (utils.isExactKeyMatch(primaryKey, state)) {
core.info(
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
);
return;
}
const cachePaths = utils.getInputAsArray(Inputs.Path, {
required: true
});
const cacheId = await cache.saveCache(cachePaths, primaryKey, {
uploadChunkSize: utils.getInputAsInt(Inputs.UploadChunkSize)
});
if (cacheId != -1) {
core.info(`Cache saved with key: ${primaryKey}`);
}
} catch (error: unknown) {
utils.logWarning((error as Error).message);
}
}
export default saveImpl;

10
src/saveOnly.ts Normal file
View File

@ -0,0 +1,10 @@
import saveImpl from "./saveImpl";
import { NullStateProvider } from "./stateProvider";
async function run(): Promise<void> {
await saveImpl(new NullStateProvider());
}
run();
export default run;

42
src/stateProvider.ts Normal file
View File

@ -0,0 +1,42 @@
import * as core from "@actions/core";
import { State } from "./constants";
export interface IStateProvider {
//setOutput(key: string, value: string): void;
setState(key: string, value: string): void;
getState(key: string): string;
getCacheState(): string | undefined;
}
class StateProviderBase implements IStateProvider {
getCacheState(): string | undefined {
const cacheKey = this.getState(State.CacheMatchedKey);
if (cacheKey) {
core.debug(`Cache state/key: ${cacheKey}`);
return cacheKey;
}
return undefined;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
setState = (key: string, value: string) => {};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
getState = (key: string) => "";
}
export class StateProvider extends StateProviderBase {
//setOutput = core.setOutput;
setState = core.saveState;
getState = core.getState;
}
export class NullStateProvider extends StateProviderBase {
//setOutput = core.setOutput;
setState = core.setOutput;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
getState = (key: string) => "";
}

View File

@ -1,7 +1,7 @@
import * as cache from "@actions/cache";
import * as core from "@actions/core";
import { Outputs, RefKey, State } from "../constants";
import { Outputs, RefKey } from "../constants";
export function isGhes(): boolean {
const ghUrl = new URL(
@ -19,30 +19,10 @@ export function isExactKeyMatch(key: string, cacheKey?: string): boolean {
);
}
export function setCacheState(state: string): void {
core.saveState(State.CacheMatchedKey, state);
}
export function setCacheHitOutput(isCacheHit: boolean): void {
core.setOutput(Outputs.CacheHit, isCacheHit.toString());
}
export function setOutputAndState(key: string, cacheKey?: string): void {
setCacheHitOutput(isExactKeyMatch(key, cacheKey));
// Store the matched cache key if it exists
cacheKey && setCacheState(cacheKey);
}
export function getCacheState(): string | undefined {
const cacheKey = core.getState(State.CacheMatchedKey);
if (cacheKey) {
core.debug(`Cache state/key: ${cacheKey}`);
return cacheKey;
}
return undefined;
}
export function logWarning(message: string): void {
const warningPrefix = "[warning]";
core.info(`${warningPrefix}${message}`);
@ -77,19 +57,20 @@ export function getInputAsInt(
}
export function isCacheFeatureAvailable(): boolean {
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.
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.
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;
}
return true;
logWarning(
"An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions."
);
return false;
}