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.
@@ -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, l) {
6
- let u = l?.client ?? createGitHubClient(o), d = l?.includeBranches ?? !1, f = i.filter((e) => e.type === "external" || e.type === "reusable-workflow");
7
- if (f.length === 0) return [];
8
- let p = /* @__PURE__ */ new Map();
9
- for (let e of f) {
10
- let t = p.get(e.name) ?? [];
11
- t.push(e), p.set(e.name, t);
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 m = {
13
+ let g = {
14
14
  rateLimitError: null,
15
15
  rateLimitHit: !1
16
- }, h = await [...p.keys()].reduce((n, i) => n.then(async (n) => {
17
- if (m.rateLimitHit) return [...n, {
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, l] = a;
31
- if (!o || !l) return [...n, {
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 = p.get(i)[0]?.version;
39
- if (a && !isSha(a) && !isSemverLike(a) && await u.getRefType(o, l, a) === "branch" && !d) return [...n, {
40
- skipReason: "branch",
41
- status: "skipped",
42
- publishedAt: null,
43
- version: null,
44
- actionName: i,
45
- sha: null
46
- }];
47
- let f = await u.getLatestRelease(o, l);
48
- if (!f) {
49
- let e = await u.getAllReleases(o, l, 1);
50
- f = e.find((e) => !e.isPrerelease) ?? e[0] ?? null;
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 (f) {
53
- let { publishedAt: a, version: s, sha: d } = f, p = !1;
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
- p = !i || a || !o || !isSemverLike(s);
63
+ f = !i || a || !o || !isSemverLike(s);
57
64
  }
58
- if (p) {
59
- let a = await u.getAllTags(o, l, 30);
65
+ if (f) {
66
+ let a = await d.getAllTags(o, u, 30);
60
67
  if (a.length > 0) {
61
- let d = a.filter((e) => isSemverLike(e.tag)).map((t) => ({
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 (d.length > 0) {
66
- d.sort((e, t) => {
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 = d[0].raw, a = semver.valid(normalizeVersion(s) ?? void 0);
73
- if (!a || semver.gt(d[0].v, a) || semver.eq(d[0].v, a) && /\d+\.\d+/u.test(t.tag)) {
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 u.getTagSha(o, l, e);
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 = d;
99
+ let e = c;
92
100
  try {
93
- d = await u.getTagSha(o, l, s) ?? e;
101
+ c = await d.getTagSha(o, u, s) ?? e;
94
102
  } catch (t) {
95
103
  if (isRateLimitError(t)) throw t;
96
- d = e;
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: d
113
+ sha: c
105
114
  }];
106
115
  }
107
- let m = await u.getAllTags(o, l, 30);
108
- if (m.length > 0) {
109
- let a = m.filter((e) => isSemverLike(e.tag)).map((t) => ({
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 = m[0];
119
- let d = s.tag, f = s.sha?.length ? s.sha : null;
120
- if (!f && d) try {
121
- f = await u.getTagSha(o, l, d);
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: d,
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" ? (m.rateLimitHit = !0, m.rateLimitError = e, [...n, {
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 (m.rateLimitError) {
154
- let e = !!(o ?? process.env.GITHUB_TOKEN), t = `${m.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);
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 g = /* @__PURE__ */ new Map();
158
- for (let e of h) g.set(e.actionName, {
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 f) {
168
- let t = g.get(e.name);
169
- t ? _.push(createUpdate(e, {
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
- })) : _.push(createUpdate(e, {
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", m = i.skipReason, h = !1, g = !1;
186
- if (p === "skipped") return {
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: m,
212
+ skipReason: g,
193
213
  latestSha: c,
194
214
  action: t,
195
- status: p
215
+ status: h
196
216
  };
197
- if (d && isSha(d)) c ? h = !compareSha(d, c) : f && (h = !0);
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 (h = semver.lt(e, n), h) {
221
+ if (_ = semver.lt(e, n), _) {
202
222
  let t = semver.major(e);
203
- g = semver.major(n) > t;
223
+ v = semver.major(n) > t;
204
224
  }
205
- !h && semver.eq(e, n) && !isSha(t.version) && c && (h = !0, g = !1);
206
- } else d !== f && (h = !0);
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: g,
213
- skipReason: m,
233
+ isBreaking: v,
234
+ skipReason: g,
214
235
  latestSha: c,
215
- hasUpdate: h,
236
+ hasUpdate: _,
216
237
  action: t,
217
- status: p
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,6 +1,6 @@
1
1
  import { ActionUpdate } from '../../../types/action-update';
2
2
  /**
3
- * Apply updates using SHA with version in comment for readability.
3
+ * Apply updates using the already-resolved target refs.
4
4
  *
5
5
  * @param updates - Array of updates to apply.
6
6
  */
@@ -1,40 +1,53 @@
1
1
  import { readFile, writeFile } from "node:fs/promises";
2
- async function applyUpdates(n) {
3
- let r = /* @__PURE__ */ new Map();
4
- for (let e of n) {
5
- let { file: t } = e.action;
6
- if (!t) continue;
7
- let n = r.get(t) ?? [];
8
- n.push(e), r.set(t, n);
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 i = [...r.entries()].map(async ([n, r]) => {
11
- let i = await readFile(n, "utf8");
12
- for (let e of r) {
13
- if (!e.latestSha) continue;
14
- function t(e) {
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 n = t(e.action.name), r = e.currentVersion ? t(e.currentVersion) : "";
18
- if (n.includes("\n") || n.includes("\r")) {
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 (r && (r.includes("\n") || r.includes("\r"))) {
23
+ if (s && (s.includes("\n") || s.includes("\r"))) {
23
24
  console.error(`Invalid version: ${e.currentVersion}`);
24
25
  continue;
25
26
  }
26
- if (!/^[\da-f]{40}$/iu.test(e.latestSha)) {
27
- console.error(`Invalid SHA format: ${e.latestSha}`);
27
+ if (n.includes("\n") || n.includes("\r") || n.trim() === "") {
28
+ console.error(`Invalid target ref: ${n}`);
28
29
  continue;
29
30
  }
30
- let a = String.raw`['"]?\buses\b['"]?\s*:\s*`, o = String.raw`(?:^[^\S\n]*(?:-[^\S\n]*)?|[{\[,][^\S\n]*)` + a, s = new RegExp(String.raw`(?<prefix>${o})` + String.raw`(?<quote>['"]?)` + String.raw`(?<name>${n})@${r}` + String.raw`\k<quote>` + String.raw`(?<after>[ \t\]}{,]*)` + String.raw`(?<comment>[^\S\r\n]*#[^\r\n]*)?`, "gm");
31
- i = i.replace(s, (t, ...n) => {
32
- let i = n.at(-3), a = n.at(-2), o = n.at(-1), s = a.indexOf("\n", i + t.length), c = (s === -1 ? a.slice(i + t.length) : a.slice(i + t.length, s)).trim().length > 0, l = o.after.endsWith(" ") ? "" : " ", u = c && !o.comment && r !== "" ? "" : `${l}# ${e.latestVersion}`;
33
- return `${`${o.prefix}${o.quote}${o.name}`}@${`${e.latestSha}${o.quote}${o.after}${u}`}`;
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(n, i, "utf8");
46
+ await writeFile(r, a, "utf8");
37
47
  });
38
- await Promise.all(i);
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 };