actions-up 1.4.1 → 1.4.2
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/bin/actions-up.js +0 -0
- package/dist/core/api/make-request.js +1 -2
- package/dist/core/api/resolve-github-token-sync.js +7 -7
- package/dist/core/ast/scanners/scan-workflow-ast.js +7 -9
- package/dist/core/interactive/pad-string.js +2 -4
- package/dist/core/interactive/prompt-update-selection.js +96 -92
- package/dist/core/scan-github-actions.js +6 -8
- package/dist/package.js +1 -1
- package/package.json +2 -2
package/bin/actions-up.js
CHANGED
|
File without changes
|
|
@@ -19,20 +19,20 @@ function resolveGitHubTokenSync() {
|
|
|
19
19
|
if (e) return e;
|
|
20
20
|
} catch {}
|
|
21
21
|
try {
|
|
22
|
-
let t = join(process.cwd(), ".git", "config"),
|
|
23
|
-
if (
|
|
24
|
-
let
|
|
25
|
-
for (let e of
|
|
22
|
+
let t = readFileSync(join(process.cwd(), ".git", "config"), "utf8"), r = t.match(/^\s*(?:github\.(?:oauth-token|token)|hub\.oauthtoken)\s*=\s*(?<token>\S[^\n\r]*)$/mu)?.groups?.token?.trim();
|
|
23
|
+
if (r) return r;
|
|
24
|
+
let i = null;
|
|
25
|
+
for (let e of t.split(/\r?\n/u)) {
|
|
26
26
|
let t = e.trim(), n = t.match(/^\[(?<name>[^\]]+)\]$/u);
|
|
27
27
|
if (n?.groups) {
|
|
28
|
-
|
|
28
|
+
i = n.groups.name.toLowerCase();
|
|
29
29
|
continue;
|
|
30
30
|
}
|
|
31
|
-
if (
|
|
31
|
+
if (i === "github") {
|
|
32
32
|
let e = t.match(/^(?:oauth-token|token)\s*=\s*(?<val>\S[^\n\r]*)$/u);
|
|
33
33
|
if (e?.groups?.val) return e.groups.val.trim();
|
|
34
34
|
}
|
|
35
|
-
if (
|
|
35
|
+
if (i === "hub") {
|
|
36
36
|
let e = t.match(/^oauthtoken\s*=\s*(?<val>\S[^\n\r]*)$/u);
|
|
37
37
|
if (e?.groups?.val) return e.groups.val.trim();
|
|
38
38
|
}
|
|
@@ -5,17 +5,15 @@ import { isPair } from "../guards/is-pair.js";
|
|
|
5
5
|
import { extractUsesFromSteps } from "../utils/extract-uses-from-steps.js";
|
|
6
6
|
import { findMapPair } from "../utils/find-map-pair.js";
|
|
7
7
|
function scanWorkflowAst(o, s, c) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
let
|
|
13
|
-
for (let e of u.value.items) {
|
|
8
|
+
if (!isWorkflowStructure(o.toJSON()) || !o.contents || !isYAMLMap(o.contents)) return [];
|
|
9
|
+
let l = findMapPair(o.contents, "jobs");
|
|
10
|
+
if (!l?.value || !isYAMLMap(l.value)) return [];
|
|
11
|
+
let u = [];
|
|
12
|
+
for (let e of l.value.items) {
|
|
14
13
|
if (!isPair(e) || !e.value || !isNode(e.value) || !isYAMLMap(e.value)) continue;
|
|
15
14
|
let o = findMapPair(e.value, "steps");
|
|
16
|
-
|
|
17
|
-
d.push(...extractUsesFromSteps(o.value, c, s));
|
|
15
|
+
o?.value && u.push(...extractUsesFromSteps(o.value, c, s));
|
|
18
16
|
}
|
|
19
|
-
return
|
|
17
|
+
return u;
|
|
20
18
|
}
|
|
21
19
|
export { scanWorkflowAst };
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { stripAnsi } from "./strip-ansi.js";
|
|
2
2
|
function padString(t, n) {
|
|
3
|
-
let r = stripAnsi(t)
|
|
4
|
-
|
|
5
|
-
let a = " ".repeat(i);
|
|
6
|
-
return t + a;
|
|
3
|
+
let r = n - stripAnsi(t).length;
|
|
4
|
+
return r <= 0 ? t : t + " ".repeat(r);
|
|
7
5
|
}
|
|
8
6
|
export { padString };
|
|
@@ -7,98 +7,99 @@ import pc from "picocolors";
|
|
|
7
7
|
import { readFile } from "node:fs/promises";
|
|
8
8
|
import enquirer from "enquirer";
|
|
9
9
|
import path from "node:path";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
o
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
var MIN_ACTION_WIDTH = 56, MIN_CURRENT_WIDTH = 16;
|
|
11
|
+
async function promptUpdateSelection(o) {
|
|
12
|
+
if (o.length === 0) return null;
|
|
13
|
+
let c = o.filter((e) => e.hasUpdate);
|
|
14
|
+
if (c.length === 0) return console.info(pc.green("✓ All actions are up to date!")), null;
|
|
15
|
+
let p = /* @__PURE__ */ new Map();
|
|
16
|
+
for (let [e, a] of c.entries()) {
|
|
17
|
+
let o = a.action.file ?? "unknown file", s = path.relative(path.join(process.cwd(), GITHUB_DIRECTORY), o);
|
|
18
|
+
s === "" && (s = o);
|
|
19
|
+
let c = p.get(s) ?? [];
|
|
20
|
+
c.push({
|
|
21
|
+
update: a,
|
|
21
22
|
index: e
|
|
22
|
-
}),
|
|
23
|
+
}), p.set(s, c);
|
|
23
24
|
}
|
|
24
|
-
let
|
|
25
|
-
let
|
|
25
|
+
let g = await Promise.all(c.map(async (e) => {
|
|
26
|
+
let i = formatVersionOrSha(e.currentVersion), a = e.currentVersion ?? void 0;
|
|
26
27
|
if (!e.currentVersion || !isSha(e.currentVersion)) return {
|
|
27
|
-
effectiveForDiff:
|
|
28
|
-
display:
|
|
28
|
+
effectiveForDiff: a,
|
|
29
|
+
display: i
|
|
29
30
|
};
|
|
30
|
-
let
|
|
31
|
-
if (
|
|
32
|
-
let
|
|
33
|
-
|
|
31
|
+
let o = await tryReadInlineVersionComment(e.action.file, e.action.line);
|
|
32
|
+
if (o) {
|
|
33
|
+
let c = e.currentVersion.slice(0, 7);
|
|
34
|
+
i = `${formatVersionOrSha(o)} ${pc.gray(`(${c})`)}`, a = o;
|
|
34
35
|
}
|
|
35
36
|
return {
|
|
36
|
-
effectiveForDiff:
|
|
37
|
-
display:
|
|
37
|
+
effectiveForDiff: a,
|
|
38
|
+
display: i
|
|
38
39
|
};
|
|
39
|
-
})),
|
|
40
|
-
for (let [e,
|
|
41
|
-
let
|
|
42
|
-
|
|
40
|
+
})), _ = [], v = stripAnsi("Action").length, y = stripAnsi("Current").length;
|
|
41
|
+
for (let [e, i] of c.entries()) {
|
|
42
|
+
let o = i.action.name, s = g[e].display;
|
|
43
|
+
v = Math.max(v, o.length), y = Math.max(y, stripAnsi(s).length);
|
|
43
44
|
}
|
|
44
|
-
let
|
|
45
|
-
for (let [
|
|
46
|
-
let
|
|
47
|
-
if (!
|
|
48
|
-
console.warn(`Unexpected missing group for file: ${
|
|
45
|
+
let b = Math.max(v, MIN_ACTION_WIDTH), x = Math.max(y, MIN_CURRENT_WIDTH), S = [...p.keys()].toSorted();
|
|
46
|
+
for (let [i, a] of S.entries()) {
|
|
47
|
+
let o = p.get(a);
|
|
48
|
+
if (!o) {
|
|
49
|
+
console.warn(`Unexpected missing group for file: ${a}`);
|
|
49
50
|
continue;
|
|
50
51
|
}
|
|
51
|
-
let
|
|
52
|
-
|
|
52
|
+
let c = [], l = o;
|
|
53
|
+
c.push({
|
|
53
54
|
current: "Current",
|
|
54
55
|
action: "Action",
|
|
55
56
|
target: "Target",
|
|
56
57
|
arrow: "❯"
|
|
57
58
|
});
|
|
58
|
-
for (let { update:
|
|
59
|
-
let
|
|
60
|
-
if (
|
|
61
|
-
let e =
|
|
62
|
-
|
|
59
|
+
for (let { update: i, index: a } of l) {
|
|
60
|
+
let o = !!i.latestSha, l = g[a].display, u = g[a]?.effectiveForDiff ?? i.currentVersion, d = formatVersion(i.latestVersion, u), f = i.action.name;
|
|
61
|
+
if (i.latestSha) {
|
|
62
|
+
let e = i.latestSha.slice(0, 7);
|
|
63
|
+
d = `${d} ${pc.gray(`(${e})`)}`;
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
-
action:
|
|
66
|
-
target:
|
|
65
|
+
o || (d = pc.gray(d), l = pc.gray(l), f = pc.gray(f)), c.push({
|
|
66
|
+
action: f,
|
|
67
|
+
target: d,
|
|
67
68
|
arrow: "❯",
|
|
68
|
-
current:
|
|
69
|
+
current: l
|
|
69
70
|
});
|
|
70
71
|
}
|
|
71
|
-
let
|
|
72
|
-
for (let [e,
|
|
73
|
-
let
|
|
74
|
-
if (
|
|
75
|
-
message: pc.gray(` ○ ${
|
|
72
|
+
let u = Math.max(b, MIN_ACTION_WIDTH), m = Math.max(x, MIN_CURRENT_WIDTH), h = [];
|
|
73
|
+
for (let [e, i] of c.entries()) {
|
|
74
|
+
let a = e === 0, o = formatTableRow(i, u, m);
|
|
75
|
+
if (a) h.push({
|
|
76
|
+
message: pc.gray(` ○ ${o}`),
|
|
76
77
|
role: "separator",
|
|
77
78
|
indent: "",
|
|
78
79
|
name: ""
|
|
79
80
|
});
|
|
80
81
|
else {
|
|
81
|
-
let
|
|
82
|
-
if (!
|
|
83
|
-
let { update:
|
|
84
|
-
|
|
85
|
-
message:
|
|
86
|
-
value: String(
|
|
87
|
-
name: String(
|
|
88
|
-
disabled: !
|
|
82
|
+
let i = l[e - 1];
|
|
83
|
+
if (!i) continue;
|
|
84
|
+
let { update: a, index: s } = i, c = !!a.latestSha, u = c && !a.isBreaking;
|
|
85
|
+
h.push({
|
|
86
|
+
message: o,
|
|
87
|
+
value: String(s),
|
|
88
|
+
name: String(s),
|
|
89
|
+
disabled: !c,
|
|
89
90
|
indent: "",
|
|
90
|
-
enabled:
|
|
91
|
+
enabled: u
|
|
91
92
|
});
|
|
92
93
|
}
|
|
93
94
|
}
|
|
94
|
-
|
|
95
|
-
message: pc.gray(
|
|
96
|
-
value: `label|${
|
|
97
|
-
choices:
|
|
98
|
-
name: `label|${
|
|
95
|
+
_.push({
|
|
96
|
+
message: pc.gray(a),
|
|
97
|
+
value: `label|${a}`,
|
|
98
|
+
choices: h,
|
|
99
|
+
name: `label|${a}`,
|
|
99
100
|
isGroupLabel: !0,
|
|
100
101
|
enabled: !1
|
|
101
|
-
}),
|
|
102
|
+
}), i < S.length - 1 && _.push({
|
|
102
103
|
role: "separator",
|
|
103
104
|
message: " ",
|
|
104
105
|
name: ""
|
|
@@ -106,22 +107,22 @@ async function promptUpdateSelection(a) {
|
|
|
106
107
|
}
|
|
107
108
|
try {
|
|
108
109
|
let e = {
|
|
109
|
-
indicator(e,
|
|
110
|
-
if (
|
|
111
|
-
let e = (
|
|
112
|
-
return ` ${pc.gray(
|
|
110
|
+
indicator(e, i) {
|
|
111
|
+
if (i.isGroupLabel) {
|
|
112
|
+
let e = (i.choices ?? []).filter((e) => !("role" in e)), a = e.length, o = e.filter((e) => !!e.enabled).length === a ? "●" : "○";
|
|
113
|
+
return ` ${pc.gray(o)}`;
|
|
113
114
|
}
|
|
114
|
-
return ` ${
|
|
115
|
+
return ` ${i.enabled ? "●" : "○"}`;
|
|
115
116
|
},
|
|
116
117
|
message: `Choose which actions to update (Press ${pc.cyan("<space>")} to select, ${pc.cyan("<a>")} to toggle all, ${pc.cyan("<i>")} to invert selection)`,
|
|
117
|
-
cancel() {
|
|
118
|
-
return console.info(pc.yellow("\nSelection cancelled")), null;
|
|
119
|
-
},
|
|
120
118
|
styles: {
|
|
121
119
|
success: pc.reset,
|
|
122
120
|
em: pc.bgBlack,
|
|
123
121
|
dark: pc.reset
|
|
124
122
|
},
|
|
123
|
+
cancel() {
|
|
124
|
+
return logSelectionCancelled(), null;
|
|
125
|
+
},
|
|
125
126
|
j() {
|
|
126
127
|
return this.down?.() ?? Promise.resolve([]);
|
|
127
128
|
},
|
|
@@ -132,49 +133,52 @@ async function promptUpdateSelection(a) {
|
|
|
132
133
|
type: "multiselect",
|
|
133
134
|
name: "selected",
|
|
134
135
|
pointer: "❯",
|
|
135
|
-
choices:
|
|
136
|
-
}, { selected:
|
|
137
|
-
for (let e of
|
|
136
|
+
choices: _
|
|
137
|
+
}, { selected: i } = await enquirer.prompt(e), a = /* @__PURE__ */ new Set();
|
|
138
|
+
for (let e of i) {
|
|
138
139
|
if (e.startsWith("label|")) {
|
|
139
|
-
let
|
|
140
|
-
for (let { update: e, index:
|
|
140
|
+
let i = e.slice(6), o = p.get(i) ?? [];
|
|
141
|
+
for (let { update: e, index: i } of o) e.latestSha && a.add(i);
|
|
141
142
|
continue;
|
|
142
143
|
}
|
|
143
|
-
let
|
|
144
|
-
Number.isFinite(
|
|
144
|
+
let i = Number.parseInt(e, 10);
|
|
145
|
+
Number.isFinite(i) && a.add(i);
|
|
145
146
|
}
|
|
146
|
-
let
|
|
147
|
-
for (let [e,
|
|
148
|
-
return
|
|
147
|
+
let o = [];
|
|
148
|
+
for (let [e, i] of c.entries()) a.has(e) && i.latestSha && o.push(i);
|
|
149
|
+
return o.length === 0 ? (console.info(pc.yellow("\nNo actions selected")), null) : o;
|
|
149
150
|
} catch (e) {
|
|
150
|
-
if (e instanceof Error && (e.message.includes("cancelled") || e.message.includes("ESC") || e.name === "ExitPromptError")) return
|
|
151
|
+
if (e instanceof Error && (e.message.includes("cancelled") || e.message.includes("ESC") || e.name === "ExitPromptError")) return logSelectionCancelled(), null;
|
|
151
152
|
throw console.error(pc.red("Unexpected error during selection:"), e), e;
|
|
152
153
|
}
|
|
153
154
|
}
|
|
154
|
-
async function tryReadInlineVersionComment(e,
|
|
155
|
+
async function tryReadInlineVersionComment(e, i) {
|
|
155
156
|
try {
|
|
156
|
-
if (!e || !
|
|
157
|
-
let
|
|
158
|
-
if (
|
|
159
|
-
let
|
|
160
|
-
if (
|
|
157
|
+
if (!e || !i || i <= 0) return null;
|
|
158
|
+
let a = (await readFile(e, "utf8")).split("\n"), o = i - 1;
|
|
159
|
+
if (o < 0 || o >= a.length) return null;
|
|
160
|
+
let s = a[o].match(/#\s*(?<version>[Vv]?\d+(?:\.\d+){0,2}(?:[+-][\w\-.]+)?)/u);
|
|
161
|
+
if (s?.groups?.version) return s.groups.version;
|
|
161
162
|
} catch {}
|
|
162
163
|
return null;
|
|
163
164
|
}
|
|
164
|
-
function formatTableRow(e,
|
|
165
|
+
function formatTableRow(e, i, a) {
|
|
165
166
|
return [
|
|
166
|
-
padString(e.action,
|
|
167
|
-
padString(e.current,
|
|
167
|
+
padString(e.action, i),
|
|
168
|
+
padString(e.current, a),
|
|
168
169
|
e.arrow,
|
|
169
170
|
e.target
|
|
170
171
|
].join(" ").replace(/\s+$/u, "");
|
|
171
172
|
}
|
|
172
173
|
function isSha(e) {
|
|
173
174
|
if (!e) return !1;
|
|
174
|
-
let
|
|
175
|
-
return /^[0-9a-f]{7,40}$/iu.test(
|
|
175
|
+
let i = e.replace(/^v/u, "");
|
|
176
|
+
return /^[0-9a-f]{7,40}$/iu.test(i);
|
|
176
177
|
}
|
|
177
178
|
function formatVersionOrSha(e) {
|
|
178
179
|
return e ? isSha(e) ? e.slice(0, 7) : e.replace(/^v/u, "") : pc.gray("unknown");
|
|
179
180
|
}
|
|
181
|
+
function logSelectionCancelled() {
|
|
182
|
+
console.info(`\r\u001B[K${pc.yellow("Selection cancelled")}`);
|
|
183
|
+
}
|
|
180
184
|
export { promptUpdateSelection };
|
|
@@ -93,8 +93,7 @@ async function scanGitHubActions(d = process.cwd()) {
|
|
|
93
93
|
let l = c.name.split("/");
|
|
94
94
|
if (l.length < 3 || `${l[0]}/${l[1]}` !== e) continue;
|
|
95
95
|
let u = join(h, ...l.slice(2));
|
|
96
|
-
|
|
97
|
-
o.add(u), s.push(u);
|
|
96
|
+
g(h, u) && (o.has(u) || (o.add(u), s.push(u)));
|
|
98
97
|
}
|
|
99
98
|
async function c() {
|
|
100
99
|
if (s.length === 0) return;
|
|
@@ -115,8 +114,7 @@ async function scanGitHubActions(d = process.cwd()) {
|
|
|
115
114
|
let c = s.name.split("/");
|
|
116
115
|
if (c.length < 3 || `${c[0]}/${c[1]}` !== e) continue;
|
|
117
116
|
let l = join(h, ...c.slice(2));
|
|
118
|
-
|
|
119
|
-
o.add(l), p.push(l);
|
|
117
|
+
g(h, l) && (o.has(l) || (o.add(l), p.push(l)));
|
|
120
118
|
}
|
|
121
119
|
return p;
|
|
122
120
|
} catch {
|
|
@@ -135,10 +133,10 @@ async function getCurrentRepoSlug(e) {
|
|
|
135
133
|
let o = process.env.GITHUB_REPOSITORY;
|
|
136
134
|
if (o && /^[^\s/]+\/[^\s/]+$/u.test(o)) return o;
|
|
137
135
|
try {
|
|
138
|
-
let o = join(e, ".git", "config"),
|
|
139
|
-
if (
|
|
140
|
-
let
|
|
141
|
-
if (
|
|
136
|
+
let o = await readFile(join(e, ".git", "config"), "utf8"), s = o.match(/\[remote "origin"\][\s\S]*?url\s*=\s*(?<url>.+)/u)?.groups?.url?.trim();
|
|
137
|
+
if (s ||= o.match(/url\s*=\s*(?<url>.+)/u)?.groups?.url?.trim(), !s) return null;
|
|
138
|
+
let c = s.match(/github\.com[/:](?<owner>[^/]+)\/(?<repo>[^./]+)(?:\.git)?$/u);
|
|
139
|
+
if (c?.groups) return `${c.groups.owner}/${c.groups.repo}`;
|
|
142
140
|
} catch {}
|
|
143
141
|
return null;
|
|
144
142
|
}
|
package/dist/package.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const version = "1.4.
|
|
1
|
+
const version = "1.4.2";
|
|
2
2
|
export { version };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "actions-up",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"description": "Interactive CLI tool to update GitHub Actions to latest versions with SHA pinning",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"github-actions",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"enquirer": "^2.4.1",
|
|
41
41
|
"nanospinner": "^1.2.2",
|
|
42
42
|
"picocolors": "^1.1.1",
|
|
43
|
-
"semver": "^7.7.
|
|
43
|
+
"semver": "^7.7.3",
|
|
44
44
|
"yaml": "^2.8.1"
|
|
45
45
|
},
|
|
46
46
|
"engines": {
|