actions-up 1.3.0 → 1.4.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.
Files changed (46) hide show
  1. package/dist/cli/index.js +41 -41
  2. package/dist/core/api/check-updates.js +146 -134
  3. package/dist/core/api/create-github-client.js +28 -29
  4. package/dist/core/api/get-all-releases.js +20 -27
  5. package/dist/core/api/get-all-tags.js +5 -7
  6. package/dist/core/api/get-latest-release.js +16 -19
  7. package/dist/core/api/get-reference-type.js +6 -12
  8. package/dist/core/api/get-tag-info.js +47 -76
  9. package/dist/core/api/get-tag-sha.js +12 -22
  10. package/dist/core/api/internal-rate-limit-error.js +3 -4
  11. package/dist/core/api/make-request.js +18 -21
  12. package/dist/core/api/resolve-github-token-sync.js +20 -26
  13. package/dist/core/api/update-rate-limit-info.js +7 -7
  14. package/dist/core/ast/guards/has-range.js +2 -2
  15. package/dist/core/ast/guards/is-node.js +2 -2
  16. package/dist/core/ast/guards/is-pair.js +2 -2
  17. package/dist/core/ast/guards/is-scalar.js +2 -2
  18. package/dist/core/ast/guards/is-yaml-map.js +2 -2
  19. package/dist/core/ast/guards/is-yaml-sequence.js +2 -2
  20. package/dist/core/ast/scanners/scan-composite-action-ast.js +9 -11
  21. package/dist/core/ast/scanners/scan-workflow-ast.js +12 -14
  22. package/dist/core/ast/update/apply-updates.js +24 -27
  23. package/dist/core/ast/utils/extract-uses-from-steps.js +12 -14
  24. package/dist/core/ast/utils/find-map-pair.js +2 -5
  25. package/dist/core/ast/utils/get-line-number.js +4 -4
  26. package/dist/core/constants.js +1 -3
  27. package/dist/core/filters/parse-exclude-patterns.d.ts +17 -0
  28. package/dist/core/filters/parse-exclude-patterns.js +23 -0
  29. package/dist/core/fs/is-yaml-file.js +2 -2
  30. package/dist/core/fs/read-yaml-document.js +4 -5
  31. package/dist/core/ignore/should-ignore.d.ts +23 -0
  32. package/dist/core/ignore/should-ignore.js +14 -0
  33. package/dist/core/interactive/format-version.js +16 -30
  34. package/dist/core/interactive/pad-string.js +5 -6
  35. package/dist/core/interactive/prompt-update-selection.js +106 -163
  36. package/dist/core/interactive/strip-ansi.js +10 -17
  37. package/dist/core/parsing/parse-action-reference.js +23 -23
  38. package/dist/core/scan-action-file.js +3 -3
  39. package/dist/core/scan-github-actions.js +87 -136
  40. package/dist/core/scan-workflow-file.js +3 -3
  41. package/dist/core/schema/composite/is-composite-action-runs.js +2 -4
  42. package/dist/core/schema/composite/is-composite-action-structure.js +4 -4
  43. package/dist/core/schema/workflow/is-workflow-structure.js +4 -4
  44. package/dist/package.js +1 -1
  45. package/package.json +1 -1
  46. package/readme.md +55 -8
@@ -1,20 +1,14 @@
1
1
  import { makeRequest } from "./make-request.js";
