actions-up 1.13.0 → 1.14.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.
Files changed (71) hide show
  1. package/dist/cli/build-json-report.d.ts +57 -36
  2. package/dist/cli/build-json-report.js +22 -18
  3. package/dist/cli/index.js +137 -122
  4. package/dist/cli/merge-scan-results.js +2 -2
  5. package/dist/cli/normalize-update-mode.js +2 -2
  6. package/dist/cli/normalize-update-style.d.ts +8 -0
  7. package/dist/cli/normalize-update-style.js +6 -0
  8. package/dist/cli/print-mode-warning.js +5 -5
  9. package/dist/cli/print-skipped-warning.d.ts +4 -1
  10. package/dist/cli/print-skipped-warning.js +10 -6
  11. package/dist/cli/resolve-scan-directories.js +8 -8
  12. package/dist/cli/validate-cli-options.js +2 -2
  13. package/dist/core/api/check-updates.d.ts +2 -0
  14. package/dist/core/api/check-updates.js +120 -96
  15. package/dist/core/api/create-github-client.js +26 -26
  16. package/dist/core/api/get-all-releases.js +12 -12
  17. package/dist/core/api/get-all-tags.js +4 -4
  18. package/dist/core/api/get-compatible-update.js +6 -6
  19. package/dist/core/api/get-latest-release.js +15 -15
  20. package/dist/core/api/get-reference-type.js +5 -5
  21. package/dist/core/api/get-tag-info.js +14 -14
  22. package/dist/core/api/get-tag-sha.js +7 -7
  23. package/dist/core/api/internal-rate-limit-error.js +2 -2
  24. package/dist/core/api/make-request.js +4 -4
  25. package/dist/core/api/resolve-github-token-sync.js +7 -7
  26. package/dist/core/api/update-rate-limit-info.js +3 -6
  27. package/dist/core/ast/guards/has-range.js +2 -2
  28. package/dist/core/ast/guards/is-node.js +2 -2
  29. package/dist/core/ast/guards/is-pair.js +2 -2
  30. package/dist/core/ast/guards/is-scalar.js +2 -2
  31. package/dist/core/ast/guards/is-yaml-map.js +2 -2
  32. package/dist/core/ast/guards/is-yaml-sequence.js +2 -2
  33. package/dist/core/ast/scanners/scan-composite-action-ast.js +13 -13
  34. package/dist/core/ast/scanners/scan-workflow-ast.js +21 -21
  35. package/dist/core/ast/update/apply-updates.d.ts +1 -1
  36. package/dist/core/ast/update/apply-updates.js +35 -22
  37. package/dist/core/ast/utils/extract-uses-from-steps.js +14 -14
  38. package/dist/core/ast/utils/find-map-pair.js +6 -6
  39. package/dist/core/ast/utils/get-line-number.js +4 -4
  40. package/dist/core/constants.js +2 -2
  41. package/dist/core/filters/parse-exclude-patterns.js +2 -2
  42. package/dist/core/fs/find-yaml-files-recursive.js +9 -9
  43. package/dist/core/fs/is-yaml-file.js +2 -2
  44. package/dist/core/fs/read-yaml-document.js +6 -6
  45. package/dist/core/ignore/should-ignore.js +4 -4
  46. package/dist/core/index.js +5 -5
  47. package/dist/core/interactive/format-version.js +14 -14
  48. package/dist/core/interactive/pad-string.js +4 -4
  49. package/dist/core/interactive/prompt-update-selection.js +162 -135
  50. package/dist/core/interactive/strip-ansi.js +2 -2
  51. package/dist/core/parsing/parse-action-reference.js +2 -2
  52. package/dist/core/scan-action-file.js +6 -6
  53. package/dist/core/scan-github-actions.js +83 -83
  54. package/dist/core/scan-recursive.js +24 -24
  55. package/dist/core/scan-workflow-file.js +6 -6
  56. package/dist/core/schema/composite/is-composite-action-runs.js +2 -2
  57. package/dist/core/schema/composite/is-composite-action-structure.js +2 -2
  58. package/dist/core/schema/workflow/is-workflow-structure.js +2 -2
  59. package/dist/core/updates/resolve-target-reference.d.ts +10 -0
  60. package/dist/core/updates/resolve-target-reference.js +24 -0
  61. package/dist/core/versions/find-compatible-tag.js +16 -16
  62. package/dist/core/versions/get-update-level.js +8 -8
  63. package/dist/core/versions/is-semver-like.js +2 -2
  64. package/dist/core/versions/is-sha.js +2 -2
  65. package/dist/core/versions/normalize-version.js +4 -4
  66. package/dist/core/versions/read-inline-version-comment.js +4 -4
  67. package/dist/package.js +2 -2
  68. package/dist/types/action-update.d.ts +16 -1
  69. package/dist/types/update-style.d.ts +4 -0
  70. package/package.json +2 -2
  71. package/readme.md +24 -5
