actions-up 1.3.1 → 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.
- package/dist/cli/index.js +41 -41
- package/dist/core/api/check-updates.js +135 -179
- package/dist/core/api/create-github-client.js +28 -29
- package/dist/core/api/get-all-releases.js +20 -27
- package/dist/core/api/get-all-tags.js +5 -7
- package/dist/core/api/get-latest-release.js +16 -19
- package/dist/core/api/get-reference-type.js +6 -12
- package/dist/core/api/get-tag-info.js +47 -76
- package/dist/core/api/get-tag-sha.js +12 -22
- package/dist/core/api/internal-rate-limit-error.js +3 -4
- package/dist/core/api/make-request.js +18 -21
- package/dist/core/api/resolve-github-token-sync.js +20 -26
- package/dist/core/api/update-rate-limit-info.js +7 -7
- package/dist/core/ast/guards/has-range.js +2 -2
- package/dist/core/ast/guards/is-node.js +2 -2
- package/dist/core/ast/guards/is-pair.js +2 -2
- package/dist/core/ast/guards/is-scalar.js +2 -2
- package/dist/core/ast/guards/is-yaml-map.js +2 -2
- package/dist/core/ast/guards/is-yaml-sequence.js +2 -2
- package/dist/core/ast/scanners/scan-composite-action-ast.js +9 -11
- package/dist/core/ast/scanners/scan-workflow-ast.js +12 -14
- package/dist/core/ast/update/apply-updates.js +24 -27
- package/dist/core/ast/utils/extract-uses-from-steps.js +12 -14
- package/dist/core/ast/utils/find-map-pair.js +2 -5
- package/dist/core/ast/utils/get-line-number.js +4 -4
- package/dist/core/constants.js +1 -3
- package/dist/core/filters/parse-exclude-patterns.d.ts +17 -0
- package/dist/core/filters/parse-exclude-patterns.js +23 -0
- package/dist/core/fs/is-yaml-file.js +2 -2
- package/dist/core/fs/read-yaml-document.js +4 -5
- package/dist/core/ignore/should-ignore.d.ts +23 -0
- package/dist/core/ignore/should-ignore.js +14 -0
- package/dist/core/interactive/format-version.js +16 -30
- package/dist/core/interactive/pad-string.js +5 -6
- package/dist/core/interactive/prompt-update-selection.js +106 -163
- package/dist/core/interactive/strip-ansi.js +10 -17
- package/dist/core/parsing/parse-action-reference.js +23 -23
- package/dist/core/scan-action-file.js +3 -3
- package/dist/core/scan-github-actions.js +87 -136
- package/dist/core/scan-workflow-file.js +3 -3
- package/dist/core/schema/composite/is-composite-action-runs.js +2 -4
- package/dist/core/schema/composite/is-composite-action-structure.js +4 -4
- package/dist/core/schema/workflow/is-workflow-structure.js +4 -4
- package/dist/package.js +1 -1
- package/package.json +1 -1
- package/readme.md +55 -8
|
@@ -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(
|
|
9
|
-
if (!isYAMLSequence(
|
|
10
|
-
let
|
|
11
|
-
for (let
|
|
12
|
-
if (!isYAMLMap(
|
|
13
|
-
let
|
|
14
|
-
if (
|
|
15
|
-
let
|
|
16
|
-
if (typeof
|
|
17
|
-
let
|
|
18
|
-
|
|
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
|
|
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(
|
|
5
|
-
|
|
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(
|
|
3
|
-
if (hasRange(
|
|
4
|
-
let [
|
|
5
|
-
if (typeof
|
|
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
|
}
|
package/dist/core/constants.js
CHANGED
|
@@ -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 };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse CLI --exclude patterns into regular expressions.
|
|
3
|
+
*
|
|
4
|
+
* Supports two forms:
|
|
5
|
+
*
|
|
6
|
+
* - Raw regex literal with optional flags: `/pattern/i`
|
|
7
|
+
* - Plain pattern string compiled as case-insensitive regex: `pattern`.
|
|
8
|
+
*
|
|
9
|
+
* Commas should be split at the CLI level; this function assumes patterns are
|
|
10
|
+
* already individual entries.
|
|
11
|
+
*
|
|
12
|
+
* Invalid patterns are skipped with a console warning.
|
|
13
|
+
*
|
|
14
|
+
* @param patterns - List of pattern strings provided via CLI.
|
|
15
|
+
* @returns Array of RegExp objects.
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseExcludePatterns(patterns: string[]): RegExp[];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
function parseExcludePatterns(e) {
|
|
2
|
+
let t = [];
|
|
3
|
+
for (let n of e) {
|
|
4
|
+
let e = n.trim();
|
|
5
|
+
if (!e) continue;
|
|
6
|
+
let r;
|
|
7
|
+
if (e.startsWith("/") && e.lastIndexOf("/") > 0) {
|
|
8
|
+
let t = e.lastIndexOf("/"), i = e.slice(1, t), a = e.slice(t + 1);
|
|
9
|
+
try {
|
|
10
|
+
r = new RegExp(i, a || "i");
|
|
11
|
+
} catch (e) {
|
|
12
|
+
console.warn(`Invalid regex exclude: ${n}`, e), r = null;
|
|
13
|
+
}
|
|
14
|
+
} else try {
|
|
15
|
+
r = new RegExp(e, "i");
|
|
16
|
+
} catch (e) {
|
|
17
|
+
console.warn(`Invalid regex exclude: ${n}`, e), r = null;
|
|
18
|
+
}
|
|
19
|
+
r && t.push(r);
|
|
20
|
+
}
|
|
21
|
+
return t;
|
|
22
|
+
}
|
|
23
|
+
export { parseExcludePatterns };
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { parseDocument } from "yaml";
|
|
3
|
-
async function readYamlDocument(
|
|
4
|
-
let
|
|
5
|
-
let document = parseDocument(content);
|
|
3
|
+
async function readYamlDocument(n) {
|
|
4
|
+
let r = await readFile(n, "utf8");
|
|
6
5
|
return {
|
|
7
|
-
document,
|
|
8
|
-
content
|
|
6
|
+
document: parseDocument(r),
|
|
7
|
+
content: r
|
|
9
8
|
};
|
|
10
9
|
}
|
|
11
10
|
export { readYamlDocument };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determine whether a given file/line should be ignored based on inline comment
|
|
3
|
+
* directives present in the file content.
|
|
4
|
+
*
|
|
5
|
+
* Supported directives (lowercase, exact match):
|
|
6
|
+
*
|
|
7
|
+
* - `actions-up-ignore-file`
|
|
8
|
+
* - `actions-up-ignore-start` … `actions-up-ignore-end`
|
|
9
|
+
* - `actions-up-ignore-next-line`
|
|
10
|
+
* - `actions-up-ignore` (inline on the same line).
|
|
11
|
+
*
|
|
12
|
+
* Notes:
|
|
13
|
+
*
|
|
14
|
+
* - "next-line" applies strictly to the immediate next physical line.
|
|
15
|
+
* - Block directives behave as a simple toggle; nested blocks are not supported.
|
|
16
|
+
* - Optional text after a colon is ignored.
|
|
17
|
+
* - If line is missing or <= 0, only file-level ignore applies.
|
|
18
|
+
*
|
|
19
|
+
* @param filePath - Path to the YAML file being processed.
|
|
20
|
+
* @param line - One-based line number to check.
|
|
21
|
+
* @returns Promise that resolves to true when the target should be ignored.
|
|
22
|
+
*/
|
|
23
|
+
export declare function shouldIgnore(filePath: undefined | string, line: undefined | number): Promise<boolean>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
async function shouldIgnore(t, n) {
|
|
3
|
+
if (!t) return !1;
|
|
4
|
+
let r = (await readFile(t, "utf8")).split("\n");
|
|
5
|
+
for (let e of r) if (e.includes("actions-up-ignore-file")) return !0;
|
|
6
|
+
if (!n || n <= 0) return !1;
|
|
7
|
+
let i = /* @__PURE__ */ new Set(), a = !1;
|
|
8
|
+
for (let [e, t] of r.entries()) {
|
|
9
|
+
let n = t, r = e + 1;
|
|
10
|
+
n.includes("actions-up-ignore-start") && (a = !0), a && i.add(r), n.includes("actions-up-ignore-end") && (i.add(r), a = !1), n.includes("actions-up-ignore-next-line") && i.add(r + 1), n.includes("actions-up-ignore") && !n.includes("actions-up-ignore-next-line") && !n.includes("actions-up-ignore-start") && !n.includes("actions-up-ignore-end") && !n.includes("actions-up-ignore-file") && i.add(r);
|
|
11
|
+
}
|
|
12
|
+
return i.has(n);
|
|
13
|
+
}
|
|
14
|
+
export { shouldIgnore };
|
|
@@ -1,36 +1,22 @@
|
|
|
1
1
|
import pc from "picocolors";
|
|
2
2
|
import semver from "semver";
|
|
3
|
-
function formatVersion(
|
|
4
|
-
if (!
|
|
5
|
-
let
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
latest.minor,
|
|
14
|
-
latest.patch
|
|
15
|
-
];
|
|
16
|
-
let colors = parts.map((_, i) => {
|
|
17
|
-
if (change === "major") return pc.redBright;
|
|
18
|
-
if (change === "minor" && i >= 1) return changeColor;
|
|
19
|
-
if (change === "patch" && i === 2) return changeColor;
|
|
20
|
-
return identity;
|
|
21
|
-
});
|
|
22
|
-
let result = colors[0](String(parts[0]));
|
|
23
|
-
if (parts[1] !== void 0) result += colors[0](".") + colors[1](String(parts[1]));
|
|
24
|
-
if (parts[2] !== void 0) result += colors[1](".") + colors[2](String(parts[2]));
|
|
25
|
-
return result;
|
|
3
|
+
function formatVersion(i, a) {
|
|
4
|
+
if (!i) return pc.gray("unknown");
|
|
5
|
+
let o = semver.parse(i), s = a ? semver.parse(normalizeVersion(a)) : null;
|
|
6
|
+
if (!s || !o) return i;
|
|
7
|
+
let c = semver.diff(normalizeVersion(a), i), l = s.major === 0 ? pc.yellowBright : pc.gray, u = [
|
|
8
|
+
o.major,
|
|
9
|
+
o.minor,
|
|
10
|
+
o.patch
|
|
11
|
+
], d = u.map((r, i) => c === "major" ? pc.redBright : c === "minor" && i >= 1 || c === "patch" && i === 2 ? l : identity), f = d[0](String(u[0]));
|
|
12
|
+
return u[1] !== void 0 && (f += d[0](".") + d[1](String(u[1]))), u[2] !== void 0 && (f += d[1](".") + d[2](String(u[2]))), f;
|
|
26
13
|
}
|
|
27
|
-
function normalizeVersion(
|
|
28
|
-
let
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return parts.slice(0, 3).join(".");
|
|
14
|
+
function normalizeVersion(e) {
|
|
15
|
+
let r = e.replace(/^v/u, "").split(".");
|
|
16
|
+
for (; r.length < 3;) r.push("0");
|
|
17
|
+
return r.slice(0, 3).join(".");
|
|
32
18
|
}
|
|
33
|
-
function identity(
|
|
34
|
-
return
|
|
19
|
+
function identity(e) {
|
|
20
|
+
return e;
|
|
35
21
|
}
|
|
36
22
|
export { formatVersion };
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { stripAnsi } from "./strip-ansi.js";
|
|
2
|
-
function padString(
|
|
3
|
-
let
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return string + padding;
|
|
2
|
+
function padString(t, n) {
|
|
3
|
+
let r = stripAnsi(t), i = n - r.length;
|
|
4
|
+
if (i <= 0) return t;
|
|
5
|
+
let a = " ".repeat(i);
|
|
6
|
+
return t + a;
|
|
8
7
|
}
|
|
9
8
|
export { padString };
|
|
@@ -7,154 +7,115 @@ import pc from "picocolors";
|
|
|
7
7
|
import { readFile } from "node:fs/promises";
|
|
8
8
|
import enquirer from "enquirer";
|
|
9
9
|
import path from "node:path";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (
|
|
14
|
-
let
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
async function promptUpdateSelection(a) {
|
|
11
|
+
if (a.length === 0) return null;
|
|
12
|
+
let s = a.filter((e) => e.hasUpdate);
|
|
13
|
+
if (s.length === 0) return console.info(pc.green("✓ All actions are up to date!")), null;
|
|
14
|
+
let u = /* @__PURE__ */ new Map();
|
|
15
|
+
for (let [e, i] of s.entries()) {
|
|
16
|
+
let a = i.action.file ?? "unknown file", o = path.relative(path.join(process.cwd(), GITHUB_DIRECTORY), a);
|
|
17
|
+
o === "" && (o = a);
|
|
18
|
+
let s = u.get(o) ?? [];
|
|
19
|
+
s.push({
|
|
20
|
+
update: i,
|
|
21
|
+
index: e
|
|
22
|
+
}), u.set(o, s);
|
|
18
23
|
}
|
|
19
|
-
let
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
let group = groups.get(file) ?? [];
|
|
25
|
-
group.push({
|
|
26
|
-
update,
|
|
27
|
-
index
|
|
28
|
-
});
|
|
29
|
-
groups.set(file, group);
|
|
30
|
-
}
|
|
31
|
-
let currentComputedByIndex = await Promise.all(outdated.map(async (update) => {
|
|
32
|
-
let display = formatVersionOrSha(update.currentVersion);
|
|
33
|
-
let effectiveForDiff = update.currentVersion ?? void 0;
|
|
34
|
-
if (!update.currentVersion || !isSha(update.currentVersion)) return {
|
|
35
|
-
effectiveForDiff,
|
|
36
|
-
display
|
|
24
|
+
let p = await Promise.all(s.map(async (e) => {
|
|
25
|
+
let r = formatVersionOrSha(e.currentVersion), i = e.currentVersion ?? void 0;
|
|
26
|
+
if (!e.currentVersion || !isSha(e.currentVersion)) return {
|
|
27
|
+
effectiveForDiff: i,
|
|
28
|
+
display: r
|
|
37
29
|
};
|
|
38
|
-
let
|
|
39
|
-
if (
|
|
40
|
-
let
|
|
41
|
-
|
|
42
|
-
display = `${version} ${pc.gray(`(${shortSha})`)}`;
|
|
43
|
-
effectiveForDiff = versionFromComment;
|
|
30
|
+
let a = await tryReadInlineVersionComment(e.action.file, e.action.line);
|
|
31
|
+
if (a) {
|
|
32
|
+
let s = e.currentVersion.slice(0, 7);
|
|
33
|
+
r = `${formatVersionOrSha(a)} ${pc.gray(`(${s})`)}`, i = a;
|
|
44
34
|
}
|
|
45
35
|
return {
|
|
46
|
-
effectiveForDiff,
|
|
47
|
-
display
|
|
36
|
+
effectiveForDiff: i,
|
|
37
|
+
display: r
|
|
48
38
|
};
|
|
49
|
-
}));
|
|
50
|
-
let
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
for (let [index, update] of outdated.entries()) {
|
|
54
|
-
let actionNameRaw = update.action.name;
|
|
55
|
-
let currentRaw = currentComputedByIndex[index].display;
|
|
56
|
-
maxActionLength = Math.max(maxActionLength, actionNameRaw.length);
|
|
57
|
-
maxCurrentLength = Math.max(maxCurrentLength, stripAnsi(currentRaw).length);
|
|
39
|
+
})), m = [], h = stripAnsi("Action").length, g = stripAnsi("Current").length;
|
|
40
|
+
for (let [e, r] of s.entries()) {
|
|
41
|
+
let a = r.action.name, o = p[e].display;
|
|
42
|
+
h = Math.max(h, a.length), g = Math.max(g, stripAnsi(o).length);
|
|
58
43
|
}
|
|
59
|
-
let
|
|
60
|
-
let
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (!fileGroup) {
|
|
65
|
-
console.warn(`Unexpected missing group for file: ${file}`);
|
|
44
|
+
let _ = Math.max(h, 56), v = Math.max(g, 16), y = [...u.keys()].toSorted();
|
|
45
|
+
for (let [r, i] of y.entries()) {
|
|
46
|
+
let a = u.get(i);
|
|
47
|
+
if (!a) {
|
|
48
|
+
console.warn(`Unexpected missing group for file: ${i}`);
|
|
66
49
|
continue;
|
|
67
50
|
}
|
|
68
|
-
let
|
|
69
|
-
|
|
70
|
-
tableRows.push({
|
|
51
|
+
let s = [], c = a;
|
|
52
|
+
s.push({
|
|
71
53
|
current: "Current",
|
|
72
54
|
action: "Action",
|
|
73
55
|
target: "Target",
|
|
74
56
|
arrow: "❯"
|
|
75
57
|
});
|
|
76
|
-
for (let { update, index } of
|
|
77
|
-
let
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
let actionName = update.action.name;
|
|
82
|
-
if (update.latestSha) {
|
|
83
|
-
let shortSha = update.latestSha.slice(0, 7);
|
|
84
|
-
latest = `${latest} ${pc.gray(`(${shortSha})`)}`;
|
|
58
|
+
for (let { update: r, index: i } of c) {
|
|
59
|
+
let a = !!r.latestSha, c = p[i].display, l = p[i]?.effectiveForDiff ?? r.currentVersion, u = formatVersion(r.latestVersion, l), d = r.action.name;
|
|
60
|
+
if (r.latestSha) {
|
|
61
|
+
let e = r.latestSha.slice(0, 7);
|
|
62
|
+
u = `${u} ${pc.gray(`(${e})`)}`;
|
|
85
63
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
actionName = pc.gray(actionName);
|
|
90
|
-
}
|
|
91
|
-
tableRows.push({
|
|
92
|
-
action: actionName,
|
|
93
|
-
target: latest,
|
|
64
|
+
a || (u = pc.gray(u), c = pc.gray(c), d = pc.gray(d)), s.push({
|
|
65
|
+
action: d,
|
|
66
|
+
target: u,
|
|
94
67
|
arrow: "❯",
|
|
95
|
-
current
|
|
68
|
+
current: c
|
|
96
69
|
});
|
|
97
70
|
}
|
|
98
|
-
let
|
|
99
|
-
let
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
let formattedRow = formatTableRow(row, maxActionWidth, maxCurrentWidth);
|
|
104
|
-
if (isHeader) groupChildren.push({
|
|
105
|
-
message: pc.gray(` ○ ${formattedRow}`),
|
|
71
|
+
let l = Math.max(_, 56), d = Math.max(v, 16), f = [];
|
|
72
|
+
for (let [e, r] of s.entries()) {
|
|
73
|
+
let i = e === 0, a = formatTableRow(r, l, d);
|
|
74
|
+
if (i) f.push({
|
|
75
|
+
message: pc.gray(` ○ ${a}`),
|
|
106
76
|
role: "separator",
|
|
107
77
|
indent: "",
|
|
108
78
|
name: ""
|
|
109
79
|
});
|
|
110
80
|
else {
|
|
111
|
-
let
|
|
112
|
-
if (!
|
|
113
|
-
let { update, index } =
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
name: String(index),
|
|
120
|
-
disabled: !hasSha,
|
|
81
|
+
let r = c[e - 1];
|
|
82
|
+
if (!r) continue;
|
|
83
|
+
let { update: i, index: o } = r, s = !!i.latestSha, l = s && !i.isBreaking;
|
|
84
|
+
f.push({
|
|
85
|
+
message: a,
|
|
86
|
+
value: String(o),
|
|
87
|
+
name: String(o),
|
|
88
|
+
disabled: !s,
|
|
121
89
|
indent: "",
|
|
122
|
-
enabled
|
|
90
|
+
enabled: l
|
|
123
91
|
});
|
|
124
92
|
}
|
|
125
93
|
}
|
|
126
|
-
|
|
127
|
-
message: pc.gray(
|
|
128
|
-
value: `label|${
|
|
129
|
-
choices:
|
|
130
|
-
name: `label|${
|
|
131
|
-
isGroupLabel:
|
|
132
|
-
enabled:
|
|
133
|
-
})
|
|
134
|
-
if (fileIndex < sortedFiles.length - 1) choices.push({
|
|
94
|
+
m.push({
|
|
95
|
+
message: pc.gray(i),
|
|
96
|
+
value: `label|${i}`,
|
|
97
|
+
choices: f,
|
|
98
|
+
name: `label|${i}`,
|
|
99
|
+
isGroupLabel: !0,
|
|
100
|
+
enabled: !1
|
|
101
|
+
}), r < y.length - 1 && m.push({
|
|
135
102
|
role: "separator",
|
|
136
103
|
message: " ",
|
|
137
104
|
name: ""
|
|
138
105
|
});
|
|
139
106
|
}
|
|
140
107
|
try {
|
|
141
|
-
let
|
|
142
|
-
indicator(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
let rows = allChildren.filter((child) => !("role" in child));
|
|
147
|
-
let total = rows.length;
|
|
148
|
-
let selectedCount = rows.filter((row) => Boolean(row.enabled)).length;
|
|
149
|
-
let mark = selectedCount === total ? "●" : "○";
|
|
150
|
-
return ` ${pc.gray(mark)}`;
|
|
108
|
+
let e = {
|
|
109
|
+
indicator(e, r) {
|
|
110
|
+
if (r.isGroupLabel) {
|
|
111
|
+
let e = (r.choices ?? []).filter((e) => !("role" in e)), i = e.length, a = e.filter((e) => !!e.enabled).length === i ? "●" : "○";
|
|
112
|
+
return ` ${pc.gray(a)}`;
|
|
151
113
|
}
|
|
152
|
-
return ` ${
|
|
114
|
+
return ` ${r.enabled ? "●" : "○"}`;
|
|
153
115
|
},
|
|
154
116
|
message: `Choose which actions to update (Press ${pc.cyan("<space>")} to select, ${pc.cyan("<a>")} to toggle all, ${pc.cyan("<i>")} to invert selection)`,
|
|
155
117
|
cancel() {
|
|
156
|
-
console.info(pc.yellow("\nSelection cancelled"));
|
|
157
|
-
return null;
|
|
118
|
+
return console.info(pc.yellow("\nSelection cancelled")), null;
|
|
158
119
|
},
|
|
159
120
|
styles: {
|
|
160
121
|
success: pc.reset,
|
|
@@ -171,67 +132,49 @@ async function promptUpdateSelection(updates) {
|
|
|
171
132
|
type: "multiselect",
|
|
172
133
|
name: "selected",
|
|
173
134
|
pointer: "❯",
|
|
174
|
-
choices
|
|
175
|
-
};
|
|
176
|
-
let
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
let fileKey = valueString.slice(6);
|
|
181
|
-
let groupItems = groups.get(fileKey) ?? [];
|
|
182
|
-
for (let { update: upd, index: index$1 } of groupItems) if (upd.latestSha) selectedIndexes.add(index$1);
|
|
135
|
+
choices: m
|
|
136
|
+
}, { selected: r } = await enquirer.prompt(e), i = /* @__PURE__ */ new Set();
|
|
137
|
+
for (let e of r) {
|
|
138
|
+
if (e.startsWith("label|")) {
|
|
139
|
+
let r = e.slice(6), a = u.get(r) ?? [];
|
|
140
|
+
for (let { update: e, index: r } of a) e.latestSha && i.add(r);
|
|
183
141
|
continue;
|
|
184
142
|
}
|
|
185
|
-
let
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
let result = [];
|
|
189
|
-
for (let [index, outdatedUpdate] of outdated.entries()) if (selectedIndexes.has(index) && outdatedUpdate.latestSha) result.push(outdatedUpdate);
|
|
190
|
-
if (result.length === 0) {
|
|
191
|
-
console.info(pc.yellow("\nNo actions selected"));
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
194
|
-
return result;
|
|
195
|
-
} catch (error) {
|
|
196
|
-
if (error instanceof Error && (error.message.includes("cancelled") || error.message.includes("ESC") || error.name === "ExitPromptError")) {
|
|
197
|
-
console.info(pc.yellow("\nSelection cancelled"));
|
|
198
|
-
return null;
|
|
143
|
+
let r = Number.parseInt(e, 10);
|
|
144
|
+
Number.isFinite(r) && i.add(r);
|
|
199
145
|
}
|
|
200
|
-
|
|
201
|
-
|
|
146
|
+
let a = [];
|
|
147
|
+
for (let [e, r] of s.entries()) i.has(e) && r.latestSha && a.push(r);
|
|
148
|
+
return a.length === 0 ? (console.info(pc.yellow("\nNo actions selected")), null) : a;
|
|
149
|
+
} catch (e) {
|
|
150
|
+
if (e instanceof Error && (e.message.includes("cancelled") || e.message.includes("ESC") || e.name === "ExitPromptError")) return console.info(pc.yellow("\nSelection cancelled")), null;
|
|
151
|
+
throw console.error(pc.red("Unexpected error during selection:"), e), e;
|
|
202
152
|
}
|
|
203
153
|
}
|
|
204
|
-
async function tryReadInlineVersionComment(
|
|
154
|
+
async function tryReadInlineVersionComment(e, r) {
|
|
205
155
|
try {
|
|
206
|
-
if (!
|
|
207
|
-
let
|
|
208
|
-
|
|
209
|
-
let
|
|
210
|
-
if (
|
|
211
|
-
let line = lines[index];
|
|
212
|
-
let match = line.match(/#\s*(?<version>[Vv]?\d+(?:\.\d+){0,2}(?:[+-][\w\-.]+)?)/u);
|
|
213
|
-
if (match?.groups?.["version"]) return match.groups["version"];
|
|
156
|
+
if (!e || !r || r <= 0) return null;
|
|
157
|
+
let i = (await readFile(e, "utf8")).split("\n"), a = r - 1;
|
|
158
|
+
if (a < 0 || a >= i.length) return null;
|
|
159
|
+
let o = i[a].match(/#\s*(?<version>[Vv]?\d+(?:\.\d+){0,2}(?:[+-][\w\-.]+)?)/u);
|
|
160
|
+
if (o?.groups?.version) return o.groups.version;
|
|
214
161
|
} catch {}
|
|
215
162
|
return null;
|
|
216
163
|
}
|
|
217
|
-
function formatTableRow(
|
|
218
|
-
|
|
219
|
-
padString(
|
|
220
|
-
padString(
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
];
|
|
224
|
-
let line = parts.join(" ");
|
|
225
|
-
return line.replace(/\s+$/u, "");
|
|
164
|
+
function formatTableRow(e, r, i) {
|
|
165
|
+
return [
|
|
166
|
+
padString(e.action, r),
|
|
167
|
+
padString(e.current, i),
|
|
168
|
+
e.arrow,
|
|
169
|
+
e.target
|
|
170
|
+
].join(" ").replace(/\s+$/u, "");
|
|
226
171
|
}
|
|
227
|
-
function isSha(
|
|
228
|
-
if (!
|
|
229
|
-
let
|
|
230
|
-
return /^[0-9a-f]{7,40}$/iu.test(
|
|
172
|
+
function isSha(e) {
|
|
173
|
+
if (!e) return !1;
|
|
174
|
+
let r = e.replace(/^v/u, "");
|
|
175
|
+
return /^[0-9a-f]{7,40}$/iu.test(r);
|
|
231
176
|
}
|
|
232
|
-
function formatVersionOrSha(
|
|
233
|
-
|
|
234
|
-
if (isSha(version)) return version.slice(0, 7);
|
|
235
|
-
return version.replace(/^v/u, "");
|
|
177
|
+
function formatVersionOrSha(e) {
|
|
178
|
+
return e ? isSha(e) ? e.slice(0, 7) : e.replace(/^v/u, "") : pc.gray("unknown");
|
|
236
179
|
}
|
|
237
180
|
export { promptUpdateSelection };
|
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
function stripAnsi(
|
|
2
|
-
let
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (char === "m") break;
|
|
10
|
-
if (!/[\d;]/u.test(char)) {
|
|
11
|
-
result += `${String.fromCharCode(27)}[${string.slice(i - 1, i)}`;
|
|
12
|
-
break;
|
|
13
|
-
}
|
|
1
|
+
function stripAnsi(e) {
|
|
2
|
+
let t = "", n = 0;
|
|
3
|
+
for (; n < e.length;) if (e.charCodeAt(n) === 27 && n + 1 < e.length && e[n + 1] === "[") for (n += 2; n < e.length;) {
|
|
4
|
+
let r = e[n];
|
|
5
|
+
if (n++, r === "m") break;
|
|
6
|
+
if (!/[\d;]/u.test(r)) {
|
|
7
|
+
t += `[${e.slice(n - 1, n)}`;
|
|
8
|
+
break;
|
|
14
9
|
}
|
|
15
|
-
} else {
|
|
16
|
-
result += string[i];
|
|
17
|
-
i++;
|
|
18
10
|
}
|
|
19
|
-
|
|
11
|
+
else t += e[n], n++;
|
|
12
|
+
return t;
|
|
20
13
|
}
|
|
21
14
|
export { stripAnsi };
|