actions-up 1.11.0 → 1.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.d.ts +3 -1
- package/dist/cli/index.js +84 -93
- package/dist/cli/merge-scan-results.d.ts +8 -0
- package/dist/cli/merge-scan-results.js +18 -0
- package/dist/cli/normalize-update-mode.d.ts +8 -0
- package/dist/cli/normalize-update-mode.js +6 -0
- package/dist/cli/print-mode-warning.d.ts +16 -0
- package/dist/cli/print-mode-warning.js +11 -0
- package/dist/cli/print-skipped-warning.d.ts +14 -0
- package/dist/cli/print-skipped-warning.js +10 -0
- package/dist/cli/resolve-scan-directories.d.ts +31 -0
- package/dist/cli/resolve-scan-directories.js +24 -0
- package/dist/core/api/check-updates.d.ts +4 -1
- package/dist/core/api/check-updates.js +119 -116
- package/dist/core/api/get-all-releases.d.ts +2 -1
- package/dist/core/api/get-compatible-update.d.ts +37 -0
- package/dist/core/api/get-compatible-update.js +40 -0
- package/dist/core/api/get-latest-release.d.ts +3 -3
- package/dist/core/ast/utils/extract-uses-from-steps.d.ts +12 -4
- package/dist/core/constants.d.ts +3 -1
- package/dist/core/fs/find-yaml-files-recursive.js +1 -1
- package/dist/core/interactive/prompt-update-selection.d.ts +3 -1
- package/dist/core/interactive/prompt-update-selection.js +9 -9
- package/dist/core/parsing/parse-action-reference.d.ts +16 -12
- package/dist/core/scan-github-actions.d.ts +4 -1
- package/dist/core/scan-github-actions.js +67 -68
- package/dist/core/scan-recursive.js +12 -14
- package/dist/core/versions/find-compatible-tag.d.ts +16 -0
- package/dist/core/versions/find-compatible-tag.js +27 -0
- package/dist/core/versions/get-update-level.d.ts +3 -1
- package/dist/core/versions/is-semver-like.d.ts +9 -0
- package/dist/core/versions/is-semver-like.js +4 -0
- package/dist/core/versions/normalize-version.d.ts +14 -0
- package/dist/core/versions/normalize-version.js +9 -0
- package/dist/package.js +1 -1
- package/dist/types/action-update.d.ts +30 -10
- package/dist/types/composite-action-runs.d.ts +12 -4
- package/dist/types/composite-action-step.d.ts +24 -8
- package/dist/types/composite-action-structure.d.ts +21 -7
- package/dist/types/github-action.d.ts +27 -9
- package/dist/types/github-client-context.d.ts +24 -8
- package/dist/types/github-client.d.ts +24 -8
- package/dist/types/release-info.d.ts +24 -8
- package/dist/types/scan-result.d.ts +12 -4
- package/dist/types/tag-info.d.ts +15 -5
- package/dist/types/update-mode.d.ts +3 -1
- package/dist/types/workflow-job.d.ts +27 -9
- package/dist/types/workflow-step.d.ts +21 -7
- package/dist/types/workflow-structure.d.ts +15 -5
- package/package.json +3 -8
- package/readme.md +53 -18
|
@@ -2,27 +2,26 @@ import { ACTIONS_DIRECTORY, GITHUB_DIRECTORY, WORKFLOWS_DIRECTORY } from "./cons
|
|
|
2
2
|
import { isYamlFile } from "./fs/is-yaml-file.js";
|
|
3
3
|
import { scanWorkflowFile } from "./scan-workflow-file.js";
|
|
4
4
|
import { scanActionFile } from "./scan-action-file.js";
|
|
5
|
-
import { isAbsolute, join, relative, resolve } from "node:path";
|
|
6
5
|
import { readFile, readdir, stat } from "node:fs/promises";
|
|
7
|
-
|
|
6
|
+
import { isAbsolute, join, relative, resolve } from "node:path";
|
|
7
|
+
async function scanGitHubActions(d = process.cwd(), m = GITHUB_DIRECTORY) {
|
|
8
8
|
let h = {
|
|
9
9
|
compositeActions: /* @__PURE__ */ new Map(),
|
|
10
10
|
workflows: /* @__PURE__ */ new Map(),
|
|
11
11
|
actions: []
|
|
12
|
-
}, g = resolve(
|
|
13
|
-
function _(e,
|
|
14
|
-
let
|
|
15
|
-
return
|
|
12
|
+
}, g = resolve(d);
|
|
13
|
+
function _(e, o) {
|
|
14
|
+
let s = relative(e, o);
|
|
15
|
+
return s !== "" && !s.startsWith("..") && !isAbsolute(s);
|
|
16
16
|
}
|
|
17
17
|
let v = join(g, m);
|
|
18
|
-
if (!_(g, v)) throw Error("Invalid path: detected path traversal attempt");
|
|
19
18
|
function y(e) {
|
|
20
19
|
return e.includes("..") || e.includes("/") || e.includes("\\") ? (console.warn(`Skipping invalid name: ${e}`), !1) : !0;
|
|
21
20
|
}
|
|
22
21
|
async function b(e) {
|
|
23
22
|
try {
|
|
24
|
-
let
|
|
25
|
-
return typeof
|
|
23
|
+
let o = await stat(e);
|
|
24
|
+
return typeof o.isFile == "function" ? o.isFile() : !1;
|
|
26
25
|
} catch {
|
|
27
26
|
return !1;
|
|
28
27
|
}
|
|
@@ -31,13 +30,13 @@ async function scanGitHubActions(p = process.cwd(), m = GITHUB_DIRECTORY) {
|
|
|
31
30
|
try {
|
|
32
31
|
if ((await stat(x)).isDirectory()) {
|
|
33
32
|
let e = (await readdir(x)).filter((e) => y(e) ? isYamlFile(e) : !1).map(async (e) => {
|
|
34
|
-
let
|
|
33
|
+
let o = join(x, e);
|
|
35
34
|
try {
|
|
36
|
-
let
|
|
35
|
+
let c = await scanWorkflowFile(o);
|
|
37
36
|
return {
|
|
38
37
|
path: `${m}/${WORKFLOWS_DIRECTORY}/${e}`,
|
|
39
38
|
success: !0,
|
|
40
|
-
actions:
|
|
39
|
+
actions: c
|
|
41
40
|
};
|
|
42
41
|
} catch {
|
|
43
42
|
return {
|
|
@@ -46,111 +45,111 @@ async function scanGitHubActions(p = process.cwd(), m = GITHUB_DIRECTORY) {
|
|
|
46
45
|
actions: []
|
|
47
46
|
};
|
|
48
47
|
}
|
|
49
|
-
}),
|
|
50
|
-
for (let e of
|
|
48
|
+
}), o = await Promise.all(e);
|
|
49
|
+
for (let e of o) e.success && e.path && (e.actions.length > 0 ? (h.workflows.set(e.path, e.actions), h.actions.push(...e.actions)) : h.workflows.set(e.path, []));
|
|
51
50
|
}
|
|
52
51
|
} catch {}
|
|
53
52
|
try {
|
|
54
|
-
let e = join(g, "action.yml"),
|
|
53
|
+
let e = join(g, "action.yml"), o = join(g, "action.yaml"), s = null, c = [];
|
|
55
54
|
if (await b(e)) try {
|
|
56
|
-
|
|
55
|
+
c = await scanActionFile(e), s = e;
|
|
57
56
|
} catch {
|
|
58
|
-
|
|
57
|
+
s = null;
|
|
59
58
|
}
|
|
60
|
-
if (!
|
|
61
|
-
|
|
59
|
+
if (!s && await b(o)) try {
|
|
60
|
+
c = await scanActionFile(o), s = o;
|
|
62
61
|
} catch {
|
|
63
|
-
|
|
62
|
+
s = null;
|
|
64
63
|
}
|
|
65
|
-
if (
|
|
66
|
-
let e = relative(g,
|
|
67
|
-
h.compositeActions.set(e, e),
|
|
64
|
+
if (s) {
|
|
65
|
+
let e = relative(g, s);
|
|
66
|
+
h.compositeActions.set(e, e), c.length > 0 && h.actions.push(...c);
|
|
68
67
|
}
|
|
69
68
|
} catch {}
|
|
70
69
|
let S = join(v, ACTIONS_DIRECTORY);
|
|
71
70
|
try {
|
|
72
71
|
if ((await stat(S)).isDirectory()) {
|
|
73
|
-
let
|
|
74
|
-
if (!y(
|
|
75
|
-
let
|
|
72
|
+
let o = (await readdir(S)).map(async (o) => {
|
|
73
|
+
if (!y(o)) return null;
|
|
74
|
+
let s = join(S, o);
|
|
76
75
|
try {
|
|
77
|
-
if (!(await stat(
|
|
78
|
-
let
|
|
76
|
+
if (!(await stat(s)).isDirectory()) return null;
|
|
77
|
+
let c = join(s, "action.yml"), l = [];
|
|
79
78
|
try {
|
|
80
|
-
|
|
79
|
+
l = await scanActionFile(c);
|
|
81
80
|
} catch {
|
|
82
81
|
try {
|
|
83
|
-
|
|
82
|
+
c = join(s, "action.yaml"), l = await scanActionFile(c);
|
|
84
83
|
} catch {
|
|
85
84
|
return null;
|
|
86
85
|
}
|
|
87
86
|
}
|
|
88
87
|
return {
|
|
89
|
-
path: `${m}/${ACTIONS_DIRECTORY}/${
|
|
90
|
-
name:
|
|
91
|
-
actions:
|
|
88
|
+
path: `${m}/${ACTIONS_DIRECTORY}/${o}`,
|
|
89
|
+
name: o,
|
|
90
|
+
actions: l
|
|
92
91
|
};
|
|
93
92
|
} catch {
|
|
94
93
|
return null;
|
|
95
94
|
}
|
|
96
|
-
}),
|
|
97
|
-
for (let e of
|
|
95
|
+
}), s = await Promise.all(o);
|
|
96
|
+
for (let e of s) e && (h.compositeActions.set(e.name, e.path), h.actions.push(...e.actions));
|
|
98
97
|
}
|
|
99
98
|
} catch {}
|
|
100
99
|
try {
|
|
101
100
|
let e = await getCurrentRepoSlug(g);
|
|
102
101
|
if (e) {
|
|
103
102
|
if (process.env.ACTIONS_UP_TEST_THROW === "1") throw Error("test");
|
|
104
|
-
let
|
|
105
|
-
for (let
|
|
106
|
-
if (
|
|
107
|
-
let
|
|
108
|
-
if (
|
|
109
|
-
let
|
|
110
|
-
_(g,
|
|
103
|
+
let o = /* @__PURE__ */ new Set(), s = [];
|
|
104
|
+
for (let c of h.actions) {
|
|
105
|
+
if (c.type !== "external") continue;
|
|
106
|
+
let l = c.name.split("/");
|
|
107
|
+
if (l.length < 3 || `${l[0]}/${l[1]}` !== e) continue;
|
|
108
|
+
let u = join(g, ...l.slice(2));
|
|
109
|
+
_(g, u) && (o.has(u) || (o.add(u), s.push(u)));
|
|
111
110
|
}
|
|
112
|
-
async function
|
|
113
|
-
if (
|
|
114
|
-
let
|
|
111
|
+
async function c() {
|
|
112
|
+
if (s.length === 0) return;
|
|
113
|
+
let l = s.splice(0), d = await Promise.all(l.map(async (s) => {
|
|
115
114
|
try {
|
|
116
|
-
let
|
|
115
|
+
let c = join(s, "action.yml"), l = join(s, "action.yaml"), d = c;
|
|
117
116
|
try {
|
|
118
|
-
if (!(await stat(s)).isFile()) throw Error("not a file");
|
|
119
|
-
} catch {
|
|
120
117
|
if (!(await stat(c)).isFile()) throw Error("not a file");
|
|
121
|
-
|
|
118
|
+
} catch {
|
|
119
|
+
if (!(await stat(l)).isFile()) throw Error("not a file");
|
|
120
|
+
d = l;
|
|
122
121
|
}
|
|
123
|
-
let
|
|
124
|
-
|
|
125
|
-
let
|
|
126
|
-
for (let
|
|
127
|
-
if (
|
|
128
|
-
let
|
|
129
|
-
if (
|
|
130
|
-
let
|
|
131
|
-
_(g,
|
|
122
|
+
let f = await scanActionFile(d);
|
|
123
|
+
f.length > 0 && h.actions.push(...f);
|
|
124
|
+
let p = [];
|
|
125
|
+
for (let s of f) {
|
|
126
|
+
if (s.type !== "external") continue;
|
|
127
|
+
let c = s.name.split("/");
|
|
128
|
+
if (c.length < 3 || `${c[0]}/${c[1]}` !== e) continue;
|
|
129
|
+
let l = join(g, ...c.slice(2));
|
|
130
|
+
_(g, l) && (o.has(l) || (o.add(l), p.push(l)));
|
|
132
131
|
}
|
|
133
|
-
return
|
|
132
|
+
return p;
|
|
134
133
|
} catch {
|
|
135
134
|
return [];
|
|
136
135
|
}
|
|
137
136
|
}));
|
|
138
|
-
for (let e of
|
|
139
|
-
await
|
|
137
|
+
for (let e of d) for (let o of e) s.push(o);
|
|
138
|
+
await c();
|
|
140
139
|
}
|
|
141
|
-
await
|
|
140
|
+
await c();
|
|
142
141
|
}
|
|
143
142
|
} catch {}
|
|
144
143
|
return h;
|
|
145
144
|
}
|
|
146
145
|
async function getCurrentRepoSlug(e) {
|
|
147
|
-
let
|
|
148
|
-
if (
|
|
146
|
+
let o = process.env.GITHUB_REPOSITORY;
|
|
147
|
+
if (o && /^[^\s/]+\/[^\s/]+$/u.test(o)) return o;
|
|
149
148
|
try {
|
|
150
|
-
let
|
|
151
|
-
if (
|
|
152
|
-
let
|
|
153
|
-
if (
|
|
149
|
+
let o = await readFile(join(e, ".git", "config"), "utf8"), s = o.match(/\[remote "origin"\][\s\S]*?url\s*=\s*(?<url>.+)/u)?.groups?.url?.trim();
|
|
150
|
+
if (s ||= o.match(/url\s*=\s*(?<url>.+)/u)?.groups?.url?.trim(), !s) return null;
|
|
151
|
+
let c = s.match(/github\.com[/:](?<owner>[^/]+)\/(?<repo>[^./]+)(?:\.git)?$/u);
|
|
152
|
+
if (c?.groups) return `${c.groups.owner}/${c.groups.repo}`;
|
|
154
153
|
} catch {}
|
|
155
154
|
return null;
|
|
156
155
|
}
|
|
@@ -4,22 +4,20 @@ import { isWorkflowStructure } from "./schema/workflow/is-workflow-structure.js"
|
|
|
4
4
|
import { findYamlFilesRecursive } from "./fs/find-yaml-files-recursive.js";
|
|
5
5
|
import { scanWorkflowAst } from "./ast/scanners/scan-workflow-ast.js";
|
|
6
6
|
import { readYamlDocument } from "./fs/read-yaml-document.js";
|
|
7
|
-
import { dirname,
|
|
8
|
-
async function scanRecursive(
|
|
9
|
-
let
|
|
7
|
+
import { dirname, relative, resolve } from "node:path";
|
|
8
|
+
async function scanRecursive(u, d) {
|
|
9
|
+
let f = {
|
|
10
10
|
compositeActions: /* @__PURE__ */ new Map(),
|
|
11
11
|
workflows: /* @__PURE__ */ new Map(),
|
|
12
12
|
actions: []
|
|
13
|
-
},
|
|
14
|
-
if (g !== "" && (g.startsWith("..") || isAbsolute(g))) throw Error("Invalid path: detected path traversal attempt");
|
|
15
|
-
let _;
|
|
13
|
+
}, p = resolve(u), m = resolve(p, d), h;
|
|
16
14
|
try {
|
|
17
|
-
|
|
15
|
+
h = await findYamlFilesRecursive(m);
|
|
18
16
|
} catch {
|
|
19
|
-
return
|
|
17
|
+
return f;
|
|
20
18
|
}
|
|
21
|
-
let
|
|
22
|
-
let s = relative(
|
|
19
|
+
let g = h.map(async (o) => {
|
|
20
|
+
let s = relative(p, o);
|
|
23
21
|
try {
|
|
24
22
|
let { document: c, content: l } = await readYamlDocument(o), u = c.toJSON();
|
|
25
23
|
if (isWorkflowStructure(u) && hasKey(u, "jobs")) return {
|
|
@@ -34,13 +32,13 @@ async function scanRecursive(d, f) {
|
|
|
34
32
|
};
|
|
35
33
|
} catch {}
|
|
36
34
|
return null;
|
|
37
|
-
}),
|
|
38
|
-
for (let e of
|
|
35
|
+
}), _ = await Promise.all(g);
|
|
36
|
+
for (let e of _) if (e) if (e.type === "workflow") f.workflows.set(e.path, e.actions), f.actions.push(...e.actions);
|
|
39
37
|
else {
|
|
40
38
|
let i = dirname(e.path), a = i === "." || i === "" ? e.path : i;
|
|
41
|
-
|
|
39
|
+
f.compositeActions.set(a, e.path), f.actions.push(...e.actions);
|
|
42
40
|
}
|
|
43
|
-
return
|
|
41
|
+
return f;
|
|
44
42
|
}
|
|
45
43
|
function hasKey(e, i) {
|
|
46
44
|
return typeof e == "object" && !!e && i in e;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { UpdateMode } from '../../types/update-mode';
|
|
2
|
+
import { TagInfo } from '../../types/tag-info';
|
|
3
|
+
/**
|
|
4
|
+
* Pick the newest compatible tag for the provided update mode.
|
|
5
|
+
*
|
|
6
|
+
* Compatibility rules:
|
|
7
|
+
*
|
|
8
|
+
* - `minor`: same major, greater than current.
|
|
9
|
+
* - `patch`: same major and minor, greater than current.
|
|
10
|
+
*
|
|
11
|
+
* @param tags - Available tags from GitHub API.
|
|
12
|
+
* @param currentVersion - Current action version.
|
|
13
|
+
* @param mode - Mode that limits the allowed update level.
|
|
14
|
+
* @returns Best compatible tag or null when no compatible candidate exists.
|
|
15
|
+
*/
|
|
16
|
+
export declare function findCompatibleTag(tags: TagInfo[], currentVersion: string | null, mode: Exclude<UpdateMode, 'major'>): TagInfo | null;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { normalizeVersion } from "./normalize-version.js";
|
|
2
|
+
import { isSemverLike } from "./is-semver-like.js";
|
|
3
|
+
import semver from "semver";
|
|
4
|
+
function findCompatibleTag(r, a, o) {
|
|
5
|
+
if (!a || !isSemverLike(a) || r.length === 0) return null;
|
|
6
|
+
let s = semver.valid(normalizeVersion(a));
|
|
7
|
+
if (!s) return null;
|
|
8
|
+
let c = semver.major(s), l = semver.minor(s), u = [];
|
|
9
|
+
for (let i of r) {
|
|
10
|
+
if (!isSemverLike(i.tag)) continue;
|
|
11
|
+
let r = semver.valid(normalizeVersion(i.tag));
|
|
12
|
+
r && semver.gt(r, s) && semver.major(r) === c && (o === "patch" && semver.minor(r) !== l || u.push({
|
|
13
|
+
tag: i,
|
|
14
|
+
parsed: r
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
return u.length === 0 ? null : (u.sort((e, n) => {
|
|
18
|
+
let r = semver.rcompare(e.parsed, n.parsed);
|
|
19
|
+
if (r !== 0) return r;
|
|
20
|
+
let a = getSemverSpecificity(e.tag.tag);
|
|
21
|
+
return getSemverSpecificity(n.tag.tag) - a;
|
|
22
|
+
}), u[0].tag);
|
|
23
|
+
}
|
|
24
|
+
function getSemverSpecificity(e) {
|
|
25
|
+
return e.replace(/^v/u, "").split(".").length;
|
|
26
|
+
}
|
|
27
|
+
export { findCompatibleTag };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check whether the value follows a semver-like tag pattern.
|
|
3
|
+
*
|
|
4
|
+
* Examples of accepted values: `v1`, `v1.2`, `1.2.3`.
|
|
5
|
+
*
|
|
6
|
+
* @param value - Raw value to validate.
|
|
7
|
+
* @returns True when value looks like a semver-like tag.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isSemverLike(value: undefined | string | null): boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize version string.
|
|
3
|
+
*
|
|
4
|
+
* Rules:
|
|
5
|
+
*
|
|
6
|
+
* - Remove `v` prefix before semver coercion.
|
|
7
|
+
* - Preserve SHA-like values as-is.
|
|
8
|
+
* - Return coerced semver when possible.
|
|
9
|
+
* - Return original value when coercion fails.
|
|
10
|
+
*
|
|
11
|
+
* @param version - Version string to normalize.
|
|
12
|
+
* @returns Normalized version string or null if input is empty.
|
|
13
|
+
*/
|
|
14
|
+
export declare function normalizeVersion(version: undefined | string | null): string | null;
|
package/dist/package.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const version = "1.
|
|
1
|
+
const version = "1.12.1";
|
|
2
2
|
export { version };
|
|
@@ -1,30 +1,50 @@
|
|
|
1
1
|
import { GitHubAction } from './github-action';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Update information for a GitHub Action.
|
|
4
|
+
*/
|
|
3
5
|
export interface ActionUpdate {
|
|
4
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Reason for skipping the update check.
|
|
8
|
+
*/
|
|
5
9
|
skipReason?: 'unknown' | 'branch'
|
|
6
10
|
|
|
7
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Current version string.
|
|
13
|
+
*/
|
|
8
14
|
currentVersion: string | null
|
|
9
15
|
|
|
10
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* Latest available version.
|
|
18
|
+
*/
|
|
11
19
|
latestVersion: string | null
|
|
12
20
|
|
|
13
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Status of the check for this action.
|
|
23
|
+
*/
|
|
14
24
|
status?: 'skipped' | 'ok'
|
|
15
25
|
|
|
16
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* SHA hash of the latest version.
|
|
28
|
+
*/
|
|
17
29
|
latestSha: string | null
|
|
18
30
|
|
|
19
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Publication date of the latest version (null if unknown).
|
|
33
|
+
*/
|
|
20
34
|
publishedAt: Date | null
|
|
21
35
|
|
|
22
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* The original action from scanning.
|
|
38
|
+
*/
|
|
23
39
|
action: GitHubAction
|
|
24
40
|
|
|
25
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Whether this is a major version change.
|
|
43
|
+
*/
|
|
26
44
|
isBreaking: boolean
|
|
27
45
|
|
|
28
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* Whether an update is available.
|
|
48
|
+
*/
|
|
29
49
|
hasUpdate: boolean
|
|
30
50
|
}
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { CompositeActionStep } from './composite-action-step';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Represents the runs configuration for a composite action.
|
|
4
|
+
*/
|
|
3
5
|
export interface CompositeActionRuns {
|
|
4
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Array of steps to execute.
|
|
8
|
+
*/
|
|
5
9
|
steps?: CompositeActionStep[]
|
|
6
10
|
|
|
7
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Allow additional properties.
|
|
13
|
+
*/
|
|
8
14
|
[key: string]: unknown
|
|
9
15
|
|
|
10
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* Must be 'composite' for composite actions.
|
|
18
|
+
*/
|
|
11
19
|
using?: string
|
|
12
20
|
}
|
|
@@ -1,23 +1,39 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Represents a step in a composite GitHub Action.
|
|
3
|
+
*/
|
|
2
4
|
export interface CompositeActionStep {
|
|
3
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Environment variables for this step.
|
|
7
|
+
*/
|
|
4
8
|
env?: Record<string, unknown>
|
|
5
9
|
|
|
6
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Working directory for the step.
|
|
12
|
+
*/
|
|
7
13
|
'working-directory'?: string
|
|
8
14
|
|
|
9
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Allow additional properties.
|
|
17
|
+
*/
|
|
10
18
|
[key: string]: unknown
|
|
11
19
|
|
|
12
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Shell to use for the run command.
|
|
22
|
+
*/
|
|
13
23
|
shell?: string
|
|
14
24
|
|
|
15
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Action to use for this step.
|
|
27
|
+
*/
|
|
16
28
|
uses?: string
|
|
17
29
|
|
|
18
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Display name for this step.
|
|
32
|
+
*/
|
|
19
33
|
name?: string
|
|
20
34
|
|
|
21
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Shell command to run for this step.
|
|
37
|
+
*/
|
|
22
38
|
run?: string
|
|
23
39
|
}
|
|
@@ -1,21 +1,35 @@
|
|
|
1
1
|
import { CompositeActionRuns } from './composite-action-runs';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Represents the structure of a composite GitHub Action file.
|
|
4
|
+
*/
|
|
3
5
|
export interface CompositeActionStructure {
|
|
4
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Output values from the action.
|
|
8
|
+
*/
|
|
5
9
|
outputs?: Record<string, unknown>
|
|
6
10
|
|
|
7
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Input parameters for the action.
|
|
13
|
+
*/
|
|
8
14
|
inputs?: Record<string, unknown>
|
|
9
15
|
|
|
10
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* Runs configuration for composite actions.
|
|
18
|
+
*/
|
|
11
19
|
runs?: CompositeActionRuns
|
|
12
20
|
|
|
13
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Allow additional properties.
|
|
23
|
+
*/
|
|
14
24
|
[key: string]: unknown
|
|
15
25
|
|
|
16
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Description of what the action does.
|
|
28
|
+
*/
|
|
17
29
|
description?: string
|
|
18
30
|
|
|
19
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Display name of the action.
|
|
33
|
+
*/
|
|
20
34
|
name?: string
|
|
21
35
|
}
|
|
@@ -1,26 +1,44 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Represents a GitHub Action used in workflows or composite actions.
|
|
3
|
+
*/
|
|
2
4
|
export interface GitHubAction {
|
|
3
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Type of the GitHub Action.
|
|
7
|
+
*/
|
|
4
8
|
type: 'reusable-workflow' | 'composite' | 'external' | 'docker' | 'local'
|
|
5
9
|
|
|
6
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Version or tag of the action (e.g., 'v1', 'main', commit SHA).
|
|
12
|
+
*/
|
|
7
13
|
version?: string | null
|
|
8
14
|
|
|
9
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Line number where the action is used in the file.
|
|
17
|
+
*/
|
|
10
18
|
line?: number
|
|
11
19
|
|
|
12
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Path to the file where this action is used.
|
|
22
|
+
*/
|
|
13
23
|
file?: string
|
|
14
24
|
|
|
15
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Original `uses` string from workflow, if available.
|
|
27
|
+
*/
|
|
16
28
|
uses?: string
|
|
17
29
|
|
|
18
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Name of the job where this action is used (for workflows).
|
|
32
|
+
*/
|
|
19
33
|
job?: string
|
|
20
34
|
|
|
21
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Full name of the action (e.g., 'actions/checkout').
|
|
37
|
+
*/
|
|
22
38
|
name: string
|
|
23
39
|
|
|
24
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Original `ref` string from workflow, if available.
|
|
42
|
+
*/
|
|
25
43
|
ref?: string
|
|
26
44
|
}
|
|
@@ -6,27 +6,43 @@ import { TagInfo } from './tag-info';
|
|
|
6
6
|
* number of API requests during a single run.
|
|
7
7
|
*/
|
|
8
8
|
export interface GitHubClientContext {
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Lightweight caches keyed by owner/repo (+ extra payload).
|
|
11
|
+
*/
|
|
10
12
|
caches: {
|
|
11
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Cache of reference type detections (branch/tag/null).
|
|
15
|
+
*/
|
|
12
16
|
refType: Map<string, 'branch' | 'tag' | null>
|
|
13
17
|
|
|
14
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Cache of resolved tag metadata (message/date/SHA).
|
|
20
|
+
*/
|
|
15
21
|
tagInfo: Map<string, TagInfo | null>
|
|
16
22
|
|
|
17
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Cache of resolved tag commit SHAs.
|
|
25
|
+
*/
|
|
18
26
|
tagSha: Map<string, string | null>
|
|
19
27
|
}
|
|
20
28
|
|
|
21
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* Remaining requests available per current rate-limit window.
|
|
31
|
+
*/
|
|
22
32
|
rateLimitRemaining: number
|
|
23
33
|
|
|
24
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* GitHub token, if available.
|
|
36
|
+
*/
|
|
25
37
|
token: undefined | string
|
|
26
38
|
|
|
27
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Scheduled time when rate limit resets.
|
|
41
|
+
*/
|
|
28
42
|
rateLimitReset: Date
|
|
29
43
|
|
|
30
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* GitHub REST API base URL.
|
|
46
|
+
*/
|
|
31
47
|
baseUrl: string
|
|
32
48
|
}
|