2
- async function getReferenceType(context, parameters) {
3
- let { reference, owner, repo } = parameters;
4
- let cacheKey = `${owner}/${repo}#${reference}`;
5
- if (context.caches.refType.has(cacheKey)) return context.caches.refType.get(cacheKey) ?? null;
2
+ async function getReferenceType(t, n) {
3
+ let { reference: r, owner: i, repo: a } = n, o = `${i}/${a}#${r}`;
4
+ if (t.caches.refType.has(o)) return t.caches.refType.get(o) ?? null;
6
5
  try {
7
- await makeRequest(context, `/repos/${owner}/${repo}/git/refs/tags/${reference}`);
8
- context.caches.refType.set(cacheKey, "tag");
9
- return "tag";
6
+ return await makeRequest(t, `/repos/${i}/${a}/git/refs/tags/${r}`), t.caches.refType.set(o, "tag"), "tag";
10
7
  } catch {
11
8
  try {
12
- await makeRequest(context, `/repos/${owner}/${repo}/git/refs/heads/${reference}`);
13
- context.caches.refType.set(cacheKey, "branch");
14
- return "branch";
9
+ return await makeRequest(t, `/repos/${i}/${a}/git/refs/heads/${r}`), t.caches.refType.set(o, "branch"), "branch";
15
10
  } catch {
16
- context.caches.refType.set(cacheKey, null);
17
- return null;
11
+ return t.caches.refType.set(o, null), null;
18
12
  }
19
13
  }
20
14
  }
@@ -1,96 +1,67 @@
1
1
  import { makeRequest } from "./make-request.js";
2
2
  import { GitHubRateLimitError } from "./internal-rate-limit-error.js";
3
- async function getTagInfo(context, parameters) {
3
+ async function getTagInfo(n, i) {
4
4
  try {
5
- let { owner, repo, tag } = parameters;
6
- let displayTag = tag.replace(/^refs\/tags\//u, "");
7
- let cacheKey = `${owner}/${repo}#${displayTag}`;
8
- if (context.caches.tagInfo.has(cacheKey)) return context.caches.tagInfo.get(cacheKey) ?? null;
5
+ let { owner: t, repo: a, tag: o } = i, s = o.replace(/^refs\/tags\//u, ""), c = `${t}/${a}#${s}`;
6
+ if (n.caches.tagInfo.has(c)) return n.caches.tagInfo.get(c) ?? null;
9
7
  try {
10
- let releaseResp = await makeRequest(context, `/repos/${owner}/${repo}/releases/tags/${displayTag}`);
11
- let releaseData = releaseResp.data;
12
- let date = releaseData.published_at ? new Date(releaseData.published_at) : null;
13
- let message = releaseData.body ?? null;
14
- let sha = null;
8
+ let i = (await makeRequest(n, `/repos/${t}/${a}/releases/tags/${s}`)).data, o = i.published_at ? new Date(i.published_at) : null, l = i.body ?? null, u = null;
15
9
  try {
16
- let referenceResp = await makeRequest(context, `/repos/${owner}/${repo}/git/refs/tags/${displayTag}`);
17
- let referenceData = referenceResp.data;
18
- let { type: objectType, sha: objectSha } = referenceData.object;
19
- if (objectSha && objectType === "tag") try {
20
- let tagResp = await makeRequest(context, `/repos/${owner}/${repo}/git/tags/${objectSha}`);
21
- let tagData = tagResp.data;
22
- sha = tagData.object.sha ?? objectSha;
23
- let taggerDate = tagData.tagger?.date;
24
- if (!date && taggerDate) date = new Date(taggerDate);
25
- if (!message && typeof tagData.message === "string") ({message} = tagData);
10
+ let { type: r, sha: i } = (await makeRequest(n, `/repos/${t}/${a}/git/refs/tags/${s}`)).data.object;
11
+ if (i && r === "tag") try {
12
+ let r = (await makeRequest(n, `/repos/${t}/${a}/git/tags/${i}`)).data;
13
+ u = r.object.sha ?? i;
14
+ let s = r.tagger?.date;
15
+ !o && s && (o = new Date(s)), !l && typeof r.message == "string" && ({message: l} = r);
26
16
  } catch {
27
- sha = objectSha;
28
- }
29
- else if (objectSha && objectType === "commit") {
30
- sha = objectSha;
31
- if (!date || !message) try {
32
- let commitResp = await makeRequest(context, `/repos/${owner}/${repo}/git/commits/${objectSha}`);
33
- let { message: commitMessage, author } = commitResp.data;
34
- if (!message && typeof commitMessage === "string") message = commitMessage;
35
- let authorDate = author?.date;
36
- if (!date && authorDate) date = new Date(authorDate);
37
- } catch (error) {}
17
+ u = i;
38
18
  }
19
+ else if (i && r === "commit" && (u = i, !o || !l)) try {
20
+ let { message: r, author: s } = (await makeRequest(n, `/repos/${t}/${a}/git/commits/${i}`)).data;
21
+ !l && typeof r == "string" && (l = r);
22
+ let c = s?.date;
23
+ !o && c && (o = new Date(c));
24
+ } catch {}
39
25
  } catch {
40
- if (isLikelySha(releaseData.target_commitish)) sha = releaseData.target_commitish;
26
+ isLikelySha(i.target_commitish) && (u = i.target_commitish);
41
27
  }
42
- let result = {
43
- tag: displayTag,
44
- message,
45
- date,
46
- sha
28
+ let d = {
29
+ tag: s,
30
+ message: l,
31
+ date: o,
32
+ sha: u
47
33
  };
48
- context.caches.tagInfo.set(cacheKey, result);
49
- return result;
34
+ return n.caches.tagInfo.set(c, d), d;
50
35
  } catch {
51
36
  try {
52
- let referenceResp = await makeRequest(context, `/repos/${owner}/${repo}/git/refs/tags/${displayTag}`);
53
- let referenceData = referenceResp.data;
54
- let { sha } = referenceData.object;
55
- let message = null;
56
- let date = null;
57
- if (referenceData.object.type === "tag") try {
58
- let tagResp = await makeRequest(context, `/repos/${owner}/${repo}/git/tags/${sha}`);
59
- let tagData = tagResp.data;
60
- sha = tagData.object.sha ?? sha;
61
- message = tagData.message ?? null;
62
- date = tagData.tagger.date ? new Date(tagData.tagger.date) : null;
63
- } catch (error) {}
37
+ let r = (await makeRequest(n, `/repos/${t}/${a}/git/refs/tags/${s}`)).data, { sha: i } = r.object, o = null, l = null;
38
+ if (r.object.type === "tag") try {
39
+ let r = (await makeRequest(n, `/repos/${t}/${a}/git/tags/${i}`)).data;
40
+ i = r.object.sha ?? i, o = r.message ?? null, l = r.tagger.date ? new Date(r.tagger.date) : null;
41
+ } catch {}
64
42
  else try {
65
- let commitResp = await makeRequest(context, `/repos/${owner}/${repo}/git/commits/${sha}`);
66
- let commitData = commitResp.data;
67
- message = commitData.message ?? null;
68
- date = commitData.author.date ? new Date(commitData.author.date) : null;
69
- } catch (error) {}
70
- let result = {
71
- tag: displayTag,
72
- message,
73
- date,
74
- sha
43
+ let r = (await makeRequest(n, `/repos/${t}/${a}/git/commits/${i}`)).data;
44
+ o = r.message ?? null, l = r.author.date ? new Date(r.author.date) : null;
45
+ } catch {}
46
+ let u = {
47
+ tag: s,
48
+ message: o,
49
+ date: l,
50
+ sha: i
75
51
  };
76
- context.caches.tagInfo.set(cacheKey, result);
77
- return result;
78
- } catch (tagError) {
79
- if (tagError && typeof tagError === "object" && "status" in tagError) {
80
- context.caches.tagInfo.set(cacheKey, null);
81
- return null;
82
- }
83
- throw tagError;
52
+ return n.caches.tagInfo.set(c, u), u;
53
+ } catch (e) {
54
+ if (e && typeof e == "object" && "status" in e) return n.caches.tagInfo.set(c, null), null;
55
+ throw e;
84
56
  }
85
57
  }
86
- } catch (error) {
87
- if (error instanceof Error && error.message.includes("rate limit")) throw new GitHubRateLimitError(context.rateLimitReset);
88
- throw error;
58
+ } catch (e) {
59
+ throw e instanceof Error && e.message.includes("rate limit") ? new GitHubRateLimitError(n.rateLimitReset) : e;
89
60
  }
90
61
  }
91
- function isLikelySha(value) {
92
- if (typeof value !== "string" || value.trim() === "") return false;
93
- let normalized = value.replace(/^v/u, "");
94
- return /^[0-9a-f]{7,40}$/iu.test(normalized);
62
+ function isLikelySha(e) {
63
+ if (typeof e != "string" || e.trim() === "") return !1;
64
+ let t = e.replace(/^v/u, "");
65
+ return /^[0-9a-f]{7,40}$/iu.test(t);
95
66
  }
96
67
  export { getTagInfo };
@@ -1,30 +1,20 @@
1
1
  import { makeRequest } from "./make-request.js";
2
2
  import { GitHubRateLimitError } from "./internal-rate-limit-error.js";
3
- async function getTagSha(context, parameters) {
4
- let { owner, repo, tag } = parameters;
5
- let displayTag = tag.replace(/^refs\/tags\//u, "");
6
- let cacheKey = `${owner}/${repo}#${displayTag}`;
7
- if (context.caches.tagSha.has(cacheKey)) return context.caches.tagSha.get(cacheKey) ?? null;
3
+ async function getTagSha(n, r) {
4
+ let { owner: i, repo: a, tag: o } = r, s = o.replace(/^refs\/tags\//u, ""), c = `${i}/${a}#${s}`;
5
+ if (n.caches.tagSha.has(c)) return n.caches.tagSha.get(c) ?? null;
8
6
  try {
9
- let referenceResp = await makeRequest(context, `/repos/${owner}/${repo}/git/refs/tags/${displayTag}`);
10
- let referenceData = referenceResp.data;
11
- let objectSha = referenceData.object.sha;
12
- let objectType = referenceData.object.type;
13
- let sha = null;
14
- if (objectSha && objectType === "tag") try {
15
- let tagResp = await makeRequest(context, `/repos/${owner}/${repo}/git/tags/${objectSha}`);
16
- let tagData = tagResp.data;
17
- sha = tagData.object.sha ?? null;
7
+ let t = (await makeRequest(n, `/repos/${i}/${a}/git/refs/tags/${s}`)).data, r = t.object.sha, o = t.object.type, l = null;
8
+ if (r && o === "tag") try {
9
+ l = (await makeRequest(n, `/repos/${i}/${a}/git/tags/${r}`)).data.object.sha ?? null;
18
10
  } catch {
19
- sha = objectSha;
11
+ l = r;
20
12
  }
21
- else if (objectSha && objectType === "commit") sha = objectSha;
22
- context.caches.tagSha.set(cacheKey, sha);
23
- return sha;
24
- } catch (error) {
25
- if (error instanceof Error && error.message.includes("rate limit")) throw new GitHubRateLimitError(context.rateLimitReset);
26
- context.caches.tagSha.set(cacheKey, null);
27
- return null;
13
+ else r && o === "commit" && (l = r);
14
+ return n.caches.tagSha.set(c, l), l;
15
+ } catch (e) {
16
+ if (e instanceof Error && e.message.includes("rate limit")) throw new GitHubRateLimitError(n.rateLimitReset);
17
+ return n.caches.tagSha.set(c, null), null;
28
18
  }
29
19
  }
30
20
  export { getTagSha };
@@ -1,8 +1,7 @@
1
1
  var GitHubRateLimitError = class extends Error {
2
- constructor(resetAt) {
3
- let resetTime = resetAt.toLocaleTimeString();
4
- super(`GitHub API rate limit exceeded. Resets at ${resetTime}`);
5
- this.name = "GitHubRateLimitError";
2
+ constructor(e) {
3
+ let t = e.toLocaleTimeString();
4
+ super(`GitHub API rate limit exceeded. Resets at ${t}`), this.name = "GitHubRateLimitError";
6
5
  }
7
6
  };
8
7
  export { GitHubRateLimitError };
@@ -1,31 +1,28 @@
1
1
  import { updateRateLimitInfo } from "./update-rate-limit-info.js";
2
- async function makeRequest(context, path, options = {}) {
3
- let headers = {
2
+ async function makeRequest(t, n, r = {}) {
3
+ let i = {
4
4
  Accept: "application/vnd.github.v3+json",
5
5
  "User-Agent": "actions-up",
6
- ...options.headers
6
+ ...r.headers
7
7
  };
8
- if (context.token) headers["Authorization"] = `Bearer ${context.token}`;
9
- let response = await fetch(`${context.baseUrl}${path}`, {
10
- ...options,
11
- headers
12
- });
13
- let responseHeaders = {};
14
- for (let [key, value] of response.headers.entries()) responseHeaders[key] = value;
15
- updateRateLimitInfo(context, responseHeaders);
16
- if (!response.ok) {
17
- let error = /* @__PURE__ */ new Error(`GitHub API error: ${response.status} ${response.statusText}`);
18
- error.status = response.status;
19
- if (response.status === 403) {
20
- let text = await response.text();
21
- if (text.includes("rate limit") || text.includes("API rate limit")) error.message = "API rate limit exceeded";
8
+ t.token && (i.Authorization = `Bearer ${t.token}`);
9
+ let a = await fetch(`${t.baseUrl}${n}`, {
10
+ ...r,
11
+ headers: i
12
+ }), o = {};
13
+ for (let [e, t] of a.headers.entries()) o[e] = t;
14
+ if (updateRateLimitInfo(t, o), !a.ok) {
15
+ let e = /* @__PURE__ */ Error(`GitHub API error: ${a.status} ${a.statusText}`);
16
+ if (e.status = a.status, a.status === 403) {
17
+ let t = await a.text();
18
+ (t.includes("rate limit") || t.includes("API rate limit")) && (e.message = "API rate limit exceeded");
22
19
  }
23
- throw error;
20
+ throw e;
24
21
  }
25
- let data = await response.json();
22
+ let s = await a.json();
26
23
  return {
27
- headers: responseHeaders,
28
- data
24
+ headers: o,
25
+ data: s
29
26
  };
30
27
  }
31
28
  export { makeRequest };
@@ -2,12 +2,12 @@ import { join } from "node:path";
2
2
  import { execFileSync } from "node:child_process";
3
3
  import { readFileSync } from "node:fs";
4
4
  function resolveGitHubTokenSync() {
5
- let fromGithubToken = process.env["GITHUB_TOKEN"];
6
- if (fromGithubToken && fromGithubToken.trim() !== "") return fromGithubToken.trim();
7
- let fromGhToken = process.env["GH_TOKEN"];
8
- if (fromGhToken && fromGhToken.trim() !== "") return fromGhToken.trim();
5
+ let r = process.env.GITHUB_TOKEN;
6
+ if (r && r.trim() !== "") return r.trim();
7
+ let i = process.env.GH_TOKEN;
8
+ if (i && i.trim() !== "") return i.trim();
9
9
  try {
10
- let output = execFileSync("gh", ["auth", "token"], {
10
+ let e = execFileSync("gh", ["auth", "token"], {
11
11
  stdio: [
12
12
  "ignore",
13
13
  "pipe",
@@ -15,34 +15,28 @@ function resolveGitHubTokenSync() {
15
15
  ],
16
16
  encoding: "utf8",
17
17
  timeout: 500
18
- });
19
- let token = output.trim();
20
- if (token) return token;
18
+ }).trim();
19
+ if (e) return e;
21
20
  } catch {}
22
21
  try {
23
- let gitConfigPath = join(process.cwd(), ".git", "config");
24
- let content = readFileSync(gitConfigPath, "utf8");
25
- let directMatch = content.match(/^\s*(?:github\.(?:oauth-token|token)|hub\.oauthtoken)\s*=\s*(?<token>\S[^\n\r]*)$/mu);
26
- let directToken = directMatch?.groups?.["token"]?.trim();
27
- if (directToken) return directToken;
28
- let currentSection = null;
29
- for (let rawLine of content.split(/\r?\n/u)) {
30
- let line = rawLine.trim();
31
- let sectionMatch = line.match(/^\[(?<name>[^\]]+)\]$/u);
32
- if (sectionMatch?.groups) {
33
- currentSection = sectionMatch.groups["name"].toLowerCase();
22
+ let t = join(process.cwd(), ".git", "config"), r = readFileSync(t, "utf8"), i = r.match(/^\s*(?:github\.(?:oauth-token|token)|hub\.oauthtoken)\s*=\s*(?<token>\S[^\n\r]*)$/mu)?.groups?.token?.trim();
23
+ if (i) return i;
24
+ let a = null;
25
+ for (let e of r.split(/\r?\n/u)) {
26
+ let t = e.trim(), n = t.match(/^\[(?<name>[^\]]+)\]$/u);
27
+ if (n?.groups) {
28
+ a = n.groups.name.toLowerCase();
34
29
  continue;
35
30
  }
36
- if (currentSection === "github") {
37
- let tokenMatch = line.match(/^(?:oauth-token|token)\s*=\s*(?<val>\S[^\n\r]*)$/u);
38
- if (tokenMatch?.groups?.["val"]) return tokenMatch.groups["val"].trim();
31
+ if (a === "github") {
32
+ let e = t.match(/^(?:oauth-token|token)\s*=\s*(?<val>\S[^\n\r]*)$/u);
33
+ if (e?.groups?.val) return e.groups.val.trim();
39
34
  }
40
- if (currentSection === "hub") {
41
- let oauthMatch = line.match(/^oauthtoken\s*=\s*(?<val>\S[^\n\r]*)$/u);
42
- if (oauthMatch?.groups?.["val"]) return oauthMatch.groups["val"].trim();
35
+ if (a === "hub") {
36
+ let e = t.match(/^oauthtoken\s*=\s*(?<val>\S[^\n\r]*)$/u);
37
+ if (e?.groups?.val) return e.groups.val.trim();
43
38
  }
44
39
  }
45
40
  } catch {}
46
- return void 0;
47
41
  }
48
42
  export { resolveGitHubTokenSync };
@@ -1,10 +1,10 @@
1
- function updateRateLimitInfo(context, headers) {
2
- let remaining = headers["x-ratelimit-remaining"];
3
- if (remaining !== void 0) context.rateLimitRemaining = typeof remaining === "string" ? Number.parseInt(remaining, 10) : remaining;
4
- let reset = headers["x-ratelimit-reset"];
5
- if (reset !== void 0) {
6
- let resetTime = typeof reset === "string" ? Number.parseInt(reset, 10) : reset;
7
- context.rateLimitReset = /* @__PURE__ */ new Date(resetTime * 1e3);
1
+ function updateRateLimitInfo(e, t) {
2
+ let n = t["x-ratelimit-remaining"];
3
+ n !== void 0 && (e.rateLimitRemaining = typeof n == "string" ? Number.parseInt(n, 10) : n);
4
+ let r = t["x-ratelimit-reset"];
5
+ if (r !== void 0) {
6
+ let t = typeof r == "string" ? Number.parseInt(r, 10) : r;
7
+ e.rateLimitReset = /* @__PURE__ */ new Date(t * 1e3);
8
8
  }
9
9
  }
10
10
  export { updateRateLimitInfo };
@@ -1,4 +1,4 @@
1
- function hasRange(node) {
2
- return node !== null && typeof node === "object" && "range" in node;
1
+ function hasRange(e) {
2
+ return typeof e == "object" && !!e && "range" in e;
3
3
  }
4
4
  export { hasRange };
@@ -1,4 +1,4 @@
1
- function isNode(node) {
2
- return node !== null && typeof node === "object" && "toJSON" in node && typeof node.toJSON === "function";
1
+ function isNode(e) {
2
+ return typeof e == "object" && !!e && "toJSON" in e && typeof e.toJSON == "function";
3
3
  }
4
4
  export { isNode };
@@ -1,4 +1,4 @@
1
- function isPair(node) {
2
- return node !== null && typeof node === "object" && "key" in node && "value" in node;
1
+ function isPair(e) {
2
+ return typeof e == "object" && !!e && "key" in e && "value" in e;
3
3
  }
4
4
  export { isPair };
@@ -1,4 +1,4 @@
1
- function isScalar(node) {
2
- return node !== null && typeof node === "object" && "value" in node;
1
+ function isScalar(e) {
2
+ return typeof e == "object" && !!e && "value" in e;
3
3
  }
4
4
  export { isScalar };
@@ -1,4 +1,4 @@
1
- function isYAMLMap(node) {
2
- return node !== null && typeof node === "object" && "items" in node && Array.isArray(node.items);
1
+ function isYAMLMap(e) {
2
+ return typeof e == "object" && !!e && "items" in e && Array.isArray(e.items);
3
3
  }
4
4
  export { isYAMLMap };
@@ -1,4 +1,4 @@
1
- function isYAMLSequence(node) {
2
- return node !== null && typeof node === "object" && "items" in node && Array.isArray(node.items);
1
+ function isYAMLSequence(e) {
2
+ return typeof e == "object" && !!e && "items" in e && Array.isArray(e.items);
3
3
  }
4
4
  export { isYAMLSequence };
@@ -3,16 +3,14 @@ import { extractUsesFromSteps } from "../utils/extract-uses-from-steps.js";
3
3
  import { findMapPair } from "../utils/find-map-pair.js";
4
4
  import { isCompositeActionStructure } from "../../schema/composite/is-composite-action-structure.js";
5
5
  import { isCompositeActionRuns } from "../../schema/composite/is-composite-action-runs.js";
6
- function scanCompositeActionAst(document, content, filePath) {
7
- let action = document.toJSON();
8
- if (!isCompositeActionStructure(action)) return [];
9
- if (!document.contents || !isYAMLMap(document.contents)) return [];
10
- let runsPair = findMapPair(document.contents, "runs");
11
- if (!runsPair?.value || !isYAMLMap(runsPair.value)) return [];
12
- let runsJson = action["runs"];
13
- if (!runsJson || !isCompositeActionRuns(runsJson) || !runsJson["steps"] || !Array.isArray(runsJson["steps"])) return [];
14
- let stepsPair = findMapPair(runsPair.value, "steps");
15
- if (!stepsPair?.value) return [];
16
- return extractUsesFromSteps(stepsPair.value, filePath, content);
6
+ function scanCompositeActionAst(a, o, s) {
7
+ let c = a.toJSON();
8
+ if (!isCompositeActionStructure(c) || !a.contents || !isYAMLMap(a.contents)) return [];
9
+ let l = findMapPair(a.contents, "runs");
10
+ if (!l?.value || !isYAMLMap(l.value)) return [];
11
+ let u = c.runs;
12
+ if (!u || !isCompositeActionRuns(u) || !u.steps || !Array.isArray(u.steps)) return [];
13
+ let d = findMapPair(l.value, "steps");
14
+ return d?.value ? extractUsesFromSteps(d.value, s, o) : [];
17
15
  }
18
16
  export { scanCompositeActionAst };
@@ -4,20 +4,18 @@ import { isNode } from "../guards/is-node.js";
4
4
  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
- function scanWorkflowAst(document, content, filePath) {
8
- let workflow = document.toJSON();
9
- if (!isWorkflowStructure(workflow)) return [];
10
- if (!document.contents || !isYAMLMap(document.contents)) return [];
11
- let jobsPair = findMapPair(document.contents, "jobs");
12
- if (!jobsPair?.value || !isYAMLMap(jobsPair.value)) return [];
13
- let actions = [];
14
- for (let jobNode of jobsPair.value.items) {
15
- if (!isPair(jobNode) || !jobNode.value || !isNode(jobNode.value)) continue;
16
- if (!isYAMLMap(jobNode.value)) continue;
17
- let stepsPair = findMapPair(jobNode.value, "steps");
18
- if (!stepsPair?.value) continue;
19
- actions.push(...extractUsesFromSteps(stepsPair.value, filePath, content));
7
+ function scanWorkflowAst(o, s, c) {
8
+ let l = o.toJSON();
9
+ if (!isWorkflowStructure(l) || !o.contents || !isYAMLMap(o.contents)) return [];
10
+ let u = findMapPair(o.contents, "jobs");
11
+ if (!u?.value || !isYAMLMap(u.value)) return [];
12
+ let d = [];
13
+ for (let e of u.value.items) {
14
+ if (!isPair(e) || !e.value || !isNode(e.value) || !isYAMLMap(e.value)) continue;
15
+ let o = findMapPair(e.value, "steps");
16
+ if (!o?.value) continue;
17
+ d.push(...extractUsesFromSteps(o.value, c, s));
20
18
  }
21
- return actions;
19
+ return d;
22
20
  }
23
21
  export { scanWorkflowAst };
@@ -1,40 +1,37 @@
1
1
  import { readFile, writeFile } from "node:fs/promises";
2
- async function applyUpdates(updates) {
3
- let updatesByFile = /* @__PURE__ */ new Map();
4
- for (let update of updates) {
5
- let { file } = update.action;
6
- if (!file) continue;
7
- let fileUpdates = updatesByFile.get(file) ?? [];
8
- fileUpdates.push(update);
9
- updatesByFile.set(file, fileUpdates);
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);
10
9
  }
11
- let filePromises = [...updatesByFile.entries()].map(async ([filePath, fileUpdates]) => {
12
- let content = await readFile(filePath, "utf8");
13
- for (let update of fileUpdates) {
14
- if (!update.latestSha) continue;
15
- function escapeRegExp(string_) {
16
- return string_.replaceAll(/[$()*+\-./?[\\\]^{|}]/gu, String.raw`\$&`);
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) {
15
+ return e.replaceAll(/[$()*+\-./?[\\\]^{|}]/gu, String.raw`\$&`);
17
16
  }
18
- let escapedName = escapeRegExp(update.action.name);
19
- let escapedVersion = update.currentVersion ? escapeRegExp(update.currentVersion) : "";
20
- if (escapedName.includes("\n") || escapedName.includes("\r")) {
21
- console.error(`Invalid action name: ${update.action.name}`);
17
+ let n = t(e.action.name), r = e.currentVersion ? t(e.currentVersion) : "";
18
+ if (n.includes("\n") || n.includes("\r")) {
19
+ console.error(`Invalid action name: ${e.action.name}`);
22
20
  continue;
23
21
  }
24
- if (escapedVersion && (escapedVersion.includes("\n") || escapedVersion.includes("\r"))) {
25
- console.error(`Invalid version: ${update.currentVersion}`);
22
+ if (r && (r.includes("\n") || r.includes("\r"))) {
23
+ console.error(`Invalid version: ${e.currentVersion}`);
26
24
  continue;
27
25
  }
28
- if (!/^[\da-f]{40}$/iu.test(update.latestSha)) {
29
- console.error(`Invalid SHA format: ${update.latestSha}`);
26
+ if (!/^[\da-f]{40}$/iu.test(e.latestSha)) {
27
+ console.error(`Invalid SHA format: ${e.latestSha}`);
30
28
  continue;
31
29
  }
32
- let pattern = new RegExp(`(^\\s*-?\\s*uses:\\s*)(['"]?)(${escapedName})@${escapedVersion}\\2(\\s*#[^\\n]*)?`, "gm");
33
- let replacement = `$1$2$3@${update.latestSha}$2 # ${update.latestVersion}`;
34
- content = content.replace(pattern, replacement);
30
+ let a = RegExp(`(^\\s*-?\\s*uses:\\s*)(['"]?)(${n})@${r}\\2(\\s*#[^\\n]*)?`, "gm"), o = `$1$2$3@${e.latestSha}$2 # ${e.latestVersion}`;
31
+ i = i.replace(a, o);
35
32
  }
36
- await writeFile(filePath, content, "utf8");
33
+ await writeFile(n, i, "utf8");
37
34
  });
38
- await Promise.all(filePromises);
35
+ await Promise.all(i);
39
36
  }
40
37
  export { applyUpdates };
@@ -5,20 +5,18 @@ import { isYAMLMap } from "../guards/is-yaml-map.js";
5
5
  import { isScalar } from "../guards/is-scalar.js";
6
6
  import { isNode } from "../guards/is-node.js";
7
7
  import { isPair } from "../guards/is-pair.js";
8
- function extractUsesFromSteps(stepsNode, filePath, content) {
9
- if (!isYAMLSequence(stepsNode)) return [];
10
- let actions = [];
11
- for (let stepNode of stepsNode.items) {
12
- if (!isYAMLMap(stepNode) || !isNode(stepNode)) continue;
13
- let step = stepNode.toJSON();
14
- if (step === null || typeof step !== "object" || Array.isArray(step)) continue;
15
- let stepObject = step;
16
- if (typeof stepObject["uses"] !== "string") continue;
17
- let usesPair = stepNode.items.find((item) => isPair(item) && isScalar(item.key) && item.key.value === "uses");
18
- let lineNumber = usesPair?.key ? getLineNumberForKey(content, usesPair.key) : 0;
19
- let action = parseActionReference(stepObject["uses"], filePath, lineNumber);
20
- if (action) actions.push(action);
8
+ function extractUsesFromSteps(s, c, l) {
9
+ if (!isYAMLSequence(s)) return [];
10
+ let u = [];
11
+ for (let o of s.items) {
12
+ if (!isYAMLMap(o) || !isNode(o)) continue;
13
+ let s = o.toJSON();
14
+ if (typeof s != "object" || !s || Array.isArray(s)) continue;
15
+ let d = s;
16
+ if (typeof d.uses != "string") continue;
17
+ let f = o.items.find((e) => isPair(e) && isScalar(e.key) && e.key.value === "uses"), p = f?.key ? getLineNumberForKey(l, f.key) : 0, m = parseActionReference(d.uses, c, p);
18
+ m && u.push(m);
21
19
  }
22
- return actions;
20
+ return u;
23
21
  }
24
22
  export { extractUsesFromSteps };
@@ -1,10 +1,7 @@
1
1
  import { isYAMLMap } from "../guards/is-yaml-map.js";
2
2
  import { isScalar } from "../guards/is-scalar.js";
3
3
  import { isPair } from "../guards/is-pair.js";
4
- function findMapPair(map, key) {
5
- if (!isYAMLMap(map) || !Array.isArray(map.items)) return null;
6
- let yamlMap = map;
7
- let pair = yamlMap.items.find((item) => isPair(item) && isScalar(item.key) && item.key.value === key);
8
- return pair ?? null;
4
+ function findMapPair(r, i) {
5
+ return !isYAMLMap(r) || !Array.isArray(r.items) ? null : r.items.find((e) => isPair(e) && isScalar(e.key) && e.key.value === i) ?? null;
9
6
  }
10
7
  export { findMapPair };
@@ -1,8 +1,8 @@
1
1
  import { hasRange } from "../guards/has-range.js";
2
- function getLineNumberForKey(content, keyNode) {
3
- if (hasRange(keyNode) && keyNode.range) {
4
- let [offset] = keyNode.range;
5
- if (typeof offset === "number" && Number.isFinite(offset)) return content.slice(0, Math.max(0, offset)).split("\n").length;
2
+ function getLineNumberForKey(t, n) {
3
+ if (hasRange(n) && n.range) {
4
+ let [e] = n.range;
5
+ if (typeof e == "number" && Number.isFinite(e)) return t.slice(0, Math.max(0, e)).split("\n").length;
6
6
  }
7
7
  return 0;
8
8
  }
@@ -1,4 +1,2 @@
1
- const GITHUB_DIRECTORY = ".github";
2
- const WORKFLOWS_DIRECTORY = "workflows";
3
- const ACTIONS_DIRECTORY = "actions";
1
+ const GITHUB_DIRECTORY = ".github", WORKFLOWS_DIRECTORY = "workflows", ACTIONS_DIRECTORY = "actions";
4
2
  export { ACTIONS_DIRECTORY, GITHUB_DIRECTORY, WORKFLOWS_DIRECTORY };