actions-up 1.14.3 → 1.15.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/anchor-directory-inputs.d.ts +30 -0
- package/dist/cli/anchor-directory-inputs.js +13 -0
- package/dist/cli/index.js +113 -103
- package/dist/cli/normalize-update-mode.js +5 -1
- package/dist/cli/parse-arguments.d.ts +4 -0
- package/dist/cli/parse-arguments.js +6 -1
- package/dist/core/api/check-updates.js +125 -114
- package/dist/core/api/internal-rate-limit-error.d.ts +1 -1
- package/dist/core/api/internal-rate-limit-error.js +3 -3
- package/dist/core/api/make-request.js +1 -2
- package/dist/core/api/resolve-github-token-sync.js +1 -2
- package/dist/core/ast/update/apply-updates.js +4 -3
- package/dist/core/fs/find-repo-root.d.ts +12 -0
- package/dist/core/fs/find-repo-root.js +17 -0
- package/dist/core/interactive/format-version.js +1 -1
- package/dist/core/interactive/prompt-update-selection.js +5 -5
- package/dist/core/scan-github-actions.js +3 -1
- package/dist/core/scan-recursive.js +8 -5
- package/dist/package.js +1 -1
- package/package.json +2 -2
- package/readme.md +10 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for anchoring directory inputs at the repository root.
|
|
3
|
+
*/
|
|
4
|
+
interface AnchorDirectoryInputsOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Raw --dir value(s), or undefined when the flag was not provided.
|
|
7
|
+
*/
|
|
8
|
+
dir?: string[] | string;
|
|
9
|
+
/**
|
|
10
|
+
* Repository root detected by walking up, or null when none was found.
|
|
11
|
+
*/
|
|
12
|
+
root: string | null;
|
|
13
|
+
/**
|
|
14
|
+
* Current working directory the CLI was invoked from.
|
|
15
|
+
*/
|
|
16
|
+
cwd: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Anchors relative scan directories at the detected repository root.
|
|
20
|
+
*
|
|
21
|
+
* When the CLI runs from a nested subdirectory, the default `.github` and any
|
|
22
|
+
* simple relative `--dir` values are resolved against the repository root
|
|
23
|
+
* instead of the current directory. Absolute and parent-relative (`..`) values
|
|
24
|
+
* are intentional and left untouched.
|
|
25
|
+
*
|
|
26
|
+
* @param options - Detected root, current directory, and raw --dir value(s).
|
|
27
|
+
* @returns The directory input(s) to feed into resolveScanDirectories.
|
|
28
|
+
*/
|
|
29
|
+
export declare function anchorDirectoryInputs(options: AnchorDirectoryInputsOptions): undefined | string[] | string;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { GITHUB_DIRECTORY as e } from "../core/constants.js";
|
|
2
|
+
import { isAbsolute as t, join as n } from "node:path";
|
|
3
|
+
function r(r) {
|
|
4
|
+
let { root: i, cwd: a, dir: o } = r;
|
|
5
|
+
if (!i || i === a) return o;
|
|
6
|
+
let s = [];
|
|
7
|
+
return Array.isArray(o) ? s.push(...o) : typeof o == "string" && s.push(o), s.length === 0 && (s = ["."]), s.map((r) => {
|
|
8
|
+
if (t(r) || r.startsWith("..")) return r;
|
|
9
|
+
let a = n(i, r);
|
|
10
|
+
return a === i ? n(i, e) : a;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export { r as anchorDirectoryInputs };
|
package/dist/cli/index.js
CHANGED
|
@@ -6,129 +6,139 @@ import { getCompatibleUpdate as i } from "../core/api/get-compatible-update.js";
|
|
|
6
6
|
import { createGitHubClient as a } from "../core/api/create-github-client.js";
|
|
7
7
|
import { resolveScanDirectories as o } from "./resolve-scan-directories.js";
|
|
8
8
|
import { getUpdateLevel as s } from "../core/versions/get-update-level.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
9
|
+
import { anchorDirectoryInputs as c } from "./anchor-directory-inputs.js";
|
|
10
|
+
import { applyUpdates as l } from "../core/ast/update/apply-updates.js";
|
|
11
|
+
import { normalizeUpdateStyle as u } from "./normalize-update-style.js";
|
|
12
|
+
import { printSkippedWarning as d } from "./print-skipped-warning.js";
|
|
13
|
+
import { normalizeUpdateMode as f } from "./normalize-update-mode.js";
|
|
14
|
+
import { validateCliOptions as p } from "./validate-cli-options.js";
|
|
15
|
+
import { shouldIgnore as m } from "../core/ignore/should-ignore.js";
|
|
16
|
+
import { findRepoRoot as h } from "../core/fs/find-repo-root.js";
|
|
17
|
+
import { checkUpdates as g } from "../core/api/check-updates.js";
|
|
18
|
+
import { mergeScanResults as _ } from "./merge-scan-results.js";
|
|
19
|
+
import { printModeWarning as v } from "./print-mode-warning.js";
|
|
20
|
+
import { scanRecursive as y } from "../core/scan-recursive.js";
|
|
21
|
+
import { buildJsonReport as b } from "./build-json-report.js";
|
|
22
|
+
import { parseArguments as x } from "./parse-arguments.js";
|
|
23
|
+
import { scanGitHubActions as S } from "../core/scan-github-actions.js";
|
|
22
24
|
import "../core/index.js";
|
|
23
|
-
import { version as
|
|
24
|
-
import { createSpinner as
|
|
25
|
-
import { resolve as
|
|
25
|
+
import { version as C } from "../package.js";
|
|
26
|
+
import { createSpinner as w } from "nanospinner";
|
|
27
|
+
import { resolve as T } from "node:path";
|
|
26
28
|
import "node:worker_threads";
|
|
27
|
-
import
|
|
28
|
-
function
|
|
29
|
-
let e =
|
|
29
|
+
import E from "picocolors";
|
|
30
|
+
function D() {
|
|
31
|
+
let e = x(process.argv.slice(2), C);
|
|
30
32
|
if (e.kind === "help" || e.kind === "version") {
|
|
31
33
|
console.info(e.text);
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
34
|
-
e.kind === "error" && (console.error(
|
|
36
|
+
e.kind === "error" && (console.error(E.redBright("\nError:"), e.message), process.exit(1)), O(e.options);
|
|
35
37
|
}
|
|
36
|
-
async function
|
|
37
|
-
let
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
async function O(x) {
|
|
39
|
+
let C = x.json ?? !1, D = x.quiet ?? !1, O = null, k = process.cwd(), A = x.recursive ? null : await h(k), j = o({
|
|
40
|
+
dir: c({
|
|
41
|
+
dir: x.dir,
|
|
42
|
+
root: A,
|
|
43
|
+
cwd: k
|
|
44
|
+
}),
|
|
45
|
+
recursive: x.recursive,
|
|
46
|
+
cwd: k
|
|
47
|
+
}), M = j.map(({ root: e, dir: t }) => T(e, t)), N = x.includeBranches ?? !1, P = f(x.mode), F = u(x.style), I = [];
|
|
48
|
+
Array.isArray(x.exclude) ? I.push(...x.exclude) : typeof x.exclude == "string" && I.push(x.exclude);
|
|
49
|
+
let L = I.flatMap((e) => e.split(",")).map((e) => e.trim()).filter(Boolean);
|
|
44
50
|
try {
|
|
45
|
-
|
|
46
|
-
yes:
|
|
47
|
-
json:
|
|
48
|
-
}),
|
|
51
|
+
p({
|
|
52
|
+
yes: x.yes,
|
|
53
|
+
json: C
|
|
54
|
+
}), C || (console.info(E.cyan("\n🚀 Actions Up!\n")), O = w("Scanning GitHub Actions...").start());
|
|
49
55
|
function o({ actionsToCheckCount: e, blockedByMode: t = [], outdated: n = [], skipped: r = [], scanResult: i, status: a }) {
|
|
50
|
-
process.stdout.write(`${JSON.stringify(
|
|
51
|
-
recursive:
|
|
52
|
-
excludePatterns:
|
|
53
|
-
directories:
|
|
54
|
-
minAge:
|
|
56
|
+
process.stdout.write(`${JSON.stringify(b({
|
|
57
|
+
recursive: x.recursive ?? !1,
|
|
58
|
+
excludePatterns: L,
|
|
59
|
+
directories: M,
|
|
60
|
+
minAge: x.minAge,
|
|
55
61
|
actionsToCheckCount: e,
|
|
56
|
-
includeBranches:
|
|
62
|
+
includeBranches: N,
|
|
57
63
|
blockedByMode: t,
|
|
58
64
|
scanResult: i,
|
|
59
65
|
outdated: n,
|
|
60
66
|
skipped: r,
|
|
61
67
|
status: a,
|
|
62
|
-
style:
|
|
63
|
-
mode:
|
|
68
|
+
style: F,
|
|
69
|
+
mode: P
|
|
64
70
|
}), null, 2)}\n`);
|
|
65
71
|
}
|
|
66
|
-
let
|
|
67
|
-
if (
|
|
68
|
-
if (
|
|
72
|
+
let c = _(x.recursive ? await Promise.all(j.map(({ root: e, dir: t }) => y(e, t))) : await Promise.all(j.map(({ root: e, dir: t }) => S(e, t)))), u = c.actions.length, f = c.workflows.size, h = c.compositeActions.size;
|
|
73
|
+
if (O?.success(`Found ${E.yellow(u)} actions in ${E.yellow(f)} workflows and ${E.yellow(h)} composite actions`), u === 0) {
|
|
74
|
+
if (C) {
|
|
69
75
|
o({
|
|
70
76
|
status: "no-actions-found",
|
|
71
77
|
actionsToCheckCount: 0,
|
|
72
|
-
scanResult:
|
|
78
|
+
scanResult: c
|
|
73
79
|
});
|
|
74
80
|
return;
|
|
75
81
|
}
|
|
76
|
-
console.info(
|
|
82
|
+
console.info(E.green("\n✨ No GitHub Actions found in this repository"));
|
|
77
83
|
return;
|
|
78
84
|
}
|
|
79
|
-
let
|
|
80
|
-
if (
|
|
81
|
-
let { parseExcludePatterns: e } = await import("../core/filters/parse-exclude-patterns.js"), t = e(
|
|
82
|
-
t.length > 0 && (
|
|
85
|
+
let T = c.actions;
|
|
86
|
+
if (L.length > 0) {
|
|
87
|
+
let { parseExcludePatterns: e } = await import("../core/filters/parse-exclude-patterns.js"), t = e(L);
|
|
88
|
+
t.length > 0 && (T = T.filter((e) => {
|
|
83
89
|
let { name: n } = e;
|
|
84
90
|
for (let e of t) if (e.test(n)) return !1;
|
|
85
91
|
return !0;
|
|
86
92
|
}));
|
|
87
93
|
}
|
|
88
|
-
if (
|
|
89
|
-
if (
|
|
94
|
+
if (C || (O = w("Checking for updates...").start()), T.length === 0) {
|
|
95
|
+
if (O?.success("No actions to check after excludes"), C) {
|
|
90
96
|
o({
|
|
91
97
|
status: "nothing-to-check",
|
|
92
98
|
actionsToCheckCount: 0,
|
|
93
|
-
scanResult:
|
|
99
|
+
scanResult: c
|
|
94
100
|
});
|
|
95
101
|
return;
|
|
96
102
|
}
|
|
97
|
-
console.info(
|
|
103
|
+
console.info(E.green("\n✨ Nothing to check after excludes\n"));
|
|
98
104
|
return;
|
|
99
105
|
}
|
|
100
|
-
let
|
|
101
|
-
client:
|
|
102
|
-
includeBranches:
|
|
103
|
-
style:
|
|
104
|
-
}),
|
|
106
|
+
let k = process.env.GITHUB_TOKEN, A = a(k), I = await g(T, k, {
|
|
107
|
+
client: A,
|
|
108
|
+
includeBranches: N,
|
|
109
|
+
style: F
|
|
110
|
+
}), R = [];
|
|
105
111
|
await Promise.all(I.map(async (e) => {
|
|
106
|
-
await
|
|
112
|
+
await m(e.action.file, e.action.line) || R.push(e);
|
|
107
113
|
}));
|
|
108
|
-
let
|
|
109
|
-
|
|
110
|
-
let
|
|
111
|
-
if (
|
|
112
|
-
let n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), o = await Promise.all(
|
|
114
|
+
let z = R.filter((e) => e.status === "skipped"), B = R.filter((e) => e.hasUpdate), V = x.minAge * 24 * 60 * 60 * 1e3, H = Date.now();
|
|
115
|
+
B = B.filter((e) => e.publishedAt ? H - e.publishedAt.getTime() >= V : !0);
|
|
116
|
+
let U = [];
|
|
117
|
+
if (P !== "major") {
|
|
118
|
+
let n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), o = await Promise.all(B.map(async (n) => {
|
|
113
119
|
let r = n.currentVersion;
|
|
114
120
|
if (t(n.currentVersion)) {
|
|
115
121
|
let t = await e(n.action.file, n.action.line, a);
|
|
116
122
|
t && (r = t);
|
|
117
123
|
}
|
|
118
|
-
let i = s(r, n.latestVersion)
|
|
124
|
+
let i = s(r, n.latestVersion), o = (P === "minor" ? [
|
|
125
|
+
"minor",
|
|
126
|
+
"patch",
|
|
127
|
+
"none"
|
|
128
|
+
] : ["patch", "none"]).includes(i);
|
|
119
129
|
return {
|
|
120
130
|
effectiveCurrentVersion: r,
|
|
121
|
-
allowed:
|
|
131
|
+
allowed: o,
|
|
122
132
|
update: n
|
|
123
133
|
};
|
|
124
134
|
})), c = [], l = await Promise.all(o.map(async (e) => {
|
|
125
135
|
if (e.allowed) return { update: e.update };
|
|
126
|
-
let t = await i(
|
|
136
|
+
let t = await i(A, {
|
|
127
137
|
currentVersion: e.effectiveCurrentVersion,
|
|
128
138
|
actionName: e.update.action.name,
|
|
129
139
|
tagsCache: n,
|
|
130
140
|
shaCache: r,
|
|
131
|
-
mode:
|
|
141
|
+
mode: P
|
|
132
142
|
});
|
|
133
143
|
return t ? { update: {
|
|
134
144
|
...e.update,
|
|
@@ -143,71 +153,71 @@ async function E(y) {
|
|
|
143
153
|
c.push(e.update);
|
|
144
154
|
continue;
|
|
145
155
|
}
|
|
146
|
-
|
|
156
|
+
U.push(e.blocked);
|
|
147
157
|
}
|
|
148
|
-
|
|
158
|
+
B = c;
|
|
149
159
|
}
|
|
150
|
-
|
|
151
|
-
let
|
|
160
|
+
B = B.map((e) => r(e, F));
|
|
161
|
+
let W = B.filter((e) => !e.targetRef).map((e) => ({
|
|
152
162
|
...e,
|
|
153
163
|
skipReason: "unsupported-style",
|
|
154
164
|
status: "skipped",
|
|
155
165
|
hasUpdate: !1
|
|
156
166
|
}));
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (z.length === 0) {
|
|
160
|
-
if (T?.success("All actions are up to date!"), x) {
|
|
167
|
+
if (z.push(...W), B = B.filter((e) => e.targetRef), B.length === 0) {
|
|
168
|
+
if (O?.success("All actions are up to date!"), C) {
|
|
161
169
|
o({
|
|
162
|
-
actionsToCheckCount:
|
|
170
|
+
actionsToCheckCount: T.length,
|
|
163
171
|
status: "up-to-date",
|
|
164
|
-
blockedByMode:
|
|
165
|
-
scanResult:
|
|
166
|
-
skipped:
|
|
172
|
+
blockedByMode: U,
|
|
173
|
+
scanResult: c,
|
|
174
|
+
skipped: z
|
|
167
175
|
});
|
|
168
176
|
return;
|
|
169
177
|
}
|
|
170
|
-
|
|
178
|
+
!D && z.length > 0 && d(z, N, F), !D && U.length > 0 && v(U, P), console.info(E.green("\n✨ Everything is already at the latest version!\n"));
|
|
171
179
|
return;
|
|
172
180
|
}
|
|
173
|
-
|
|
181
|
+
let G = B.filter((e) => e.isBreaking);
|
|
182
|
+
if (O?.success(`Found ${E.yellow(B.length)} updates available${G.length > 0 ? ` (${E.redBright(G.length)} breaking)` : ""}`), C) {
|
|
174
183
|
o({
|
|
175
|
-
actionsToCheckCount:
|
|
184
|
+
actionsToCheckCount: T.length,
|
|
176
185
|
status: "updates-available",
|
|
177
|
-
blockedByMode:
|
|
178
|
-
scanResult:
|
|
179
|
-
outdated:
|
|
180
|
-
skipped:
|
|
186
|
+
blockedByMode: U,
|
|
187
|
+
scanResult: c,
|
|
188
|
+
outdated: B,
|
|
189
|
+
skipped: z
|
|
181
190
|
});
|
|
182
191
|
return;
|
|
183
192
|
}
|
|
184
|
-
if (
|
|
185
|
-
console.info(
|
|
186
|
-
for (let e of
|
|
187
|
-
let t = e.targetRefStyle === "sha" && e.targetRef ? `${e.latestVersion} ${
|
|
188
|
-
console.info(`${
|
|
193
|
+
if (!D && z.length > 0 && d(z, N, F), !D && U.length > 0 && v(U, P), x.dryRun) {
|
|
194
|
+
console.info(E.yellow("\n📋 Dry Run - No changes will be made\n"));
|
|
195
|
+
for (let e of B) {
|
|
196
|
+
let t = e.targetRefStyle === "sha" && e.targetRef ? `${e.latestVersion} ${E.gray(`(${e.targetRef.slice(0, 7)})`)}` : e.targetRef ?? e.latestVersion;
|
|
197
|
+
console.info(`${E.cyan(e.action.file ?? "unknown")}:\n${e.action.name}: ${E.redBright(e.currentVersion)} → ${E.green(t)}\n`);
|
|
189
198
|
}
|
|
190
|
-
console.info(
|
|
199
|
+
console.info(E.gray(`\n${B.length} actions would be updated\n`));
|
|
191
200
|
return;
|
|
192
201
|
}
|
|
193
|
-
if (
|
|
194
|
-
let e =
|
|
202
|
+
if (x.yes) {
|
|
203
|
+
let e = B.filter((e) => e.targetRef);
|
|
195
204
|
if (e.length === 0) {
|
|
196
|
-
console.info(
|
|
205
|
+
console.info(E.yellow("\n⚠️ No actionable updates available\n"));
|
|
197
206
|
return;
|
|
198
207
|
}
|
|
199
|
-
console.info(
|
|
208
|
+
console.info(E.yellow(`\n🔄 Updating ${e.length} actions...\n`)), await l(e);
|
|
200
209
|
} else {
|
|
201
|
-
(
|
|
202
|
-
let e = await n(
|
|
210
|
+
!D && (z.length > 0 || U.length > 0) && console.info("");
|
|
211
|
+
let e = await n(B, { showAge: x.minAge > 0 });
|
|
203
212
|
if (!e || e.length === 0) {
|
|
204
|
-
console.info(
|
|
213
|
+
console.info(E.gray("\nNo updates applied"));
|
|
205
214
|
return;
|
|
206
215
|
}
|
|
207
|
-
console.info(
|
|
216
|
+
console.info(E.yellow(`\n🔄 Updating ${e.length} selected actions...\n`)), await l(e);
|
|
208
217
|
}
|
|
218
|
+
console.info(E.green("\n✓ Updates applied successfully!"));
|
|
209
219
|
} catch (e) {
|
|
210
|
-
|
|
220
|
+
O?.error("Failed"), e instanceof Error && e.name === "GitHubRateLimitError" ? (console.error(E.yellow("\n⚠️ Rate Limit Exceeded\n")), console.error(e.message), console.error(E.gray("\nExample: GITHUB_TOKEN=ghp_xxxx actions-up\n"))) : console.error(E.redBright("\nError:"), e instanceof Error ? e.message : String(e)), process.exit(1);
|
|
211
221
|
}
|
|
212
222
|
}
|
|
213
|
-
export {
|
|
223
|
+
export { D as run };
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
function e(e) {
|
|
2
2
|
let t = (e ?? "major").toLowerCase();
|
|
3
|
-
if (
|
|
3
|
+
if ([
|
|
4
|
+
"major",
|
|
5
|
+
"minor",
|
|
6
|
+
"patch"
|
|
7
|
+
].includes(t)) return t;
|
|
4
8
|
throw Error(`Invalid mode "${e}". Expected "major", "minor", or "patch".`);
|
|
5
9
|
}
|
|
6
10
|
export { e as normalizeUpdateMode };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseArgs as e } from "node:util";
|
|
2
|
-
var t = "Usage:\n $ actions-up [options]\n\nOptions:\n --dir <directory> Directory to scan (repeatable). Default: .github, or . with --recursive\n --dry-run Preview changes without applying them\n --exclude <regex> Exclude actions by regex (repeatable)\n --include-branches Also check actions pinned to branches (default: false)\n --json Output update information as machine-readable JSON\n --min-age <days> Minimum age in days for updates (default: 0)\n --mode <mode> Update mode: major, minor, or patch (default: major)\n --style <style> Update style: sha or preserve (default: sha)\n -r, --recursive Recursively scan directories for YAML files\n -y, --yes Skip all confirmations\n -h, --help Display this message\n -v, --version Display version number", n = {
|
|
2
|
+
var t = "Usage:\n $ actions-up [options]\n\nOptions:\n --dir <directory> Directory to scan (repeatable). Default: .github, or . with --recursive\n --dry-run Preview changes without applying them\n --exclude <regex> Exclude actions by regex (repeatable)\n --include-branches Also check actions pinned to branches (default: false)\n --json Output update information as machine-readable JSON\n --min-age <days> Minimum age in days for updates (default: 0)\n --mode <mode> Update mode: major, minor, or patch (default: major)\n --style <style> Update style: sha or preserve (default: sha)\n -r, --recursive Recursively scan directories for YAML files\n -y, --yes Skip all confirmations\n -q, --quiet Suppress skipped/blocked warnings\n -h, --help Display this message\n -v, --version Display version number", n = {
|
|
3
3
|
exclude: {
|
|
4
4
|
type: "string",
|
|
5
5
|
multiple: !0
|
|
@@ -17,6 +17,10 @@ var t = "Usage:\n $ actions-up [options]\n\nOptions:\n --dir <directory> Dir
|
|
|
17
17
|
type: "string",
|
|
18
18
|
multiple: !0
|
|
19
19
|
},
|
|
20
|
+
quiet: {
|
|
21
|
+
type: "boolean",
|
|
22
|
+
short: "q"
|
|
23
|
+
},
|
|
20
24
|
help: {
|
|
21
25
|
type: "boolean",
|
|
22
26
|
short: "h"
|
|
@@ -60,6 +64,7 @@ function r(r, i) {
|
|
|
60
64
|
recursive: a.recursive,
|
|
61
65
|
yes: a.yes ?? !1,
|
|
62
66
|
exclude: a.exclude,
|
|
67
|
+
quiet: a.quiet,
|
|
63
68
|
json: a.json,
|
|
64
69
|
dir: a.dir,
|
|
65
70
|
minAge: s
|
|
@@ -3,173 +3,183 @@ import { preserveTagFormat as t } from "../versions/preserve-tag-format.js";
|
|
|
3
3
|
import { normalizeVersion as n } from "../versions/normalize-version.js";
|
|
4
4
|
import { createGitHubClient as r } from "./create-github-client.js";
|
|
5
5
|
import i from "semver";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
let h = /* @__PURE__ */ new Map();
|
|
10
|
-
for (let e of m) {
|
|
11
|
-
let t = h.get(e.name) ?? [];
|
|
12
|
-
t.push(e), h.set(e.name, t);
|
|
6
|
+
var a = class extends Error {
|
|
7
|
+
constructor(e, t) {
|
|
8
|
+
super(e, t), this.name = "GitHubRateLimitError";
|
|
13
9
|
}
|
|
14
|
-
|
|
10
|
+
};
|
|
11
|
+
async function o(t, o, c) {
|
|
12
|
+
let f = c?.client ?? r(o), p = c?.includeBranches ?? !1, m = c?.style ?? "sha", h = t.filter((e) => e.type === "external" || e.type === "reusable-workflow");
|
|
13
|
+
if (h.length === 0) return [];
|
|
14
|
+
let g = /* @__PURE__ */ new Map();
|
|
15
|
+
for (let e of h) {
|
|
16
|
+
let t = g.get(e.name) ?? [];
|
|
17
|
+
t.push(e), g.set(e.name, t);
|
|
18
|
+
}
|
|
19
|
+
let _ = {
|
|
15
20
|
rateLimitError: null,
|
|
16
21
|
rateLimitHit: !1
|
|
17
|
-
},
|
|
18
|
-
|
|
22
|
+
}, v = [];
|
|
23
|
+
async function y(t) {
|
|
24
|
+
if (_.rateLimitHit) return {
|
|
19
25
|
currentRefType: "unknown",
|
|
20
26
|
publishedAt: null,
|
|
21
27
|
version: null,
|
|
22
|
-
actionName:
|
|
28
|
+
actionName: t,
|
|
23
29
|
sha: null
|
|
24
|
-
}
|
|
25
|
-
let
|
|
26
|
-
if (
|
|
30
|
+
};
|
|
31
|
+
let r = t.split("/");
|
|
32
|
+
if (r.length < 2) return {
|
|
27
33
|
currentRefType: "unknown",
|
|
28
34
|
publishedAt: null,
|
|
29
35
|
version: null,
|
|
30
|
-
actionName:
|
|
36
|
+
actionName: t,
|
|
31
37
|
sha: null
|
|
32
|
-
}
|
|
33
|
-
let [
|
|
34
|
-
if (!
|
|
38
|
+
};
|
|
39
|
+
let [a, o] = r;
|
|
40
|
+
if (!a || !o) return {
|
|
35
41
|
currentRefType: "unknown",
|
|
36
42
|
publishedAt: null,
|
|
37
43
|
version: null,
|
|
38
|
-
actionName:
|
|
44
|
+
actionName: t,
|
|
39
45
|
sha: null
|
|
40
|
-
}
|
|
46
|
+
};
|
|
41
47
|
try {
|
|
42
|
-
let
|
|
43
|
-
if (
|
|
44
|
-
let e = await
|
|
45
|
-
if (
|
|
46
|
-
currentRefType:
|
|
48
|
+
let r = g.get(t)[0]?.version, s = u(r);
|
|
49
|
+
if (r && !l(r) && !e(r)) {
|
|
50
|
+
let e = await f.getRefType(a, o, r);
|
|
51
|
+
if (s = e === "branch" || e === "tag" ? e : s, e === "branch" && !p) return {
|
|
52
|
+
currentRefType: s,
|
|
47
53
|
skipReason: "branch",
|
|
48
54
|
status: "skipped",
|
|
49
55
|
publishedAt: null,
|
|
50
56
|
version: null,
|
|
51
|
-
actionName:
|
|
57
|
+
actionName: t,
|
|
52
58
|
sha: null
|
|
53
|
-
}
|
|
59
|
+
};
|
|
54
60
|
}
|
|
55
|
-
let
|
|
56
|
-
if (!
|
|
57
|
-
let e = await
|
|
58
|
-
|
|
61
|
+
let c = await f.getLatestRelease(a, o);
|
|
62
|
+
if (!c) {
|
|
63
|
+
let e = await f.getAllReleases(a, o, 1);
|
|
64
|
+
c = e.find((e) => !e.isPrerelease) ?? e[0] ?? null;
|
|
59
65
|
}
|
|
60
|
-
if (
|
|
61
|
-
let { publishedAt:
|
|
66
|
+
if (c) {
|
|
67
|
+
let { publishedAt: r, version: l, sha: u } = c, p = !1;
|
|
62
68
|
{
|
|
63
|
-
let t = n(
|
|
64
|
-
|
|
69
|
+
let t = n(l), r = !!(l && l.trim() !== ""), a = r && /^v?\d+$/u.test(l.trim()), o = i.valid(t);
|
|
70
|
+
p = !r || a || !o || !e(l);
|
|
65
71
|
}
|
|
66
|
-
if (
|
|
67
|
-
let
|
|
68
|
-
if (
|
|
69
|
-
let
|
|
72
|
+
if (p) {
|
|
73
|
+
let r = await f.getAllTags(a, o, 30);
|
|
74
|
+
if (r.length > 0) {
|
|
75
|
+
let c = r.filter((t) => e(t.tag)).map((e) => ({
|
|
70
76
|
v: i.valid(n(e.tag)),
|
|
71
77
|
raw: e
|
|
72
78
|
}));
|
|
73
|
-
if (
|
|
74
|
-
|
|
79
|
+
if (c.length > 0) {
|
|
80
|
+
c.sort((e, t) => {
|
|
75
81
|
let n = i.rcompare(e.v, t.v);
|
|
76
82
|
if (n !== 0) return n;
|
|
77
83
|
let r = +!!/\d+\.\d+/u.test(e.raw.tag);
|
|
78
84
|
return +!!/\d+\.\d+/u.test(t.raw.tag) - r;
|
|
79
85
|
});
|
|
80
|
-
let e =
|
|
81
|
-
if (!
|
|
82
|
-
let n = e.tag,
|
|
83
|
-
if (!
|
|
84
|
-
|
|
86
|
+
let e = c[0].raw, r = i.valid(n(l) ?? void 0);
|
|
87
|
+
if (!r || i.gt(c[0].v, r) || i.eq(c[0].v, r) && /\d+\.\d+/u.test(e.tag)) {
|
|
88
|
+
let n = e.tag, r = e.sha?.length ? e.sha : null;
|
|
89
|
+
if (!r && n) try {
|
|
90
|
+
r = await f.getTagSha(a, o, n);
|
|
85
91
|
} catch (e) {
|
|
86
|
-
if (
|
|
92
|
+
if (d(e)) throw e;
|
|
87
93
|
}
|
|
88
|
-
return
|
|
89
|
-
currentRefType:
|
|
94
|
+
return {
|
|
95
|
+
currentRefType: s,
|
|
90
96
|
version: n,
|
|
91
97
|
publishedAt: null,
|
|
92
|
-
sha:
|
|
93
|
-
actionName:
|
|
94
|
-
}
|
|
98
|
+
sha: r,
|
|
99
|
+
actionName: t
|
|
100
|
+
};
|
|
95
101
|
}
|
|
96
102
|
}
|
|
97
103
|
}
|
|
98
104
|
}
|
|
99
|
-
if (
|
|
100
|
-
let e =
|
|
105
|
+
if (l) {
|
|
106
|
+
let e = u;
|
|
101
107
|
try {
|
|
102
|
-
|
|
108
|
+
u = await f.getTagSha(a, o, l) ?? e;
|
|
103
109
|
} catch (t) {
|
|
104
|
-
if (
|
|
105
|
-
|
|
110
|
+
if (d(t)) throw t;
|
|
111
|
+
u = e;
|
|
106
112
|
}
|
|
107
113
|
}
|
|
108
|
-
return
|
|
109
|
-
currentRefType:
|
|
114
|
+
return {
|
|
115
|
+
currentRefType: s,
|
|
110
116
|
status: "ok",
|
|
111
|
-
publishedAt:
|
|
112
|
-
actionName:
|
|
113
|
-
version:
|
|
114
|
-
sha:
|
|
115
|
-
}
|
|
117
|
+
publishedAt: r,
|
|
118
|
+
actionName: t,
|
|
119
|
+
version: l,
|
|
120
|
+
sha: u
|
|
121
|
+
};
|
|
116
122
|
}
|
|
117
|
-
let
|
|
118
|
-
if (
|
|
119
|
-
let
|
|
123
|
+
let m = await f.getAllTags(a, o, 30);
|
|
124
|
+
if (m.length > 0) {
|
|
125
|
+
let r = m.filter((t) => e(t.tag)).map((e) => ({
|
|
120
126
|
v: i.valid(n(e.tag)),
|
|
121
127
|
raw: e
|
|
122
128
|
})), c;
|
|
123
|
-
|
|
129
|
+
r.length > 0 ? (r.sort((e, t) => {
|
|
124
130
|
let n = i.rcompare(e.v, t.v);
|
|
125
131
|
if (n !== 0) return n;
|
|
126
132
|
let r = +!!/\d+\.\d+/u.test(e.raw.tag);
|
|
127
133
|
return +!!/\d+\.\d+/u.test(t.raw.tag) - r;
|
|
128
|
-
}), c =
|
|
129
|
-
let l = c.tag,
|
|
130
|
-
if (!
|
|
131
|
-
|
|
134
|
+
}), c = r[0].raw) : c = m[0];
|
|
135
|
+
let l = c.tag, u = c.sha?.length ? c.sha : null;
|
|
136
|
+
if (!u && l) try {
|
|
137
|
+
u = await f.getTagSha(a, o, l);
|
|
132
138
|
} catch (e) {
|
|
133
|
-
if (
|
|
139
|
+
if (d(e)) throw e;
|
|
134
140
|
}
|
|
135
|
-
return
|
|
136
|
-
currentRefType:
|
|
141
|
+
return {
|
|
142
|
+
currentRefType: s,
|
|
137
143
|
status: "ok",
|
|
138
144
|
publishedAt: null,
|
|
139
|
-
actionName:
|
|
145
|
+
actionName: t,
|
|
140
146
|
version: l,
|
|
141
|
-
sha:
|
|
142
|
-
}
|
|
147
|
+
sha: u
|
|
148
|
+
};
|
|
143
149
|
}
|
|
144
|
-
return
|
|
145
|
-
currentRefType:
|
|
150
|
+
return {
|
|
151
|
+
currentRefType: s,
|
|
146
152
|
publishedAt: null,
|
|
147
153
|
version: null,
|
|
148
|
-
actionName:
|
|
154
|
+
actionName: t,
|
|
149
155
|
sha: null
|
|
150
|
-
}
|
|
156
|
+
};
|
|
151
157
|
} catch (e) {
|
|
152
|
-
return e instanceof Error && e.name === "GitHubRateLimitError" ? (
|
|
158
|
+
return e instanceof Error && e.name === "GitHubRateLimitError" ? (_.rateLimitHit = !0, _.rateLimitError = e, {
|
|
153
159
|
currentRefType: "unknown",
|
|
154
160
|
publishedAt: null,
|
|
155
161
|
version: null,
|
|
156
|
-
actionName:
|
|
162
|
+
actionName: t,
|
|
157
163
|
sha: null
|
|
158
|
-
}
|
|
164
|
+
}) : (console.warn(`Failed to check ${t}:`, e), {
|
|
159
165
|
currentRefType: "unknown",
|
|
160
166
|
publishedAt: null,
|
|
161
167
|
version: null,
|
|
162
|
-
actionName:
|
|
168
|
+
actionName: t,
|
|
163
169
|
sha: null
|
|
164
|
-
}
|
|
170
|
+
});
|
|
165
171
|
}
|
|
166
|
-
}), Promise.resolve([]));
|
|
167
|
-
if (g.rateLimitError) {
|
|
168
|
-
let e = !!(a ?? 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);
|
|
169
|
-
throw n.name = "GitHubRateLimitError", n;
|
|
170
172
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
+
async function b(e) {
|
|
174
|
+
let t = e.next();
|
|
175
|
+
t.done || (v.push(await y(t.value)), await b(e));
|
|
176
|
+
}
|
|
177
|
+
if (await b(g.keys()), _.rateLimitError) {
|
|
178
|
+
let e = !!(o ?? process.env.GITHUB_TOKEN);
|
|
179
|
+
throw new a(`${_.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"}`);
|
|
180
|
+
}
|
|
181
|
+
let x = /* @__PURE__ */ new Map();
|
|
182
|
+
for (let e of v) x.set(e.actionName, {
|
|
173
183
|
currentRefType: e.currentRefType,
|
|
174
184
|
publishedAt: e.publishedAt,
|
|
175
185
|
actionName: e.actionName,
|
|
@@ -178,10 +188,10 @@ async function a(t, a, s) {
|
|
|
178
188
|
status: e.status,
|
|
179
189
|
sha: e.sha
|
|
180
190
|
});
|
|
181
|
-
let
|
|
182
|
-
for (let e of
|
|
183
|
-
let t =
|
|
184
|
-
t ?
|
|
191
|
+
let S = [];
|
|
192
|
+
for (let e of h) {
|
|
193
|
+
let t = x.get(e.name);
|
|
194
|
+
t ? S.push(s(e, {
|
|
185
195
|
publishedAt: t.publishedAt,
|
|
186
196
|
version: t.version,
|
|
187
197
|
sha: t.sha
|
|
@@ -189,20 +199,20 @@ async function a(t, a, s) {
|
|
|
189
199
|
currentRefType: t.currentRefType,
|
|
190
200
|
skipReason: t.skipReason,
|
|
191
201
|
status: t.status,
|
|
192
|
-
style:
|
|
193
|
-
})) :
|
|
202
|
+
style: m
|
|
203
|
+
})) : S.push(s(e, {
|
|
194
204
|
publishedAt: null,
|
|
195
205
|
version: null,
|
|
196
206
|
sha: null
|
|
197
207
|
}, {
|
|
198
|
-
currentRefType:
|
|
199
|
-
style:
|
|
208
|
+
currentRefType: u(e.version),
|
|
209
|
+
style: m
|
|
200
210
|
}));
|
|
201
211
|
}
|
|
202
|
-
return
|
|
212
|
+
return S;
|
|
203
213
|
}
|
|
204
|
-
function
|
|
205
|
-
let { version: o, sha:
|
|
214
|
+
function s(e, r, a) {
|
|
215
|
+
let { version: o, sha: s, publishedAt: u } = r, d = e.version ?? "unknown", f = n(d), p = a.currentRefType, { style: m } = a, h = (m === "preserve" && p === "tag" ? t(d, o) : null) ?? o, g = h ? n(h) : null, _ = a.status ?? "ok", v = a.skipReason;
|
|
206
216
|
if (_ === "skipped") return {
|
|
207
217
|
currentRefType: p,
|
|
208
218
|
currentVersion: d,
|
|
@@ -211,11 +221,12 @@ function o(e, r, a) {
|
|
|
211
221
|
latestVersion: o,
|
|
212
222
|
publishedAt: u,
|
|
213
223
|
skipReason: v,
|
|
214
|
-
latestSha:
|
|
224
|
+
latestSha: s,
|
|
215
225
|
action: e,
|
|
216
226
|
status: _
|
|
217
227
|
};
|
|
218
|
-
|
|
228
|
+
let y = !1, b = !1;
|
|
229
|
+
if (f && l(f)) s ? y = !c(f, s) : g && (y = !0);
|
|
219
230
|
else if (f && g) {
|
|
220
231
|
let t = i.valid(f), n = i.valid(g);
|
|
221
232
|
if (t && n) {
|
|
@@ -223,7 +234,7 @@ function o(e, r, a) {
|
|
|
223
234
|
let e = i.major(t);
|
|
224
235
|
b = i.major(n) > e;
|
|
225
236
|
}
|
|
226
|
-
!y && i.eq(t, n) && !
|
|
237
|
+
!y && i.eq(t, n) && !l(e.version) && s && m === "sha" && (y = !0, b = !1);
|
|
227
238
|
} else f !== g && (y = !0);
|
|
228
239
|
}
|
|
229
240
|
return {
|
|
@@ -233,25 +244,25 @@ function o(e, r, a) {
|
|
|
233
244
|
publishedAt: u,
|
|
234
245
|
isBreaking: b,
|
|
235
246
|
skipReason: v,
|
|
236
|
-
latestSha:
|
|
247
|
+
latestSha: s,
|
|
237
248
|
hasUpdate: y,
|
|
238
249
|
action: e,
|
|
239
250
|
status: _
|
|
240
251
|
};
|
|
241
252
|
}
|
|
242
|
-
function
|
|
253
|
+
function c(e, t) {
|
|
243
254
|
let n = e.replace(/^v/u, ""), r = t.replace(/^v/u, ""), i = Math.min(n.length, r.length);
|
|
244
255
|
return i < 7 ? !1 : n.slice(0, Math.max(0, i)).toLowerCase() === r.slice(0, Math.max(0, i)).toLowerCase();
|
|
245
256
|
}
|
|
246
|
-
function
|
|
257
|
+
function l(e) {
|
|
247
258
|
if (!e) return !1;
|
|
248
259
|
let t = e.replace(/^v/u, "");
|
|
249
260
|
return /^[0-9a-f]{7,40}$/iu.test(t);
|
|
250
261
|
}
|
|
251
|
-
function
|
|
252
|
-
return t ?
|
|
262
|
+
function u(t) {
|
|
263
|
+
return t ? l(t) ? "sha" : e(t) ? "tag" : "unknown" : "unknown";
|
|
253
264
|
}
|
|
254
|
-
function
|
|
265
|
+
function d(e) {
|
|
255
266
|
return e instanceof Error && e.name === "GitHubRateLimitError";
|
|
256
267
|
}
|
|
257
|
-
export {
|
|
268
|
+
export { o as checkUpdates };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var e = class extends Error {
|
|
2
|
-
constructor(e) {
|
|
3
|
-
let
|
|
4
|
-
super(`GitHub API rate limit exceeded. Resets at ${t
|
|
2
|
+
constructor(e, t) {
|
|
3
|
+
let n = e.toLocaleTimeString();
|
|
4
|
+
super(`GitHub API rate limit exceeded. Resets at ${n}`, t), this.name = "GitHubRateLimitError";
|
|
5
5
|
}
|
|
6
6
|
};
|
|
7
7
|
export { e as GitHubRateLimitError };
|
|
@@ -9,8 +9,7 @@ async function t(t, n, r = {}) {
|
|
|
9
9
|
let a = await fetch(`${t.baseUrl}${n}`, {
|
|
10
10
|
...r,
|
|
11
11
|
headers: i
|
|
12
|
-
}), o =
|
|
13
|
-
for (let [e, t] of a.headers.entries()) o[e] = t;
|
|
12
|
+
}), o = Object.fromEntries(a.headers.entries());
|
|
14
13
|
if (e(t, o), !a.ok) {
|
|
15
14
|
let e = /* @__PURE__ */ Error(`GitHub API error: ${a.status} ${a.statusText}`);
|
|
16
15
|
if (e.status = a.status, a.status === 403) {
|
|
@@ -31,8 +31,7 @@ function r() {
|
|
|
31
31
|
if (i === "github") {
|
|
32
32
|
let e = t.match(/^(?:oauth-token|token)\s*=\s*(?<val>\S[^\n\r]*)$/u);
|
|
33
33
|
if (e?.groups?.val) return e.groups.val.trim();
|
|
34
|
-
}
|
|
35
|
-
if (i === "hub") {
|
|
34
|
+
} else if (i === "hub") {
|
|
36
35
|
let e = t.match(/^oauthtoken\s*=\s*(?<val>\S[^\n\r]*)$/u);
|
|
37
36
|
if (e?.groups?.val) return e.groups.val.trim();
|
|
38
37
|
}
|
|
@@ -7,7 +7,7 @@ async function n(n) {
|
|
|
7
7
|
let n = i.get(t) ?? [];
|
|
8
8
|
n.push(e), i.set(t, n);
|
|
9
9
|
}
|
|
10
|
-
let a = [...i
|
|
10
|
+
let a = [...i].map(async ([n, i]) => {
|
|
11
11
|
let a = await e(n, "utf8");
|
|
12
12
|
for (let e of i) {
|
|
13
13
|
let t = e.targetRef ?? e.latestSha, n = e.targetRefStyle ?? (e.latestSha ? "sha" : null);
|
|
@@ -15,11 +15,12 @@ async function n(n) {
|
|
|
15
15
|
function i(e) {
|
|
16
16
|
return e.replaceAll(/[$()*+\-./?[\\\]^{|}]/gu, String.raw`\$&`);
|
|
17
17
|
}
|
|
18
|
-
let o = i(e.action.name)
|
|
18
|
+
let o = i(e.action.name);
|
|
19
19
|
if (o.includes("\n") || o.includes("\r")) {
|
|
20
20
|
console.error(`Invalid action name: ${e.action.name}`);
|
|
21
21
|
continue;
|
|
22
22
|
}
|
|
23
|
+
let s = e.currentVersion ? i(e.currentVersion) : "";
|
|
23
24
|
if (s && (s.includes("\n") || s.includes("\r"))) {
|
|
24
25
|
console.error(`Invalid version: ${e.currentVersion}`);
|
|
25
26
|
continue;
|
|
@@ -32,7 +33,7 @@ async function n(n) {
|
|
|
32
33
|
console.error(`Invalid SHA format: ${t}`);
|
|
33
34
|
continue;
|
|
34
35
|
}
|
|
35
|
-
let l = String.raw`['"]?\buses\b['"]?\s*:\s*`, u = String.raw`(?:^[^\S\n]*(?:-[^\S\n]*)?|[{\[,][^\S\n]*)` + l, d =
|
|
36
|
+
let c = s ? String.raw`(?=(?:['"]|[ \t\]}{,#]|$))` : "", l = String.raw`['"]?\buses\b['"]?\s*:\s*`, u = String.raw`(?:^[^\S\n]*(?:-[^\S\n]*)?|[{\[,][^\S\n]*)` + l, d = RegExp(`(?<prefix>${u})(?<quote>['"]?)(?<name>${o})@${s}${c}${String.raw`\k<quote>`}${String.raw`(?<after>[ \t\]}{,]*)`}${String.raw`(?<comment>[^\S\r\n]*#[^\r\n]*)?`}`, "gm");
|
|
36
37
|
a = a.replace(d, (i, ...a) => {
|
|
37
38
|
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
39
|
if (n === "sha") p = d && !l.comment && s !== "" ? "" : `${f}# ${e.latestVersion}`;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walks up from a starting directory to find the repository root.
|
|
3
|
+
*
|
|
4
|
+
* The root is the nearest ancestor (including the start) that contains a `.git`
|
|
5
|
+
* entry — a directory in a normal clone or a file in a git worktree — or, as a
|
|
6
|
+
* fallback for non-git checkouts, a `.github` directory. Returns null when no
|
|
7
|
+
* such ancestor exists up to the filesystem root.
|
|
8
|
+
*
|
|
9
|
+
* @param startDirectory - Absolute path to start searching from.
|
|
10
|
+
* @returns The repository root directory, or null when none is found.
|
|
11
|
+
*/
|
|
12
|
+
export declare function findRepoRoot(startDirectory: string): Promise<string | null>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import "../constants.js";
|
|
2
|
+
import { dirname as e, join as t, resolve as n } from "node:path";
|
|
3
|
+
import { stat as r } from "node:fs/promises";
|
|
4
|
+
async function i(r) {
|
|
5
|
+
let o = n(r);
|
|
6
|
+
if (await a(t(o, ".git")) || await a(t(o, ".github"))) return o;
|
|
7
|
+
let s = e(o);
|
|
8
|
+
return s === o ? null : await i(s);
|
|
9
|
+
}
|
|
10
|
+
async function a(e) {
|
|
11
|
+
try {
|
|
12
|
+
return await r(e), !0;
|
|
13
|
+
} catch {
|
|
14
|
+
return !1;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export { i as findRepoRoot };
|
|
@@ -4,7 +4,7 @@ function n(n, a) {
|
|
|
4
4
|
if (!n) return e.gray("unknown");
|
|
5
5
|
let o = t.parse(n), s = a ? t.parse(r(a)) : null;
|
|
6
6
|
if (!s || !o) return n;
|
|
7
|
-
let c = t.diff(r(a), n), l = s.major === 0 ?
|
|
7
|
+
let c = t.diff(r(a), n), l = e[s.major === 0 ? "yellowBright" : "gray"], u = [
|
|
8
8
|
o.major,
|
|
9
9
|
o.minor,
|
|
10
10
|
o.patch
|
|
@@ -43,13 +43,13 @@ async function p(p, T = {}) {
|
|
|
43
43
|
for (let [e, n] of D.entries()) {
|
|
44
44
|
let r = n.action.name, o = k[e], c = o.display, l = n.action.job ?? "–";
|
|
45
45
|
if (j = Math.max(j, r.length), M = Math.max(M, i(c).length, o.versionForPadding && o.shortSha ? i(`${a(o.versionForPadding, P + 1)}${s.gray(`(${o.shortSha})`)}`).length : 0), N = Math.max(N, l.length), n.latestVersion) {
|
|
46
|
-
let r =
|
|
47
|
-
P = Math.max(P, i(
|
|
46
|
+
let r = n[n.targetRefStyle === "tag" && n.targetRef ? "targetRef" : "latestVersion"], a = t(r, k[e]?.effectiveForDiff ?? n.currentVersion);
|
|
47
|
+
P = Math.max(P, i(a).length);
|
|
48
48
|
}
|
|
49
49
|
let u = k[e]?.versionForPadding;
|
|
50
50
|
u && (P = Math.max(P, i(u).length)), n.publishedAt && (F = !0);
|
|
51
51
|
}
|
|
52
|
-
let I = Math.max(j, l), L = Math.max(M, d), R = Math.max(N, u), z = Math.min(P, f), B = z + 1 + 9, V = E && F ? 6 : 0, H =
|
|
52
|
+
let I = Math.max(j, l), L = Math.max(M, d), R = Math.max(N, u), z = Math.min(P, f), B = z + 1 + 9, V = E && F ? 6 : 0, H = O.keys().toArray().toSorted();
|
|
53
53
|
for (let [e, n] of H.entries()) {
|
|
54
54
|
let r = O.get(n);
|
|
55
55
|
if (!r) {
|
|
@@ -129,7 +129,7 @@ async function p(p, T = {}) {
|
|
|
129
129
|
let e = {
|
|
130
130
|
indicator(e, t) {
|
|
131
131
|
if (t.isGroupLabel) {
|
|
132
|
-
let e = (t.choices ?? []).filter((e) => !("role" in e)), n = e.length, r = e.filter((e) =>
|
|
132
|
+
let e = (t.choices ?? []).filter((e) => !("role" in e)), n = e.length, r = e.filter((e) => e.enabled).length === n ? "●" : "○";
|
|
133
133
|
return ` ${s.gray(r)}`;
|
|
134
134
|
}
|
|
135
135
|
return ` ${t.enabled ? "●" : "○"}`;
|
|
@@ -215,7 +215,7 @@ function S(e) {
|
|
|
215
215
|
return e.targetRef ? e.targetRef : e.latestSha;
|
|
216
216
|
}
|
|
217
217
|
function C() {
|
|
218
|
-
console.info(`\r\
|
|
218
|
+
console.info(`\r\u{1B}[K${s.yellow("Selection cancelled")}`);
|
|
219
219
|
}
|
|
220
220
|
function w(e) {
|
|
221
221
|
return !!S(e);
|
|
@@ -110,7 +110,9 @@ async function p(u = process.cwd(), p = t) {
|
|
|
110
110
|
}
|
|
111
111
|
async function r() {
|
|
112
112
|
if (n.length === 0) return;
|
|
113
|
-
let i = n
|
|
113
|
+
let i = [...n];
|
|
114
|
+
n.length = 0;
|
|
115
|
+
let o = await Promise.all(i.map(async (n) => {
|
|
114
116
|
try {
|
|
115
117
|
let r = s(n, "action.yml"), i = s(n, "action.yaml"), o = r;
|
|
116
118
|
try {
|
|
@@ -33,14 +33,17 @@ async function l(l, d) {
|
|
|
33
33
|
} catch {}
|
|
34
34
|
return null;
|
|
35
35
|
}), _ = await Promise.all(g);
|
|
36
|
-
for (let e of _) if (e)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
for (let e of _) if (e) {
|
|
37
|
+
if (e.type === "workflow") f.workflows.set(e.path, e.actions);
|
|
38
|
+
else {
|
|
39
|
+
let t = o(e.path), n = t === "." || t === "" ? e.path : t;
|
|
40
|
+
f.compositeActions.set(n, e.path);
|
|
41
|
+
}
|
|
42
|
+
f.actions.push(...e.actions);
|
|
40
43
|
}
|
|
41
44
|
return f;
|
|
42
45
|
}
|
|
43
46
|
function u(e, t) {
|
|
44
|
-
return typeof e == "object" && !!e && t
|
|
47
|
+
return typeof e == "object" && !!e && Object.hasOwn(e, t);
|
|
45
48
|
}
|
|
46
49
|
export { l as scanRecursive };
|
package/dist/package.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e = "1.
|
|
1
|
+
var e = "1.15.0";
|
|
2
2
|
export { e as version };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "actions-up",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "Interactive CLI tool to update GitHub Actions with SHA pinning or preserved refs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"github-actions",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"enquirer": "^2.4.1",
|
|
40
40
|
"nanospinner": "^1.2.2",
|
|
41
41
|
"picocolors": "^1.1.1",
|
|
42
|
-
"semver": "^7.8.
|
|
42
|
+
"semver": "^7.8.5",
|
|
43
43
|
"yaml": "^2.9.0"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
package/readme.md
CHANGED
|
@@ -187,6 +187,16 @@ skipped to avoid changing intentionally floating references. Skipped entries are
|
|
|
187
187
|
listed in the output. To include them in update checks, pass
|
|
188
188
|
`--include-branches`.
|
|
189
189
|
|
|
190
|
+
### Quiet Mode
|
|
191
|
+
|
|
192
|
+
Use `--quiet` (`-q`) to hide the skipped and blocked-update warnings (for
|
|
193
|
+
example, actions intentionally pinned to branches). Other output — results,
|
|
194
|
+
applied updates, and errors — is unchanged.
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
npx actions-up --yes --quiet
|
|
198
|
+
```
|
|
199
|
+
|
|
190
200
|
### Update Mode
|
|
191
201
|
|
|
192
202
|
By default, Actions Up allows major updates. Use `--mode` to limit updates:
|