@@ -1,4 +1,5 @@
1
1
  import { ActionUpdate } from '../types/action-update';
2
+ import { UpdateStyle } from '../types/update-style';
2
3
  import { ScanResult } from '../types/scan-result';
3
4
  import { UpdateMode } from '../types/update-mode';
4
5
  /**
@@ -49,6 +50,10 @@ interface BuildJsonReportOptions {
49
50
  * Whether recursive scanning mode is enabled.
50
51
  */
51
52
  recursive: boolean;
53
+ /**
54
+ * Effective update style for the run.
55
+ */
56
+ style: UpdateStyle;
52
57
  /**
53
58
  * Effective update mode for the run.
54
59
  */
@@ -66,6 +71,14 @@ interface BuildJsonReportOptions {
66
71
  * Serialized update entry in the JSON report.
67
72
  */
68
73
  interface JsonReportUpdate {
74
+ /**
75
+ * Style of the final reference.
76
+ */
77
+ targetRefStyle: NonNullable<ActionUpdate['targetRefStyle']> | null;
78
+ /**
79
+ * Detected style of the current reference in the source file.
80
+ */
81
+ currentRefType: ActionUpdate['currentRefType'] | null;
69
82
  /**
70
83
  * Reason why this entry was skipped, if any.
71
84
  */
@@ -94,6 +107,10 @@ interface JsonReportUpdate {
94
107
  * Resolved SHA for the target version.
95
108
  */
96
109
  latestSha: string | null;
110
+ /**
111
+ * Final reference that would be written back to the file.
112
+ */
113
+ targetRef: string | null;
97
114
  /**
98
115
  * Whether this update crosses a major version boundary.
99
116
  */
@@ -141,78 +158,82 @@ interface JsonReportSummary {
141
158
  totalUpdates: number;
142
159
  }
143
160
  /**
144
- * Serialized action reference included in each update entry.
161
+ * Effective CLI options serialized into the report.
145
162
  */
146
- interface JsonReportAction {
163
+ interface JsonReportOptions {
147
164
  /**
148
- * Action reference type detected during scanning.
165
+ * Regex patterns supplied through `--exclude`.
149
166
  */
150
- type: ActionUpdate['action']['type'];
167
+ excludePatterns: string[];
151
168
  /**
152
- * Original version or ref from the file, if available.
169
+ * Whether branch references were checked.
153
170
  */
154
- version: string | null;
171
+ includeBranches: boolean;
155
172
  /**
156
- * Relative or absolute file path for the action reference.
173
+ * Resolved scan directories.
157
174
  */
158
- file: string | null;
175
+ directories: string[];
159
176
  /**
160
- * Line number of the action reference.
177
+ * Whether recursive scanning mode is enabled.
161
178
  */
162
- line: number | null;
179
+ recursive: boolean;
163
180
  /**
164
- * Original `uses` value, if available.
181
+ * Effective update style.
165
182
  */
166
- uses: string | null;
183
+ style: UpdateStyle;
167
184
  /**
168
- * Workflow job name, when applicable.
185
+ * Effective update mode.
169
186
  */
170
- job: string | null;
187
+ mode: UpdateMode;
171
188
  /**
172
- * Full `owner/repo@ref` string, when available.
189
+ * Indicates that JSON mode never applies changes.
173
190
  */
174
- ref: string | null;
191
+ reportOnly: true;
175
192
  /**
176
- * Normalized action name.
193
+ * Minimum age filter in days.
177
194
  */
178
- name: string;
195
+ minAge: number;
196
+ /**
197
+ * Indicates that this payload came from `--json`.
198
+ */
199
+ json: true;
179
200
  }
180
201
  /**
181
- * Effective CLI options serialized into the report.
202
+ * Serialized action reference included in each update entry.
182
203
  */
183
- interface JsonReportOptions {
204
+ interface JsonReportAction {
184
205
  /**
185
- * Regex patterns supplied through `--exclude`.
206
+ * Action reference type detected during scanning.
186
207
  */
187
- excludePatterns: string[];
208
+ type: ActionUpdate['action']['type'];
188
209
  /**
189
- * Whether branch references were checked.
210
+ * Original version or ref from the file, if available.
190
211
  */
191
- includeBranches: boolean;
212
+ version: string | null;
192
213
  /**
193
- * Resolved scan directories.
214
+ * Relative or absolute file path for the action reference.
194
215
  */
195
- directories: string[];
216
+ file: string | null;
196
217
  /**
197
- * Whether recursive scanning mode is enabled.
218
+ * Line number of the action reference.
198
219
  */
199
- recursive: boolean;
220
+ line: number | null;
200
221
  /**
201
- * Effective update mode.
222
+ * Original `uses` value, if available.
202
223
  */
203
- mode: UpdateMode;
224
+ uses: string | null;
204
225
  /**
205
- * Indicates that JSON mode never applies changes.
226
+ * Workflow job name, when applicable.
206
227
  */
207
- reportOnly: true;
228
+ job: string | null;
208
229
  /**
209
- * Minimum age filter in days.
230
+ * Full `owner/repo@ref` string, when available.
210
231
  */
211
- minAge: number;
232
+ ref: string | null;
212
233
  /**
213
- * Indicates that this payload came from `--json`.
234
+ * Normalized action name.
214
235
  */
215
- json: true;
236
+ name: string;
216
237
  }
217
238
  /**
218
239
  * Top-level machine-readable report emitted by `--json`.
@@ -1,6 +1,6 @@
1
- import { isAbsolute, relative, resolve } from "node:path";
2
- function buildJsonReport(e) {
3
- let n = resolve(e.cwd ?? process.cwd());
1
+ import { isAbsolute as e, relative as t, resolve as n } from "node:path";
2
+ function r(e) {
3
+ let t = n(e.cwd ?? process.cwd());
4
4
  return {
5
5
  summary: {
6
6
  totalBreakingUpdates: e.outdated.filter((e) => e.isBreaking).length,
@@ -13,26 +13,27 @@ function buildJsonReport(e) {
13
13
  totalSkipped: e.skipped.length
14
14
  },
15
15
  options: {
16
- directories: e.directories.map((e) => serializeDirectoryPath(e, n)),
16
+ directories: e.directories.map((e) => o(e, t)),
17
17
  excludePatterns: e.excludePatterns,
18
18
  includeBranches: e.includeBranches,
19
19
  recursive: e.recursive,
20
20
  minAge: e.minAge,
21
+ style: e.style,
21
22
  mode: e.mode,
22
23
  reportOnly: !0,
23
24
  json: !0
24
25
  },
25
- blockedByMode: e.blockedByMode.map((e) => serializeUpdate(e, n)),
26
- updates: e.outdated.map((e) => serializeUpdate(e, n)),
27
- skipped: e.skipped.map((e) => serializeUpdate(e, n)),
26
+ blockedByMode: e.blockedByMode.map((e) => i(e, t)),
27
+ updates: e.outdated.map((e) => i(e, t)),
28
+ skipped: e.skipped.map((e) => i(e, t)),
28
29
  status: e.status,
29
30
  schemaVersion: 1
30
31
  };
31
32
  }
32
- function serializeUpdate(e, n) {
33
+ function i(e, t) {
33
34
  return {
34
35
  action: {
35
- file: serializePath(e.action.file, n),
36
+ file: a(e.action.file, t),
36
37
  version: e.action.version ?? null,
37
38
  line: e.action.line ?? null,
38
39
  uses: e.action.uses ?? null,
@@ -42,23 +43,26 @@ function serializeUpdate(e, n) {
42
43
  type: e.action.type
43
44
  },
44
45
  publishedAt: e.publishedAt?.toISOString() ?? null,
46
+ currentRefType: e.currentRefType ?? null,
47
+ targetRefStyle: e.targetRefStyle ?? null,
45
48
  currentVersion: e.currentVersion,
46
49
  skipReason: e.skipReason ?? null,
47
50
  latestVersion: e.latestVersion,
51
+ targetRef: e.targetRef ?? null,
48
52
  isBreaking: e.isBreaking,
49
53
  status: e.status ?? "ok",
50
54
  hasUpdate: e.hasUpdate,
51
55
  latestSha: e.latestSha
52
56
  };
53
57
  }
54
- function serializePath(r, i, a = null) {
55
- if (!r) return null;
56
- if (!isAbsolute(r)) return r;
57
- let o = relative(i, r);
58
- return o === "" ? a ?? r : o.startsWith("..") || isAbsolute(o) ? r : o;
58
+ function a(n, r, i = null) {
59
+ if (!n) return null;
60
+ if (!e(n)) return n;
61
+ let a = t(r, n);
62
+ return a === "" ? i ?? n : a.startsWith("..") || e(a) ? n : a;
59
63
  }
60
- function serializeDirectoryPath(r, i) {
61
- let a = relative(i, r);
62
- return a === "" ? "." : a.startsWith("..") || isAbsolute(a) ? r : a;
64
+ function o(n, r) {
65
+ let i = t(r, n);
66
+ return i === "" ? "." : i.startsWith("..") || e(i) ? n : i;
63
67
  }
64
- export { buildJsonReport };
68
+ export { r as buildJsonReport };
package/dist/cli/index.js CHANGED
@@ -1,193 +1,208 @@
1
- import { readInlineVersionComment } from "../core/versions/read-inline-version-comment.js";
2
- import { isSha } from "../core/versions/is-sha.js";
3
- import { promptUpdateSelection } from "../core/interactive/prompt-update-selection.js";
4
- import { getCompatibleUpdate } from "../core/api/get-compatible-update.js";
5
- import { createGitHubClient } from "../core/api/create-github-client.js";
6
- import { resolveScanDirectories } from "./resolve-scan-directories.js";
7
- import { getUpdateLevel } from "../core/versions/get-update-level.js";
8
- import { applyUpdates } from "../core/ast/update/apply-updates.js";
9
- import { printSkippedWarning } from "./print-skipped-warning.js";
10
- import { normalizeUpdateMode } from "./normalize-update-mode.js";
11
- import { validateCliOptions } from "./validate-cli-options.js";
12
- import { shouldIgnore } from "../core/ignore/should-ignore.js";
13
- import { checkUpdates } from "../core/api/check-updates.js";
14
- import { mergeScanResults } from "./merge-scan-results.js";
15
- import { printModeWarning } from "./print-mode-warning.js";
16
- import { scanRecursive } from "../core/scan-recursive.js";
17
- import { buildJsonReport } from "./build-json-report.js";
18
- import { scanGitHubActions } from "../core/scan-github-actions.js";
1
+ import { readInlineVersionComment as e } from "../core/versions/read-inline-version-comment.js";
2
+ import { isSha as t } from "../core/versions/is-sha.js";
3
+ import { promptUpdateSelection as n } from "../core/interactive/prompt-update-selection.js";
4
+ import { resolveTargetReference as r } from "../core/updates/resolve-target-reference.js";
5
+ import { getCompatibleUpdate as i } from "../core/api/get-compatible-update.js";
6
+ import { createGitHubClient as a } from "../core/api/create-github-client.js";
7
+ import { resolveScanDirectories as o } from "./resolve-scan-directories.js";
8
+ import { getUpdateLevel as s } from "../core/versions/get-update-level.js";
9
+ import { applyUpdates as c } from "../core/ast/update/apply-updates.js";
10
+ import { normalizeUpdateStyle as l } from "./normalize-update-style.js";
11
+ import { printSkippedWarning as u } from "./print-skipped-warning.js";
12
+ import { normalizeUpdateMode as d } from "./normalize-update-mode.js";
13
+ import { validateCliOptions as f } from "./validate-cli-options.js";
14
+ import { shouldIgnore as p } from "../core/ignore/should-ignore.js";
15
+ import { checkUpdates as m } from "../core/api/check-updates.js";
16
+ import { mergeScanResults as h } from "./merge-scan-results.js";
17
+ import { printModeWarning as g } from "./print-mode-warning.js";
18
+ import { scanRecursive as _ } from "../core/scan-recursive.js";
19
+ import { buildJsonReport as v } from "./build-json-report.js";
20
+ import { scanGitHubActions as y } from "../core/scan-github-actions.js";
19
21
  import "../core/index.js";
20
- import { version } from "../package.js";
21
- import { createSpinner } from "nanospinner";
22
- import { resolve } from "node:path";
22
+ import { version as b } from "../package.js";
23
+ import { createSpinner as x } from "nanospinner";
24
+ import { resolve as S } from "node:path";
23
25
  import "node:worker_threads";
24
- import pc from "picocolors";
25
- import cac from "cac";
26
- function run() {
27
- let C = cac("actions-up");
28
- C.help().version(version).option("--dir <directory>", "Directory to scan (repeatable). Default: .github, or . with --recursive").option("--dry-run", "Preview changes without applying them").option("--exclude <regex>", "Exclude actions by regex (repeatable)").option("--include-branches", "Also check actions pinned to branches (default: false)").option("--json", "Output update information as machine-readable JSON").option("--min-age <days>", "Minimum age in days for updates (default: 0)", { default: 0 }).option("--mode <mode>", "Update mode: major, minor, or patch (default: major)", { default: "major" }).option("--recursive, -r", "Recursively scan directories for YAML files").option("--yes, -y", "Skip all confirmations").command("", "Update GitHub Actions").action(async (b) => {
29
- let S = b.json ?? !1, C = null, w = resolveScanDirectories({
26
+ import C from "picocolors";
27
+ import w from "cac";
28
+ function T() {
29
+ let T = w("actions-up");
30
+ T.help().version(b).option("--dir <directory>", "Directory to scan (repeatable). Default: .github, or . with --recursive").option("--dry-run", "Preview changes without applying them").option("--exclude <regex>", "Exclude actions by regex (repeatable)").option("--include-branches", "Also check actions pinned to branches (default: false)").option("--json", "Output update information as machine-readable JSON").option("--min-age <days>", "Minimum age in days for updates (default: 0)", { default: 0 }).option("--mode <mode>", "Update mode: major, minor, or patch (default: major)", { default: "major" }).option("--style <style>", "Update style: sha or preserve (default: sha)", { default: "sha" }).option("--recursive, -r", "Recursively scan directories for YAML files").option("--yes, -y", "Skip all confirmations").command("", "Update GitHub Actions").action(async (b) => {
31
+ let w = b.json ?? !1, T = null, E = o({
30
32
  recursive: b.recursive,
31
33
  cwd: process.cwd(),
32
34
  dir: b.dir
33
- }), T = w.map(({ root: e, dir: f }) => resolve(e, f)), E = b.includeBranches ?? !1, D = normalizeUpdateMode(b.mode), O = [];
34
- Array.isArray(b.exclude) ? O.push(...b.exclude) : typeof b.exclude == "string" && O.push(b.exclude);
35
- let k = O.flatMap((e) => e.split(",")).map((e) => e.trim()).filter(Boolean);
35
+ }), D = E.map(({ root: e, dir: t }) => S(e, t)), O = b.includeBranches ?? !1, k = d(b.mode), A = l(b.style), j = [];
36
+ Array.isArray(b.exclude) ? j.push(...b.exclude) : typeof b.exclude == "string" && j.push(b.exclude);
37
+ let M = j.flatMap((e) => e.split(",")).map((e) => e.trim()).filter(Boolean);
36
38
  try {
37
- validateCliOptions({
39
+ f({
38
40
  yes: b.yes,
39
- json: S
40
- }), S || (console.info(pc.cyan("\n🚀 Actions Up!\n")), C = createSpinner("Scanning GitHub Actions...").start());
41
- function g({ actionsToCheckCount: e, blockedByMode: f = [], outdated: p = [], skipped: m = [], scanResult: h, status: g }) {
42
- process.stdout.write(`${JSON.stringify(buildJsonReport({
41
+ json: w
42
+ }), w || (console.info(C.cyan("\n🚀 Actions Up!\n")), T = x("Scanning GitHub Actions...").start());
43
+ function o({ actionsToCheckCount: e, blockedByMode: t = [], outdated: n = [], skipped: r = [], scanResult: i, status: a }) {
44
+ process.stdout.write(`${JSON.stringify(v({
43
45
  recursive: b.recursive ?? !1,
44
- excludePatterns: k,
45
- directories: T,
46
+ excludePatterns: M,
47
+ directories: D,
46
48
  minAge: b.minAge,
47
49
  actionsToCheckCount: e,
48
- includeBranches: E,
49
- blockedByMode: f,
50
- scanResult: h,
51
- outdated: p,
52
- skipped: m,
53
- status: g,
54
- mode: D
50
+ includeBranches: O,
51
+ blockedByMode: t,
52
+ scanResult: i,
53
+ outdated: n,
54
+ skipped: r,
55
+ status: a,
56
+ style: A,
57
+ mode: k
55
58
  }), null, 2)}\n`);
56
59
  }
57
- let y = mergeScanResults(b.recursive ? await Promise.all(w.map(({ root: e, dir: f }) => scanRecursive(e, f))) : await Promise.all(w.map(({ root: e, dir: f }) => scanGitHubActions(e, f)))), x = y.actions.length, O = y.workflows.size, A = y.compositeActions.size;
58
- if (C?.success(`Found ${pc.yellow(x)} actions in ${pc.yellow(O)} workflows and ${pc.yellow(A)} composite actions`), x === 0) {
59
- if (S) {
60
- g({
60
+ let l = h(b.recursive ? await Promise.all(E.map(({ root: e, dir: t }) => _(e, t))) : await Promise.all(E.map(({ root: e, dir: t }) => y(e, t)))), d = l.actions.length, S = l.workflows.size, j = l.compositeActions.size;
61
+ if (T?.success(`Found ${C.yellow(d)} actions in ${C.yellow(S)} workflows and ${C.yellow(j)} composite actions`), d === 0) {
62
+ if (w) {
63
+ o({
61
64
  status: "no-actions-found",
62
65
  actionsToCheckCount: 0,
63
- scanResult: y
66
+ scanResult: l
64
67
  });
65
68
  return;
66
69
  }
67
- console.info(pc.green("\n✨ No GitHub Actions found in this repository"));
70
+ console.info(C.green("\n✨ No GitHub Actions found in this repository"));
68
71
  return;
69
72
  }
70
- let j = y.actions;
71
- if (k.length > 0) {
72
- let { parseExcludePatterns: e } = await import("../core/filters/parse-exclude-patterns.js"), f = e(k);
73
- f.length > 0 && (j = j.filter((e) => {
74
- let { name: p } = e;
75
- for (let e of f) if (e.test(p)) return !1;
73
+ let N = l.actions;
74
+ if (M.length > 0) {
75
+ let { parseExcludePatterns: e } = await import("../core/filters/parse-exclude-patterns.js"), t = e(M);
76
+ t.length > 0 && (N = N.filter((e) => {
77
+ let { name: n } = e;
78
+ for (let e of t) if (e.test(n)) return !1;
76
79
  return !0;
77
80
  }));
78
81
  }
79
- if (S || (C = createSpinner("Checking for updates...").start()), j.length === 0) {
80
- if (C?.success("No actions to check after excludes"), S) {
81
- g({
82
+ if (w || (T = x("Checking for updates...").start()), N.length === 0) {
83
+ if (T?.success("No actions to check after excludes"), w) {
84
+ o({
82
85
  status: "nothing-to-check",
83
86
  actionsToCheckCount: 0,
84
- scanResult: y
87
+ scanResult: l
85
88
  });
86
89
  return;
87
90
  }
88
- console.info(pc.green("\n✨ Nothing to check after excludes\n"));
91
+ console.info(C.green("\n✨ Nothing to check after excludes\n"));
89
92
  return;
90
93
  }
91
- let M = process.env.GITHUB_TOKEN, N = createGitHubClient(M), P = await checkUpdates(j, M, {
92
- client: N,
93
- includeBranches: E
94
- }), F = [];
95
- await Promise.all(P.map(async (e) => {
96
- await shouldIgnore(e.action.file, e.action.line) || F.push(e);
94
+ let P = process.env.GITHUB_TOKEN, F = a(P), I = await m(N, P, {
95
+ client: F,
96
+ includeBranches: O,
97
+ style: A
98
+ }), L = [];
99
+ await Promise.all(I.map(async (e) => {
100
+ await p(e.action.file, e.action.line) || L.push(e);
97
101
  }));
98
- let I = F.filter((e) => e.status === "skipped"), L = F.filter((e) => e.hasUpdate), R = b.minAge * 24 * 60 * 60 * 1e3, z = Date.now();
99
- L = L.filter((e) => e.publishedAt ? z - e.publishedAt.getTime() >= R : !0);
100
- let B = [];
101
- if (D !== "major") {
102
- let p = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Map(), g = /* @__PURE__ */ new Map(), _ = await Promise.all(L.map(async (p) => {
103
- let m = p.currentVersion;
104
- if (isSha(p.currentVersion)) {
105
- let f = await readInlineVersionComment(p.action.file, p.action.line, g);
106
- f && (m = f);
102
+ let R = L.filter((e) => e.status === "skipped"), z = L.filter((e) => e.hasUpdate), B = b.minAge * 24 * 60 * 60 * 1e3, V = Date.now();
103
+ z = z.filter((e) => e.publishedAt ? V - e.publishedAt.getTime() >= B : !0);
104
+ let H = [];
105
+ if (k !== "major") {
106
+ let n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), o = await Promise.all(z.map(async (n) => {
107
+ let r = n.currentVersion;
108
+ if (t(n.currentVersion)) {
109
+ let t = await e(n.action.file, n.action.line, a);
110
+ t && (r = t);
107
111
  }
108
- let h = getUpdateLevel(m, p.latestVersion);
112
+ let i = s(r, n.latestVersion);
109
113
  return {
110
- effectiveCurrentVersion: m,
111
- allowed: D === "minor" ? h === "minor" || h === "patch" || h === "none" : h === "patch" || h === "none",
112
- update: p
114
+ effectiveCurrentVersion: r,
115
+ allowed: k === "minor" ? i === "minor" || i === "patch" || i === "none" : i === "patch" || i === "none",
116
+ update: n
113
117
  };
114
- })), v = [], y = await Promise.all(_.map(async (e) => {
118
+ })), c = [], l = await Promise.all(o.map(async (e) => {
115
119
  if (e.allowed) return { update: e.update };
116
- let f = await getCompatibleUpdate(N, {
120
+ let t = await i(F, {
117
121
  currentVersion: e.effectiveCurrentVersion,
118
122
  actionName: e.update.action.name,
119
- tagsCache: p,
120
- shaCache: h,
121
- mode: D
123
+ tagsCache: n,
124
+ shaCache: r,
125
+ mode: k
122
126
  });
123
- return f ? { update: {
127
+ return t ? { update: {
124
128
  ...e.update,
125
- latestVersion: f.version,
126
- latestSha: f.sha,
129
+ latestVersion: t.version,
130
+ latestSha: t.sha,
127
131
  isBreaking: !1,
128
132
  hasUpdate: !0
129
133
  } } : { blocked: e.update };
130
134
  }));
131
- for (let e of y) {
135
+ for (let e of l) {
132
136
  if (e.update) {
133
- v.push(e.update);
137
+ c.push(e.update);
134
138
  continue;
135
139
  }
136
- B.push(e.blocked);
140
+ H.push(e.blocked);
137
141
  }
138
- L = v;
142
+ z = c;
139
143
  }
140
- let V = L.filter((e) => e.isBreaking);
141
- if (L.length === 0) {
142
- if (C?.success("All actions are up to date!"), S) {
143
- g({
144
- actionsToCheckCount: j.length,
144
+ z = z.map((e) => r(e, A));
145
+ let U = z.filter((e) => !e.targetRef).map((e) => ({
146
+ ...e,
147
+ skipReason: "unsupported-style",
148
+ status: "skipped",
149
+ hasUpdate: !1
150
+ }));
151
+ R.push(...U), z = z.filter((e) => e.targetRef);
152
+ let W = z.filter((e) => e.isBreaking);
153
+ if (z.length === 0) {
154
+ if (T?.success("All actions are up to date!"), w) {
155
+ o({
156
+ actionsToCheckCount: N.length,
145
157
  status: "up-to-date",
146
- blockedByMode: B,
147
- scanResult: y,
148
- skipped: I
158
+ blockedByMode: H,
159
+ scanResult: l,
160
+ skipped: R
149
161
  });
150
162
  return;
151
163
  }
152
- I.length > 0 && printSkippedWarning(I, E), B.length > 0 && printModeWarning(B, D), console.info(pc.green("\n✨ Everything is already at the latest version!\n"));
164
+ R.length > 0 && u(R, O, A), H.length > 0 && g(H, k), console.info(C.green("\n✨ Everything is already at the latest version!\n"));
153
165
  return;
154
166
  }
155
- if (C?.success(`Found ${pc.yellow(L.length)} updates available${V.length > 0 ? ` (${pc.redBright(V.length)} breaking)` : ""}`), S) {
156
- g({
157
- actionsToCheckCount: j.length,
167
+ if (T?.success(`Found ${C.yellow(z.length)} updates available${W.length > 0 ? ` (${C.redBright(W.length)} breaking)` : ""}`), w) {
168
+ o({
169
+ actionsToCheckCount: N.length,
158
170
  status: "updates-available",
159
- blockedByMode: B,
160
- scanResult: y,
161
- outdated: L,
162
- skipped: I
171
+ blockedByMode: H,
172
+ scanResult: l,
173
+ outdated: z,
174
+ skipped: R
163
175
  });
164
176
  return;
165
177
  }
166
- if (I.length > 0 && printSkippedWarning(I, E), B.length > 0 && printModeWarning(B, D), b.dryRun) {
167
- console.info(pc.yellow("\n📋 Dry Run - No changes will be made\n"));
168
- for (let e of L) console.info(`${pc.cyan(e.action.file ?? "unknown")}:\n${e.action.name}: ${pc.redBright(e.currentVersion)} → ${pc.green(e.latestVersion)} ${e.latestSha ? pc.gray(`(${e.latestSha.slice(0, 7)})`) : ""}\n`);
169
- console.info(pc.gray(`\n${L.length} actions would be updated\n`));
178
+ if (R.length > 0 && u(R, O, A), H.length > 0 && g(H, k), b.dryRun) {
179
+ console.info(C.yellow("\n📋 Dry Run - No changes will be made\n"));
180
+ for (let e of z) {
181
+ let t = e.targetRefStyle === "sha" && e.targetRef ? `${e.latestVersion} ${C.gray(`(${e.targetRef.slice(0, 7)})`)}` : e.targetRef ?? e.latestVersion;
182
+ console.info(`${C.cyan(e.action.file ?? "unknown")}:\n${e.action.name}: ${C.redBright(e.currentVersion)} → ${C.green(t)}\n`);
183
+ }
184
+ console.info(C.gray(`\n${z.length} actions would be updated\n`));
170
185
  return;
171
186
  }
172
187
  if (b.yes) {
173
- let e = L.filter((e) => e.latestSha);
188
+ let e = z.filter((e) => e.targetRef);
174
189
  if (e.length === 0) {
175
- console.info(pc.yellow("\n⚠️ No actions with SHA available for update\n"));
190
+ console.info(C.yellow("\n⚠️ No actionable updates available\n"));
176
191
  return;
177
192
  }
178
- console.info(pc.yellow(`\n🔄 Updating ${e.length} actions...\n`)), await applyUpdates(e), console.info(pc.green("\n✓ Updates applied successfully!"));
193
+ console.info(C.yellow(`\n🔄 Updating ${e.length} actions...\n`)), await c(e), console.info(C.green("\n✓ Updates applied successfully!"));
179
194
  } else {
180
- (I.length > 0 || B.length > 0) && console.info("");
181
- let e = await promptUpdateSelection(L, { showAge: b.minAge > 0 });
195
+ (R.length > 0 || H.length > 0) && console.info("");
196
+ let e = await n(z, { showAge: b.minAge > 0 });
182
197
  if (!e || e.length === 0) {
183
- console.info(pc.gray("\nNo updates applied"));
198
+ console.info(C.gray("\nNo updates applied"));
184
199
  return;
185
200
  }
186
- console.info(pc.yellow(`\n🔄 Updating ${e.length} selected actions...\n`)), await applyUpdates(e), console.info(pc.green("\n✓ Updates applied successfully!"));
201
+ console.info(C.yellow(`\n🔄 Updating ${e.length} selected actions...\n`)), await c(e), console.info(C.green("\n✓ Updates applied successfully!"));
187
202
  }
188
203
  } catch (e) {
189
- C?.error("Failed"), e instanceof Error && e.name === "GitHubRateLimitError" ? (console.error(pc.yellow("\n⚠️ Rate Limit Exceeded\n")), console.error(e.message), console.error(pc.gray("\nExample: GITHUB_TOKEN=ghp_xxxx actions-up\n"))) : console.error(pc.redBright("\nError:"), e instanceof Error ? e.message : String(e)), process.exit(1);
204
+ T?.error("Failed"), e instanceof Error && e.name === "GitHubRateLimitError" ? (console.error(C.yellow("\n⚠️ Rate Limit Exceeded\n")), console.error(e.message), console.error(C.gray("\nExample: GITHUB_TOKEN=ghp_xxxx actions-up\n"))) : console.error(C.redBright("\nError:"), e instanceof Error ? e.message : String(e)), process.exit(1);
190
205
  }
191
- }), C.parse();
206
+ }), T.parse();
192
207
  }
193
- export { run };
208
+ export { T as run };
@@ -1,4 +1,4 @@
1
- function mergeScanResults(e) {
1
+ function e(e) {
2
2
  let t = {
3
3
  compositeActions: /* @__PURE__ */ new Map(),
4
4
  workflows: /* @__PURE__ */ new Map(),
@@ -15,4 +15,4 @@ function mergeScanResults(e) {
15
15
  return n.has(t) ? !1 : (n.add(t), !0);
16
16
  }), t;
17
17
  }
18
- export { mergeScanResults };
18
+ export { e as mergeScanResults };
@@ -1,6 +1,6 @@
1
- function normalizeUpdateMode(e) {
1
+ function e(e) {
2
2
  let t = (e ?? "major").toLowerCase();
3
3
  if (t === "major" || t === "minor" || t === "patch") return t;
4
4
  throw Error(`Invalid mode "${e}". Expected "major", "minor", or "patch".`);
5
5
  }
6
- export { normalizeUpdateMode };
6
+ export { e as normalizeUpdateMode };
@@ -0,0 +1,8 @@
1
+ import { UpdateStyle } from '../types/update-style';
2
+ /**
3
+ * Normalizes the update style option.
4
+ *
5
+ * @param style - Raw style option.
6
+ * @returns Normalized update style.
7
+ */
8
+ export declare function normalizeUpdateStyle(style: undefined | string): UpdateStyle;
@@ -0,0 +1,6 @@
1
+ function e(e) {
2
+ let t = (e ?? "sha").toLowerCase();
3
+ if (t === "preserve" || t === "sha") return t;
4
+ throw Error(`Invalid style "${e}". Expected "sha" or "preserve".`);
5
+ }
6
+ export { e as normalizeUpdateStyle };
@@ -1,11 +1,11 @@
1
- import pc from "picocolors";
2
- function printModeWarning(t, n) {
1
+ import e from "picocolors";
2
+ function t(t, n) {
3
3
  if (t.length === 0) return;
4
4
  let r = new Intl.PluralRules("en-US", { type: "cardinal" }).select(t.length) === "one" ? "action" : "actions", i = n === "minor" ? "major" : "major/minor";
5
- console.info(pc.yellow(`\n⚠️ Skipped ${t.length} ${r} due to ${i} updates`));
5
+ console.info(e.yellow(`\n⚠️ Skipped ${t.length} ${r} due to ${i} updates`));
6
6
  for (let n of t) {
7
7
  let t = n.action.uses ?? `${n.action.name}@${n.currentVersion ?? "unknown"}`;
8
- console.info(pc.gray(` • ${t}`));
8
+ console.info(e.gray(` • ${t}`));
9
9
  }
10
10
  }
11
- export { printModeWarning };
11
+ export { t as printModeWarning };