actions-up 1.13.0 → 1.14.0
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/build-json-report.d.ts +57 -36
- package/dist/cli/build-json-report.js +4 -0
- package/dist/cli/index.js +109 -94
- package/dist/cli/normalize-update-style.d.ts +8 -0
- package/dist/cli/normalize-update-style.js +6 -0
- package/dist/cli/print-skipped-warning.d.ts +4 -1
- package/dist/cli/print-skipped-warning.js +7 -3
- package/dist/core/api/check-updates.d.ts +2 -0
- package/dist/core/api/check-updates.js +98 -74
- package/dist/core/ast/update/apply-updates.d.ts +1 -1
- package/dist/core/ast/update/apply-updates.js +36 -23
- package/dist/core/interactive/prompt-update-selection.js +127 -115
- package/dist/core/updates/resolve-target-reference.d.ts +10 -0
- package/dist/core/updates/resolve-target-reference.js +24 -0
- package/dist/package.js +1 -1
- package/dist/types/action-update.d.ts +16 -1
- package/dist/types/update-style.d.ts +4 -0
- package/package.json +2 -2
- package/readme.md +24 -5
|
@@ -2,19 +2,20 @@ import { normalizeVersion } from "../versions/normalize-version.js";
|
|
|
2
2
|
import { isSemverLike } from "../versions/is-semver-like.js";
|
|
3
3
|
import { createGitHubClient } from "./create-github-client.js";
|
|
4
4
|
import semver from "semver";
|
|
5
|
-
async function checkUpdates(i, o,
|
|
6
|
-
let
|
|
7
|
-
if (
|
|
8
|
-
let
|
|
9
|
-
for (let e of
|
|
10
|
-
let t =
|
|
11
|
-
t.push(e),
|
|
5
|
+
async function checkUpdates(i, o, u) {
|
|
6
|
+
let d = u?.client ?? createGitHubClient(o), f = u?.includeBranches ?? !1, p = u?.style ?? "sha", m = i.filter((e) => e.type === "external" || e.type === "reusable-workflow");
|
|
7
|
+
if (m.length === 0) return [];
|
|
8
|
+
let h = /* @__PURE__ */ new Map();
|
|
9
|
+
for (let e of m) {
|
|
10
|
+
let t = h.get(e.name) ?? [];
|
|
11
|
+
t.push(e), h.set(e.name, t);
|
|
12
12
|
}
|
|
13
|
-
let
|
|
13
|
+
let g = {
|
|
14
14
|
rateLimitError: null,
|
|
15
15
|
rateLimitHit: !1
|
|
16
|
-
},
|
|
17
|
-
if (
|
|
16
|
+
}, _ = await [...h.keys()].reduce((n, i) => n.then(async (n) => {
|
|
17
|
+
if (g.rateLimitHit) return [...n, {
|
|
18
|
+
currentRefType: "unknown",
|
|
18
19
|
publishedAt: null,
|
|
19
20
|
version: null,
|
|
20
21
|
actionName: i,
|
|
@@ -22,62 +23,69 @@ async function checkUpdates(i, o, l) {
|
|
|
22
23
|
}];
|
|
23
24
|
let a = i.split("/");
|
|
24
25
|
if (a.length < 2) return [...n, {
|
|
26
|
+
currentRefType: "unknown",
|
|
25
27
|
publishedAt: null,
|
|
26
28
|
version: null,
|
|
27
29
|
actionName: i,
|
|
28
30
|
sha: null
|
|
29
31
|
}];
|
|
30
|
-
let [o,
|
|
31
|
-
if (!o || !
|
|
32
|
+
let [o, u] = a;
|
|
33
|
+
if (!o || !u) return [...n, {
|
|
34
|
+
currentRefType: "unknown",
|
|
32
35
|
publishedAt: null,
|
|
33
36
|
version: null,
|
|
34
37
|
actionName: i,
|
|
35
38
|
sha: null
|
|
36
39
|
}];
|
|
37
40
|
try {
|
|
38
|
-
let a =
|
|
39
|
-
if (a && !isSha(a) && !isSemverLike(a)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
let a = h.get(i)[0]?.version, p = deriveCurrentReferenceType(a);
|
|
42
|
+
if (a && !isSha(a) && !isSemverLike(a)) {
|
|
43
|
+
let e = await d.getRefType(o, u, a);
|
|
44
|
+
if (p = e === "branch" || e === "tag" ? e : p, e === "branch" && !f) return [...n, {
|
|
45
|
+
currentRefType: p,
|
|
46
|
+
skipReason: "branch",
|
|
47
|
+
status: "skipped",
|
|
48
|
+
publishedAt: null,
|
|
49
|
+
version: null,
|
|
50
|
+
actionName: i,
|
|
51
|
+
sha: null
|
|
52
|
+
}];
|
|
53
|
+
}
|
|
54
|
+
let m = await d.getLatestRelease(o, u);
|
|
55
|
+
if (!m) {
|
|
56
|
+
let e = await d.getAllReleases(o, u, 1);
|
|
57
|
+
m = e.find((e) => !e.isPrerelease) ?? e[0] ?? null;
|
|
51
58
|
}
|
|
52
|
-
if (
|
|
53
|
-
let { publishedAt: a, version: s, sha:
|
|
59
|
+
if (m) {
|
|
60
|
+
let { publishedAt: a, version: s, sha: c } = m, f = !1;
|
|
54
61
|
{
|
|
55
62
|
let n = normalizeVersion(s), i = !!(s && s.trim() !== ""), a = i && /^v?\d+$/u.test(s.trim()), o = semver.valid(n);
|
|
56
|
-
|
|
63
|
+
f = !i || a || !o || !isSemverLike(s);
|
|
57
64
|
}
|
|
58
|
-
if (
|
|
59
|
-
let a = await
|
|
65
|
+
if (f) {
|
|
66
|
+
let a = await d.getAllTags(o, u, 30);
|
|
60
67
|
if (a.length > 0) {
|
|
61
|
-
let
|
|
68
|
+
let c = a.filter((e) => isSemverLike(e.tag)).map((t) => ({
|
|
62
69
|
v: semver.valid(normalizeVersion(t.tag)),
|
|
63
70
|
raw: t
|
|
64
71
|
}));
|
|
65
|
-
if (
|
|
66
|
-
|
|
72
|
+
if (c.length > 0) {
|
|
73
|
+
c.sort((e, t) => {
|
|
67
74
|
let n = semver.rcompare(e.v, t.v);
|
|
68
75
|
if (n !== 0) return n;
|
|
69
76
|
let i = /\d+\.\d+/u.test(e.raw.tag) ? 1 : 0;
|
|
70
77
|
return (/\d+\.\d+/u.test(t.raw.tag) ? 1 : 0) - i;
|
|
71
78
|
});
|
|
72
|
-
let t =
|
|
73
|
-
if (!a || semver.gt(
|
|
79
|
+
let t = c[0].raw, a = semver.valid(normalizeVersion(s) ?? void 0);
|
|
80
|
+
if (!a || semver.gt(c[0].v, a) || semver.eq(c[0].v, a) && /\d+\.\d+/u.test(t.tag)) {
|
|
74
81
|
let e = t.tag, r = t.sha?.length ? t.sha : null;
|
|
75
82
|
if (!r && e) try {
|
|
76
|
-
r = await
|
|
83
|
+
r = await d.getTagSha(o, u, e);
|
|
77
84
|
} catch (e) {
|
|
78
85
|
if (isRateLimitError(e)) throw e;
|
|
79
86
|
}
|
|
80
87
|
return [...n, {
|
|
88
|
+
currentRefType: p,
|
|
81
89
|
version: e,
|
|
82
90
|
publishedAt: null,
|
|
83
91
|
sha: r,
|
|
@@ -88,25 +96,26 @@ async function checkUpdates(i, o, l) {
|
|
|
88
96
|
}
|
|
89
97
|
}
|
|
90
98
|
if (s) {
|
|
91
|
-
let e =
|
|
99
|
+
let e = c;
|
|
92
100
|
try {
|
|
93
|
-
|
|
101
|
+
c = await d.getTagSha(o, u, s) ?? e;
|
|
94
102
|
} catch (t) {
|
|
95
103
|
if (isRateLimitError(t)) throw t;
|
|
96
|
-
|
|
104
|
+
c = e;
|
|
97
105
|
}
|
|
98
106
|
}
|
|
99
107
|
return [...n, {
|
|
108
|
+
currentRefType: p,
|
|
100
109
|
status: "ok",
|
|
101
110
|
publishedAt: a,
|
|
102
111
|
actionName: i,
|
|
103
112
|
version: s,
|
|
104
|
-
sha:
|
|
113
|
+
sha: c
|
|
105
114
|
}];
|
|
106
115
|
}
|
|
107
|
-
let
|
|
108
|
-
if (
|
|
109
|
-
let a =
|
|
116
|
+
let g = await d.getAllTags(o, u, 30);
|
|
117
|
+
if (g.length > 0) {
|
|
118
|
+
let a = g.filter((e) => isSemverLike(e.tag)).map((t) => ({
|
|
110
119
|
v: semver.valid(normalizeVersion(t.tag)),
|
|
111
120
|
raw: t
|
|
112
121
|
})), s;
|
|
@@ -115,34 +124,38 @@ async function checkUpdates(i, o, l) {
|
|
|
115
124
|
if (n !== 0) return n;
|
|
116
125
|
let i = /\d+\.\d+/u.test(e.raw.tag) ? 1 : 0;
|
|
117
126
|
return (/\d+\.\d+/u.test(t.raw.tag) ? 1 : 0) - i;
|
|
118
|
-
}), s = a[0].raw) : s =
|
|
119
|
-
let
|
|
120
|
-
if (!f &&
|
|
121
|
-
f = await
|
|
127
|
+
}), s = a[0].raw) : s = g[0];
|
|
128
|
+
let c = s.tag, f = s.sha?.length ? s.sha : null;
|
|
129
|
+
if (!f && c) try {
|
|
130
|
+
f = await d.getTagSha(o, u, c);
|
|
122
131
|
} catch (e) {
|
|
123
132
|
if (isRateLimitError(e)) throw e;
|
|
124
133
|
}
|
|
125
134
|
return [...n, {
|
|
135
|
+
currentRefType: p,
|
|
126
136
|
status: "ok",
|
|
127
137
|
publishedAt: null,
|
|
128
138
|
actionName: i,
|
|
129
|
-
version:
|
|
139
|
+
version: c,
|
|
130
140
|
sha: f
|
|
131
141
|
}];
|
|
132
142
|
}
|
|
133
143
|
return [...n, {
|
|
144
|
+
currentRefType: p,
|
|
134
145
|
publishedAt: null,
|
|
135
146
|
version: null,
|
|
136
147
|
actionName: i,
|
|
137
148
|
sha: null
|
|
138
149
|
}];
|
|
139
150
|
} catch (e) {
|
|
140
|
-
return e instanceof Error && e.name === "GitHubRateLimitError" ? (
|
|
151
|
+
return e instanceof Error && e.name === "GitHubRateLimitError" ? (g.rateLimitHit = !0, g.rateLimitError = e, [...n, {
|
|
152
|
+
currentRefType: "unknown",
|
|
141
153
|
publishedAt: null,
|
|
142
154
|
version: null,
|
|
143
155
|
actionName: i,
|
|
144
156
|
sha: null
|
|
145
157
|
}]) : (console.warn(`Failed to check ${i}:`, e), [...n, {
|
|
158
|
+
currentRefType: "unknown",
|
|
146
159
|
publishedAt: null,
|
|
147
160
|
version: null,
|
|
148
161
|
actionName: i,
|
|
@@ -150,12 +163,13 @@ async function checkUpdates(i, o, l) {
|
|
|
150
163
|
}]);
|
|
151
164
|
}
|
|
152
165
|
}), Promise.resolve([]));
|
|
153
|
-
if (
|
|
154
|
-
let e = !!(o ?? process.env.GITHUB_TOKEN), t = `${
|
|
166
|
+
if (g.rateLimitError) {
|
|
167
|
+
let e = !!(o ?? process.env.GITHUB_TOKEN), t = `${g.rateLimitError.message || "GitHub API rate limit exceeded."}\n${e ? "Wait for reset or reduce request rate." : "Please set GITHUB_TOKEN environment variable to increase the limit.\nSee: https://github.com/azat-io/actions-up?tab=readme-ov-file#github-token"}`, n = Error(t);
|
|
155
168
|
throw n.name = "GitHubRateLimitError", n;
|
|
156
169
|
}
|
|
157
|
-
let
|
|
158
|
-
for (let e of
|
|
170
|
+
let v = /* @__PURE__ */ new Map();
|
|
171
|
+
for (let e of _) v.set(e.actionName, {
|
|
172
|
+
currentRefType: e.currentRefType,
|
|
159
173
|
publishedAt: e.publishedAt,
|
|
160
174
|
actionName: e.actionName,
|
|
161
175
|
skipReason: e.skipReason,
|
|
@@ -163,58 +177,65 @@ async function checkUpdates(i, o, l) {
|
|
|
163
177
|
status: e.status,
|
|
164
178
|
sha: e.sha
|
|
165
179
|
});
|
|
166
|
-
let
|
|
167
|
-
for (let e of
|
|
168
|
-
let t =
|
|
169
|
-
t ?
|
|
180
|
+
let y = [];
|
|
181
|
+
for (let e of m) {
|
|
182
|
+
let t = v.get(e.name);
|
|
183
|
+
t ? y.push(createUpdate(e, {
|
|
170
184
|
publishedAt: t.publishedAt,
|
|
171
185
|
version: t.version,
|
|
172
186
|
sha: t.sha
|
|
173
187
|
}, {
|
|
188
|
+
currentRefType: t.currentRefType,
|
|
174
189
|
skipReason: t.skipReason,
|
|
175
|
-
status: t.status
|
|
176
|
-
|
|
190
|
+
status: t.status,
|
|
191
|
+
style: p
|
|
192
|
+
})) : y.push(createUpdate(e, {
|
|
177
193
|
publishedAt: null,
|
|
178
194
|
version: null,
|
|
179
195
|
sha: null
|
|
196
|
+
}, {
|
|
197
|
+
currentRefType: deriveCurrentReferenceType(e.version),
|
|
198
|
+
style: p
|
|
180
199
|
}));
|
|
181
200
|
}
|
|
182
|
-
return
|
|
201
|
+
return y;
|
|
183
202
|
}
|
|
184
|
-
function createUpdate(t, n, i
|
|
185
|
-
let { version: a, sha: c, publishedAt: l } = n, u = t.version ?? "unknown", d = normalizeVersion(u), f = a ? normalizeVersion(a) : null, p = i.status ?? "ok",
|
|
186
|
-
if (
|
|
203
|
+
function createUpdate(t, n, i) {
|
|
204
|
+
let { version: a, sha: c, publishedAt: l } = n, u = t.version ?? "unknown", d = normalizeVersion(u), f = a ? normalizeVersion(a) : null, p = i.currentRefType, { style: m } = i, h = i.status ?? "ok", g = i.skipReason, _ = !1, v = !1;
|
|
205
|
+
if (h === "skipped") return {
|
|
206
|
+
currentRefType: p,
|
|
187
207
|
currentVersion: u,
|
|
188
208
|
isBreaking: !1,
|
|
189
209
|
hasUpdate: !1,
|
|
190
210
|
latestVersion: a,
|
|
191
211
|
publishedAt: l,
|
|
192
|
-
skipReason:
|
|
212
|
+
skipReason: g,
|
|
193
213
|
latestSha: c,
|
|
194
214
|
action: t,
|
|
195
|
-
status:
|
|
215
|
+
status: h
|
|
196
216
|
};
|
|
197
|
-
if (d && isSha(d)) c ?
|
|
217
|
+
if (d && isSha(d)) c ? _ = !compareSha(d, c) : f && (_ = !0);
|
|
198
218
|
else if (d && f) {
|
|
199
219
|
let e = semver.valid(d), n = semver.valid(f);
|
|
200
220
|
if (e && n) {
|
|
201
|
-
if (
|
|
221
|
+
if (_ = semver.lt(e, n), _) {
|
|
202
222
|
let t = semver.major(e);
|
|
203
|
-
|
|
223
|
+
v = semver.major(n) > t;
|
|
204
224
|
}
|
|
205
|
-
!
|
|
206
|
-
} else d !== f && (
|
|
225
|
+
!_ && semver.eq(e, n) && !isSha(t.version) && c && m === "sha" && (_ = !0, v = !1);
|
|
226
|
+
} else d !== f && (_ = !0);
|
|
207
227
|
}
|
|
208
228
|
return {
|
|
229
|
+
currentRefType: p,
|
|
209
230
|
currentVersion: u,
|
|
210
231
|
latestVersion: a,
|
|
211
232
|
publishedAt: l,
|
|
212
|
-
isBreaking:
|
|
213
|
-
skipReason:
|
|
233
|
+
isBreaking: v,
|
|
234
|
+
skipReason: g,
|
|
214
235
|
latestSha: c,
|
|
215
|
-
hasUpdate:
|
|
236
|
+
hasUpdate: _,
|
|
216
237
|
action: t,
|
|
217
|
-
status:
|
|
238
|
+
status: h
|
|
218
239
|
};
|
|
219
240
|
}
|
|
220
241
|
function compareSha(e, t) {
|
|
@@ -226,6 +247,9 @@ function isSha(e) {
|
|
|
226
247
|
let t = e.replace(/^v/u, "");
|
|
227
248
|
return /^[0-9a-f]{7,40}$/iu.test(t);
|
|
228
249
|
}
|
|
250
|
+
function deriveCurrentReferenceType(e) {
|
|
251
|
+
return e ? isSha(e) ? "sha" : isSemverLike(e) ? "tag" : "unknown" : "unknown";
|
|
252
|
+
}
|
|
229
253
|
function isRateLimitError(e) {
|
|
230
254
|
return e instanceof Error && e.name === "GitHubRateLimitError";
|
|
231
255
|
}
|
|
@@ -1,40 +1,53 @@
|
|
|
1
1
|
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
async function applyUpdates(
|
|
3
|
-
let
|
|
4
|
-
for (let e of
|
|
5
|
-
let { file:
|
|
6
|
-
if (!
|
|
7
|
-
let
|
|
8
|
-
|
|
2
|
+
async function applyUpdates(r) {
|
|
3
|
+
let i = /* @__PURE__ */ new Map();
|
|
4
|
+
for (let e of r) {
|
|
5
|
+
let { file: n } = e.action;
|
|
6
|
+
if (!n) continue;
|
|
7
|
+
let r = i.get(n) ?? [];
|
|
8
|
+
r.push(e), i.set(n, r);
|
|
9
9
|
}
|
|
10
|
-
let
|
|
11
|
-
let
|
|
12
|
-
for (let e of
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
let a = [...i.entries()].map(async ([r, i]) => {
|
|
11
|
+
let a = await readFile(r, "utf8");
|
|
12
|
+
for (let e of i) {
|
|
13
|
+
let n = e.targetRef ?? e.latestSha, r = e.targetRefStyle ?? (e.latestSha ? "sha" : null);
|
|
14
|
+
if (!n || !r) continue;
|
|
15
|
+
function i(e) {
|
|
15
16
|
return e.replaceAll(/[$()*+\-./?[\\\]^{|}]/gu, String.raw`\$&`);
|
|
16
17
|
}
|
|
17
|
-
let
|
|
18
|
-
if (
|
|
18
|
+
let o = i(e.action.name), s = e.currentVersion ? i(e.currentVersion) : "";
|
|
19
|
+
if (o.includes("\n") || o.includes("\r")) {
|
|
19
20
|
console.error(`Invalid action name: ${e.action.name}`);
|
|
20
21
|
continue;
|
|
21
22
|
}
|
|
22
|
-
if (
|
|
23
|
+
if (s && (s.includes("\n") || s.includes("\r"))) {
|
|
23
24
|
console.error(`Invalid version: ${e.currentVersion}`);
|
|
24
25
|
continue;
|
|
25
26
|
}
|
|
26
|
-
if (
|
|
27
|
-
console.error(`Invalid
|
|
27
|
+
if (n.includes("\n") || n.includes("\r") || n.trim() === "") {
|
|
28
|
+
console.error(`Invalid target ref: ${n}`);
|
|
28
29
|
continue;
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
if (r === "sha" && !/^[\da-f]{40}$/iu.test(n)) {
|
|
32
|
+
console.error(`Invalid SHA format: ${n}`);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
let c = String.raw`['"]?\buses\b['"]?\s*:\s*`, l = String.raw`(?:^[^\S\n]*(?:-[^\S\n]*)?|[{\[,][^\S\n]*)` + c, u = new RegExp(String.raw`(?<prefix>${l})` + String.raw`(?<quote>['"]?)` + String.raw`(?<name>${o})@${s}` + String.raw`\k<quote>` + String.raw`(?<after>[ \t\]}{,]*)` + String.raw`(?<comment>[^\S\r\n]*#[^\r\n]*)?`, "gm");
|
|
36
|
+
a = a.replace(u, (i, ...a) => {
|
|
37
|
+
let o = a.at(-3), c = a.at(-2), l = a.at(-1), u = c.indexOf("\n", o + i.length), d = (u === -1 ? c.slice(o + i.length) : c.slice(o + i.length, u)).trim().length > 0, f = l.after.endsWith(" ") ? "" : " ", p = "";
|
|
38
|
+
if (r === "sha") p = d && !l.comment && s !== "" ? "" : `${f}# ${e.latestVersion}`;
|
|
39
|
+
else if (l.comment && !looksLikeInlineVersionComment(l.comment)) {
|
|
40
|
+
let { comment: e } = l;
|
|
41
|
+
p = e;
|
|
42
|
+
}
|
|
43
|
+
return `${`${l.prefix}${l.quote}${l.name}`}@${`${n}${l.quote}${l.after}${p}`}`;
|
|
34
44
|
});
|
|
35
45
|
}
|
|
36
|
-
await writeFile(
|
|
46
|
+
await writeFile(r, a, "utf8");
|
|
37
47
|
});
|
|
38
|
-
await Promise.all(
|
|
48
|
+
await Promise.all(a);
|
|
49
|
+
}
|
|
50
|
+
function looksLikeInlineVersionComment(e) {
|
|
51
|
+
return /^#\s*[Vv]?\d+(?:\.\d+){0,2}(?:[+-][\w\-.]+)?\s*$/u.test(e.trim());
|
|
39
52
|
}
|
|
40
53
|
export { applyUpdates };
|