@rainy-updates/cli 0.5.7 → 0.6.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.
- package/CHANGELOG.md +134 -0
- package/README.md +90 -31
- package/dist/bin/cli.js +11 -126
- package/dist/bin/dispatch.js +35 -32
- package/dist/bin/help.js +79 -2
- package/dist/bin/main.d.ts +1 -0
- package/dist/bin/main.js +126 -0
- package/dist/cache/cache.js +13 -11
- package/dist/commands/audit/parser.js +38 -2
- package/dist/commands/audit/runner.js +41 -61
- package/dist/commands/audit/targets.js +13 -13
- package/dist/commands/bisect/oracle.js +31 -11
- package/dist/commands/bisect/parser.js +3 -3
- package/dist/commands/bisect/runner.js +16 -8
- package/dist/commands/changelog/fetcher.js +11 -5
- package/dist/commands/dashboard/parser.js +144 -1
- package/dist/commands/dashboard/runner.d.ts +2 -2
- package/dist/commands/dashboard/runner.js +67 -37
- package/dist/commands/doctor/parser.js +53 -4
- package/dist/commands/doctor/runner.js +2 -2
- package/dist/commands/ga/parser.js +43 -4
- package/dist/commands/ga/runner.js +22 -13
- package/dist/commands/health/parser.js +38 -2
- package/dist/commands/health/runner.js +5 -1
- package/dist/commands/hook/parser.d.ts +2 -0
- package/dist/commands/hook/parser.js +40 -0
- package/dist/commands/hook/runner.d.ts +2 -0
- package/dist/commands/hook/runner.js +174 -0
- package/dist/commands/licenses/parser.js +39 -0
- package/dist/commands/licenses/runner.js +9 -5
- package/dist/commands/resolve/graph/builder.js +5 -1
- package/dist/commands/resolve/parser.js +39 -0
- package/dist/commands/resolve/runner.js +14 -4
- package/dist/commands/review/parser.js +101 -4
- package/dist/commands/review/runner.js +31 -5
- package/dist/commands/snapshot/parser.js +39 -0
- package/dist/commands/snapshot/runner.js +21 -18
- package/dist/commands/snapshot/store.d.ts +0 -12
- package/dist/commands/snapshot/store.js +26 -38
- package/dist/commands/unused/parser.js +39 -0
- package/dist/commands/unused/runner.js +10 -8
- package/dist/commands/unused/scanner.d.ts +2 -1
- package/dist/commands/unused/scanner.js +65 -52
- package/dist/config/loader.d.ts +2 -2
- package/dist/config/loader.js +2 -5
- package/dist/config/policy.js +20 -11
- package/dist/core/analysis/run-silenced.js +0 -1
- package/dist/core/artifacts.js +6 -5
- package/dist/core/baseline.js +3 -5
- package/dist/core/check.js +7 -3
- package/dist/core/ci.js +52 -1
- package/dist/core/decision-plan.d.ts +14 -0
- package/dist/core/decision-plan.js +107 -0
- package/dist/core/doctor/result.js +8 -5
- package/dist/core/fix-pr-batch.js +38 -28
- package/dist/core/fix-pr.js +27 -24
- package/dist/core/init-ci.js +34 -28
- package/dist/core/options.d.ts +4 -1
- package/dist/core/options.js +152 -4
- package/dist/core/review-model.js +3 -0
- package/dist/core/summary.js +6 -0
- package/dist/core/upgrade.js +64 -2
- package/dist/core/verification.d.ts +2 -0
- package/dist/core/verification.js +108 -0
- package/dist/core/warm-cache.js +7 -3
- package/dist/generated/version.d.ts +1 -0
- package/dist/generated/version.js +2 -0
- package/dist/git/scope.d.ts +19 -0
- package/dist/git/scope.js +167 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/output/format.js +15 -0
- package/dist/output/github.js +6 -0
- package/dist/output/sarif.js +12 -18
- package/dist/parsers/package-json.js +2 -4
- package/dist/pm/detect.d.ts +40 -1
- package/dist/pm/detect.js +152 -9
- package/dist/pm/install.d.ts +3 -1
- package/dist/pm/install.js +18 -17
- package/dist/registry/npm.js +34 -76
- package/dist/rup +0 -0
- package/dist/types/index.d.ts +134 -5
- package/dist/ui/tui.d.ts +4 -1
- package/dist/ui/tui.js +156 -67
- package/dist/utils/io.js +5 -6
- package/dist/utils/lockfile.js +24 -19
- package/dist/utils/runtime-paths.d.ts +4 -0
- package/dist/utils/runtime-paths.js +35 -0
- package/dist/utils/runtime.d.ts +7 -0
- package/dist/utils/runtime.js +32 -0
- package/dist/workspace/discover.d.ts +7 -1
- package/dist/workspace/discover.js +67 -54
- package/package.json +24 -19
- package/dist/ui/dashboard/DashboardTUI.d.ts +0 -6
- package/dist/ui/dashboard/DashboardTUI.js +0 -34
- package/dist/ui/dashboard/components/DetailPanel.d.ts +0 -4
- package/dist/ui/dashboard/components/DetailPanel.js +0 -30
- package/dist/ui/dashboard/components/Footer.d.ts +0 -4
- package/dist/ui/dashboard/components/Footer.js +0 -9
- package/dist/ui/dashboard/components/Header.d.ts +0 -4
- package/dist/ui/dashboard/components/Header.js +0 -12
- package/dist/ui/dashboard/components/Sidebar.d.ts +0 -4
- package/dist/ui/dashboard/components/Sidebar.js +0 -23
- package/dist/ui/dashboard/store.d.ts +0 -34
- package/dist/ui/dashboard/store.js +0 -148
package/dist/bin/dispatch.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import process from "node:process";
|
|
2
1
|
import { check } from "../core/check.js";
|
|
3
2
|
import { upgrade } from "../core/upgrade.js";
|
|
4
3
|
import { warmCache } from "../core/warm-cache.js";
|
|
5
4
|
import { runCi } from "../core/ci.js";
|
|
6
5
|
import { initCiWorkflow } from "../core/init-ci.js";
|
|
7
6
|
import { diffBaseline, saveBaseline } from "../core/baseline.js";
|
|
7
|
+
import { setRuntimeExitCode, writeStdout, } from "../utils/runtime.js";
|
|
8
8
|
export async function handleDirectCommand(parsed) {
|
|
9
9
|
if (parsed.command === "init-ci") {
|
|
10
10
|
const workflow = await initCiWorkflow(parsed.options.cwd, parsed.options.force, {
|
|
11
11
|
mode: parsed.options.mode,
|
|
12
12
|
schedule: parsed.options.schedule,
|
|
13
13
|
});
|
|
14
|
-
|
|
14
|
+
writeStdout(workflow.created
|
|
15
15
|
? `Created CI workflow at ${workflow.path}\n`
|
|
16
16
|
: `CI workflow already exists at ${workflow.path}. Use --force to overwrite.\n`);
|
|
17
17
|
return true;
|
|
@@ -19,110 +19,113 @@ export async function handleDirectCommand(parsed) {
|
|
|
19
19
|
if (parsed.command === "baseline") {
|
|
20
20
|
if (parsed.options.action === "save") {
|
|
21
21
|
const saved = await saveBaseline(parsed.options);
|
|
22
|
-
|
|
22
|
+
writeStdout(`Saved baseline at ${saved.filePath} (${saved.entries} entries)\n`);
|
|
23
23
|
return true;
|
|
24
24
|
}
|
|
25
25
|
const diff = await diffBaseline(parsed.options);
|
|
26
26
|
const changes = diff.added.length + diff.removed.length + diff.changed.length;
|
|
27
27
|
if (changes === 0) {
|
|
28
|
-
|
|
28
|
+
writeStdout(`No baseline drift detected (${diff.filePath}).\n`);
|
|
29
29
|
return true;
|
|
30
30
|
}
|
|
31
|
-
|
|
31
|
+
writeStdout(`Baseline drift detected (${diff.filePath}).\n`);
|
|
32
32
|
if (diff.added.length > 0)
|
|
33
|
-
|
|
33
|
+
writeStdout(`Added: ${diff.added.length}\n`);
|
|
34
34
|
if (diff.removed.length > 0)
|
|
35
|
-
|
|
35
|
+
writeStdout(`Removed: ${diff.removed.length}\n`);
|
|
36
36
|
if (diff.changed.length > 0)
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
writeStdout(`Changed: ${diff.changed.length}\n`);
|
|
38
|
+
setRuntimeExitCode(1);
|
|
39
39
|
return true;
|
|
40
40
|
}
|
|
41
41
|
if (parsed.command === "bisect") {
|
|
42
42
|
const { runBisect } = await import("../commands/bisect/runner.js");
|
|
43
43
|
const result = await runBisect(parsed.options);
|
|
44
|
-
|
|
44
|
+
setRuntimeExitCode(result.breakingVersion ? 1 : 0);
|
|
45
45
|
return true;
|
|
46
46
|
}
|
|
47
47
|
if (parsed.command === "audit") {
|
|
48
48
|
const { runAudit } = await import("../commands/audit/runner.js");
|
|
49
49
|
const result = await runAudit(parsed.options);
|
|
50
|
-
|
|
50
|
+
setRuntimeExitCode(result.advisories.length > 0 ? 1 : 0);
|
|
51
51
|
return true;
|
|
52
52
|
}
|
|
53
53
|
if (parsed.command === "health") {
|
|
54
54
|
const { runHealth } = await import("../commands/health/runner.js");
|
|
55
55
|
const result = await runHealth(parsed.options);
|
|
56
|
-
|
|
56
|
+
setRuntimeExitCode(result.totalFlagged > 0 ? 1 : 0);
|
|
57
57
|
return true;
|
|
58
58
|
}
|
|
59
59
|
if (parsed.command === "unused") {
|
|
60
60
|
const { runUnused } = await import("../commands/unused/runner.js");
|
|
61
61
|
const result = await runUnused(parsed.options);
|
|
62
|
-
|
|
62
|
+
setRuntimeExitCode(result.totalUnused > 0 || result.totalMissing > 0 ? 1 : 0);
|
|
63
63
|
return true;
|
|
64
64
|
}
|
|
65
65
|
if (parsed.command === "resolve") {
|
|
66
66
|
const { runResolve } = await import("../commands/resolve/runner.js");
|
|
67
67
|
const result = await runResolve(parsed.options);
|
|
68
|
-
|
|
68
|
+
setRuntimeExitCode(result.errorConflicts > 0 ? 1 : 0);
|
|
69
69
|
return true;
|
|
70
70
|
}
|
|
71
71
|
if (parsed.command === "licenses") {
|
|
72
72
|
const { runLicenses } = await import("../commands/licenses/runner.js");
|
|
73
73
|
const result = await runLicenses(parsed.options);
|
|
74
|
-
|
|
74
|
+
setRuntimeExitCode(result.totalViolations > 0 ? 1 : 0);
|
|
75
75
|
return true;
|
|
76
76
|
}
|
|
77
77
|
if (parsed.command === "snapshot") {
|
|
78
78
|
const { runSnapshot } = await import("../commands/snapshot/runner.js");
|
|
79
79
|
const result = await runSnapshot(parsed.options);
|
|
80
|
-
|
|
80
|
+
setRuntimeExitCode(result.errors.length > 0 ? 1 : 0);
|
|
81
81
|
return true;
|
|
82
82
|
}
|
|
83
83
|
if (parsed.command === "review") {
|
|
84
84
|
const { runReview } = await import("../commands/review/runner.js");
|
|
85
85
|
const result = await runReview(parsed.options);
|
|
86
|
-
|
|
87
|
-
result.summary.verdict === "
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
: 0;
|
|
86
|
+
setRuntimeExitCode(result.summary.verdict === "blocked" ||
|
|
87
|
+
result.summary.verdict === "actionable" ||
|
|
88
|
+
result.summary.verdict === "review"
|
|
89
|
+
? 1
|
|
90
|
+
: 0);
|
|
92
91
|
return true;
|
|
93
92
|
}
|
|
94
93
|
if (parsed.command === "doctor") {
|
|
95
94
|
const { runDoctor } = await import("../commands/doctor/runner.js");
|
|
96
95
|
const result = await runDoctor(parsed.options);
|
|
97
|
-
|
|
96
|
+
setRuntimeExitCode(result.verdict === "safe" ? 0 : 1);
|
|
98
97
|
return true;
|
|
99
98
|
}
|
|
100
99
|
if (parsed.command === "dashboard") {
|
|
101
100
|
const { runDashboard } = await import("../commands/dashboard/runner.js");
|
|
102
101
|
const result = await runDashboard(parsed.options);
|
|
103
|
-
|
|
102
|
+
setRuntimeExitCode(result.errors.length > 0 ? 1 : 0);
|
|
104
103
|
return true;
|
|
105
104
|
}
|
|
106
105
|
if (parsed.command === "ga") {
|
|
107
106
|
const { runGa } = await import("../commands/ga/runner.js");
|
|
108
107
|
const result = await runGa(parsed.options);
|
|
109
|
-
|
|
108
|
+
setRuntimeExitCode(result.ready ? 0 : 1);
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
if (parsed.command === "hook") {
|
|
112
|
+
const { runHook } = await import("../commands/hook/runner.js");
|
|
113
|
+
const result = await runHook(parsed.options);
|
|
114
|
+
setRuntimeExitCode(result.errors.length > 0 ? 1 : 0);
|
|
110
115
|
return true;
|
|
111
116
|
}
|
|
112
117
|
if (parsed.options.interactive &&
|
|
113
118
|
(parsed.command === "check" ||
|
|
114
119
|
parsed.command === "upgrade" ||
|
|
115
120
|
parsed.command === "ci")) {
|
|
116
|
-
const {
|
|
117
|
-
const result = await
|
|
121
|
+
const { runDashboard } = await import("../commands/dashboard/runner.js");
|
|
122
|
+
const result = await runDashboard({
|
|
118
123
|
...parsed.options,
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
diff: undefined,
|
|
124
|
+
mode: parsed.command === "upgrade" ? "upgrade" : "review",
|
|
125
|
+
focus: "all",
|
|
122
126
|
applySelected: parsed.command === "upgrade",
|
|
123
127
|
});
|
|
124
|
-
|
|
125
|
-
result.summary.verdict === "safe" && result.updates.length === 0 ? 0 : 1;
|
|
128
|
+
setRuntimeExitCode(result.errors.length > 0 ? 1 : 0);
|
|
126
129
|
return true;
|
|
127
130
|
}
|
|
128
131
|
return false;
|
package/dist/bin/help.js
CHANGED
|
@@ -40,7 +40,16 @@ Options:
|
|
|
40
40
|
--cooldown-days <n>
|
|
41
41
|
--pr-limit <n>
|
|
42
42
|
--only-changed
|
|
43
|
+
--affected
|
|
44
|
+
--staged
|
|
45
|
+
--base <ref>
|
|
46
|
+
--head <ref>
|
|
47
|
+
--since <ref>
|
|
43
48
|
--interactive
|
|
49
|
+
--plan-file <path>
|
|
50
|
+
--verify none|install|test|install,test
|
|
51
|
+
--test-command <cmd>
|
|
52
|
+
--verification-report-file <path>
|
|
44
53
|
--show-impact
|
|
45
54
|
--show-links
|
|
46
55
|
--show-homepage
|
|
@@ -79,7 +88,7 @@ Options:
|
|
|
79
88
|
--workspace
|
|
80
89
|
--sync
|
|
81
90
|
--install
|
|
82
|
-
--pm auto|npm|pnpm
|
|
91
|
+
--pm auto|bun|npm|pnpm|yarn
|
|
83
92
|
--target patch|minor|major|latest
|
|
84
93
|
--policy-file <path>
|
|
85
94
|
--concurrency <n>
|
|
@@ -92,6 +101,10 @@ Options:
|
|
|
92
101
|
--fix-pr-no-checkout
|
|
93
102
|
--fix-pr-batch-size <n>
|
|
94
103
|
--interactive
|
|
104
|
+
--from-plan <path>
|
|
105
|
+
--verify none|install|test|install,test
|
|
106
|
+
--test-command <cmd>
|
|
107
|
+
--verification-report-file <path>
|
|
95
108
|
--lockfile-mode preserve|update|error
|
|
96
109
|
--no-pr-report
|
|
97
110
|
--json-file <path>
|
|
@@ -109,11 +122,17 @@ Run CI-oriented automation around the same lifecycle:
|
|
|
109
122
|
Options:
|
|
110
123
|
--workspace
|
|
111
124
|
--mode minimal|strict|enterprise
|
|
125
|
+
--gate check|doctor|review|upgrade
|
|
112
126
|
--group-by none|name|scope|kind|risk
|
|
113
127
|
--group-max <n>
|
|
114
128
|
--cooldown-days <n>
|
|
115
129
|
--pr-limit <n>
|
|
116
130
|
--only-changed
|
|
131
|
+
--affected
|
|
132
|
+
--staged
|
|
133
|
+
--base <ref>
|
|
134
|
+
--head <ref>
|
|
135
|
+
--since <ref>
|
|
117
136
|
--offline
|
|
118
137
|
--concurrency <n>
|
|
119
138
|
--registry-timeout-ms <n>
|
|
@@ -126,6 +145,10 @@ Options:
|
|
|
126
145
|
--fix-pr-no-checkout
|
|
127
146
|
--fix-pr-batch-size <n>
|
|
128
147
|
--no-pr-report
|
|
148
|
+
--plan-file <path>
|
|
149
|
+
--verify none|install|test|install,test
|
|
150
|
+
--test-command <cmd>
|
|
151
|
+
--verification-report-file <path>
|
|
129
152
|
--json-file <path>
|
|
130
153
|
--github-output <path>
|
|
131
154
|
--sarif-file <path>
|
|
@@ -167,6 +190,11 @@ Scan dependencies for CVEs using OSV.dev and GitHub Advisory Database.
|
|
|
167
190
|
|
|
168
191
|
Options:
|
|
169
192
|
--workspace
|
|
193
|
+
--affected
|
|
194
|
+
--staged
|
|
195
|
+
--base <ref>
|
|
196
|
+
--head <ref>
|
|
197
|
+
--since <ref>
|
|
170
198
|
--severity critical|high|medium|low
|
|
171
199
|
--summary
|
|
172
200
|
--report table|summary|json
|
|
@@ -187,11 +215,18 @@ Use it to inspect risk, security, peer, license, and policy context before apply
|
|
|
187
215
|
|
|
188
216
|
Options:
|
|
189
217
|
--workspace
|
|
218
|
+
--only-changed
|
|
219
|
+
--affected
|
|
220
|
+
--staged
|
|
221
|
+
--base <ref>
|
|
222
|
+
--head <ref>
|
|
223
|
+
--since <ref>
|
|
190
224
|
--interactive
|
|
191
225
|
--security-only
|
|
192
226
|
--risk critical|high|medium|low
|
|
193
227
|
--diff patch|minor|major|latest
|
|
194
228
|
--apply-selected
|
|
229
|
+
--plan-file <path>
|
|
195
230
|
--show-changelog
|
|
196
231
|
--policy-file <path>
|
|
197
232
|
--json-file <path>
|
|
@@ -206,9 +241,37 @@ Produce a fast summary verdict and point the operator to review when action is n
|
|
|
206
241
|
|
|
207
242
|
Options:
|
|
208
243
|
--workspace
|
|
244
|
+
--only-changed
|
|
245
|
+
--affected
|
|
246
|
+
--staged
|
|
247
|
+
--base <ref>
|
|
248
|
+
--head <ref>
|
|
249
|
+
--since <ref>
|
|
209
250
|
--verdict-only
|
|
210
251
|
--include-changelog
|
|
211
252
|
--json-file <path>`;
|
|
253
|
+
}
|
|
254
|
+
if (isCommand && command === "dashboard") {
|
|
255
|
+
return `rainy-updates dashboard [options]
|
|
256
|
+
|
|
257
|
+
Open the primary interactive dependency operations console.
|
|
258
|
+
|
|
259
|
+
Options:
|
|
260
|
+
--workspace
|
|
261
|
+
--only-changed
|
|
262
|
+
--affected
|
|
263
|
+
--staged
|
|
264
|
+
--base <ref>
|
|
265
|
+
--head <ref>
|
|
266
|
+
--since <ref>
|
|
267
|
+
--mode check|review|upgrade
|
|
268
|
+
--focus all|security|risk|major|blocked|workspace
|
|
269
|
+
--apply-selected
|
|
270
|
+
--plan-file <path>
|
|
271
|
+
--verify none|install|test|install,test
|
|
272
|
+
--test-command <cmd>
|
|
273
|
+
--verification-report-file <path>
|
|
274
|
+
--cwd <path>`;
|
|
212
275
|
}
|
|
213
276
|
if (isCommand && command === "ga") {
|
|
214
277
|
return `rainy-updates ga [options]
|
|
@@ -218,6 +281,14 @@ Audit release and CI readiness for Rainy Updates.
|
|
|
218
281
|
Options:
|
|
219
282
|
--workspace
|
|
220
283
|
--json-file <path>
|
|
284
|
+
--cwd <path>`;
|
|
285
|
+
}
|
|
286
|
+
if (isCommand && command === "hook") {
|
|
287
|
+
return `rainy-updates hook <install|uninstall|doctor> [options]
|
|
288
|
+
|
|
289
|
+
Install, remove, or inspect Rainy-managed git hooks.
|
|
290
|
+
|
|
291
|
+
Options:
|
|
221
292
|
--cwd <path>`;
|
|
222
293
|
}
|
|
223
294
|
return `rainy-updates (rup / rainy-up) <command> [options]
|
|
@@ -227,7 +298,7 @@ Commands:
|
|
|
227
298
|
doctor Summarize what matters
|
|
228
299
|
review Decide what to do
|
|
229
300
|
upgrade Apply the approved change set
|
|
230
|
-
dashboard Open the interactive
|
|
301
|
+
dashboard Open the primary interactive dependency dashboard
|
|
231
302
|
ci Run CI-focused orchestration
|
|
232
303
|
warm-cache Warm local cache for fast/offline checks
|
|
233
304
|
init-ci Scaffold GitHub Actions workflow
|
|
@@ -240,6 +311,7 @@ Commands:
|
|
|
240
311
|
licenses Scan dependency licenses and generate SPDX SBOM
|
|
241
312
|
snapshot Save, list, restore, and diff dependency state snapshots
|
|
242
313
|
ga Audit GA and CI readiness for this checkout
|
|
314
|
+
hook Install or inspect Rainy-managed git hooks
|
|
243
315
|
|
|
244
316
|
Global options:
|
|
245
317
|
--cwd <path>
|
|
@@ -258,6 +330,11 @@ Global options:
|
|
|
258
330
|
--cooldown-days <n>
|
|
259
331
|
--pr-limit <n>
|
|
260
332
|
--only-changed
|
|
333
|
+
--affected
|
|
334
|
+
--staged
|
|
335
|
+
--base <ref>
|
|
336
|
+
--head <ref>
|
|
337
|
+
--since <ref>
|
|
261
338
|
--interactive
|
|
262
339
|
--show-impact
|
|
263
340
|
--show-links
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runCli(): Promise<void>;
|
package/dist/bin/main.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { parseCliArgs } from "../core/options.js";
|
|
2
|
+
import { createRunId, writeArtifactManifest } from "../core/artifacts.js";
|
|
3
|
+
import { renderResult } from "../output/format.js";
|
|
4
|
+
import { writeGitHubOutput } from "../output/github.js";
|
|
5
|
+
import { createSarifReport } from "../output/sarif.js";
|
|
6
|
+
import { renderPrReport } from "../output/pr-report.js";
|
|
7
|
+
import { writeFileAtomic } from "../utils/io.js";
|
|
8
|
+
import { resolveFailReason } from "../core/summary.js";
|
|
9
|
+
import { stableStringify } from "../utils/stable-json.js";
|
|
10
|
+
import { getRuntimeArgv, setRuntimeExitCode, writeStderr, writeStdout, } from "../utils/runtime.js";
|
|
11
|
+
import { CLI_VERSION } from "../generated/version.js";
|
|
12
|
+
import { handleDirectCommand, runPrimaryCommand } from "./dispatch.js";
|
|
13
|
+
import { renderHelp } from "./help.js";
|
|
14
|
+
export async function runCli() {
|
|
15
|
+
try {
|
|
16
|
+
const argv = getRuntimeArgv();
|
|
17
|
+
if (argv.includes("--version") || argv.includes("-v")) {
|
|
18
|
+
writeStdout((await readPackageVersion()) + "\n");
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
22
|
+
writeStdout(renderHelp(argv[0]) + "\n");
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const parsed = await parseCliArgs(argv);
|
|
26
|
+
if (await handleDirectCommand(parsed))
|
|
27
|
+
return;
|
|
28
|
+
if (parsed.command !== "check" &&
|
|
29
|
+
parsed.command !== "upgrade" &&
|
|
30
|
+
parsed.command !== "warm-cache" &&
|
|
31
|
+
parsed.command !== "ci") {
|
|
32
|
+
throw new Error(`Unhandled command: ${parsed.command}`);
|
|
33
|
+
}
|
|
34
|
+
const result = await runPrimaryCommand(parsed);
|
|
35
|
+
result.summary.runId = createRunId(parsed.command, parsed.options, result);
|
|
36
|
+
if (parsed.options.fixPr &&
|
|
37
|
+
(parsed.command === "check" ||
|
|
38
|
+
parsed.command === "upgrade" ||
|
|
39
|
+
parsed.command === "ci")) {
|
|
40
|
+
result.summary.fixPrApplied = false;
|
|
41
|
+
result.summary.fixBranchName =
|
|
42
|
+
parsed.options.fixBranch ?? "chore/rainy-updates";
|
|
43
|
+
result.summary.fixCommitSha = "";
|
|
44
|
+
result.summary.fixPrBranchesCreated = 0;
|
|
45
|
+
if (parsed.command === "ci") {
|
|
46
|
+
const { applyFixPrBatches } = await import("../core/fix-pr-batch.js");
|
|
47
|
+
const batched = await applyFixPrBatches(parsed.options, result);
|
|
48
|
+
result.summary.fixPrApplied = batched.applied;
|
|
49
|
+
result.summary.fixBranchName =
|
|
50
|
+
batched.branches[0] ??
|
|
51
|
+
parsed.options.fixBranch ??
|
|
52
|
+
"chore/rainy-updates";
|
|
53
|
+
result.summary.fixCommitSha = batched.commits[0] ?? "";
|
|
54
|
+
result.summary.fixPrBranchesCreated = batched.branches.length;
|
|
55
|
+
if (batched.branches.length > 1) {
|
|
56
|
+
result.warnings.push(`Created ${batched.branches.length} fix-pr batch branches.`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
const { applyFixPr } = await import("../core/fix-pr.js");
|
|
61
|
+
const fixResult = await applyFixPr(parsed.options, result, []);
|
|
62
|
+
result.summary.fixPrApplied = fixResult.applied;
|
|
63
|
+
result.summary.fixBranchName = fixResult.branchName ?? "";
|
|
64
|
+
result.summary.fixCommitSha = fixResult.commitSha ?? "";
|
|
65
|
+
result.summary.fixPrBranchesCreated = fixResult.applied ? 1 : 0;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (parsed.options.prReportFile) {
|
|
69
|
+
const markdown = renderPrReport(result);
|
|
70
|
+
await writeFileAtomic(parsed.options.prReportFile, markdown + "\n");
|
|
71
|
+
}
|
|
72
|
+
const artifactManifest = await writeArtifactManifest(parsed.command, parsed.options, result);
|
|
73
|
+
if (artifactManifest) {
|
|
74
|
+
result.summary.artifactManifest = artifactManifest.artifactManifestPath;
|
|
75
|
+
}
|
|
76
|
+
result.summary.failReason = resolveFailReason(result.updates, result.errors, parsed.options.failOn, parsed.options.maxUpdates, parsed.options.ci);
|
|
77
|
+
const renderStartedAt = Date.now();
|
|
78
|
+
let rendered = renderResult(result, parsed.options.format, {
|
|
79
|
+
showImpact: parsed.options.showImpact,
|
|
80
|
+
showHomepage: parsed.options.showHomepage,
|
|
81
|
+
});
|
|
82
|
+
result.summary.durationMs.render = Math.max(0, Date.now() - renderStartedAt);
|
|
83
|
+
if (parsed.options.format === "json" ||
|
|
84
|
+
parsed.options.format === "metrics") {
|
|
85
|
+
rendered = renderResult(result, parsed.options.format, {
|
|
86
|
+
showImpact: parsed.options.showImpact,
|
|
87
|
+
showHomepage: parsed.options.showHomepage,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (parsed.options.onlyChanged &&
|
|
91
|
+
result.updates.length === 0 &&
|
|
92
|
+
result.errors.length === 0 &&
|
|
93
|
+
result.warnings.length === 0 &&
|
|
94
|
+
(parsed.options.format === "table" ||
|
|
95
|
+
parsed.options.format === "minimal" ||
|
|
96
|
+
parsed.options.format === "github")) {
|
|
97
|
+
rendered = "";
|
|
98
|
+
}
|
|
99
|
+
if (parsed.options.jsonFile) {
|
|
100
|
+
await writeFileAtomic(parsed.options.jsonFile, stableStringify(result, 2) + "\n");
|
|
101
|
+
}
|
|
102
|
+
if (parsed.options.githubOutputFile) {
|
|
103
|
+
await writeGitHubOutput(parsed.options.githubOutputFile, result);
|
|
104
|
+
}
|
|
105
|
+
if (parsed.options.sarifFile) {
|
|
106
|
+
const sarif = createSarifReport(result);
|
|
107
|
+
await writeFileAtomic(parsed.options.sarifFile, stableStringify(sarif, 2) + "\n");
|
|
108
|
+
}
|
|
109
|
+
writeStdout(rendered + "\n");
|
|
110
|
+
setRuntimeExitCode(resolveExitCode(result, result.summary.failReason));
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
writeStderr(`rainy-updates (rup): ${String(error)}\n`);
|
|
114
|
+
setRuntimeExitCode(2);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function readPackageVersion() {
|
|
118
|
+
return CLI_VERSION;
|
|
119
|
+
}
|
|
120
|
+
function resolveExitCode(result, failReason) {
|
|
121
|
+
if (result.errors.length > 0)
|
|
122
|
+
return 2;
|
|
123
|
+
if (failReason !== "none")
|
|
124
|
+
return 1;
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
package/dist/cache/cache.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { promises as fs } from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
1
|
import path from "node:path";
|
|
4
|
-
import
|
|
2
|
+
import { writeFileAtomic } from "../utils/io.js";
|
|
3
|
+
import { getCacheDir } from "../utils/runtime-paths.js";
|
|
4
|
+
import { readEnv } from "../utils/runtime.js";
|
|
5
5
|
class FileCacheStore {
|
|
6
6
|
filePath;
|
|
7
7
|
constructor(filePath) {
|
|
@@ -15,19 +15,19 @@ class FileCacheStore {
|
|
|
15
15
|
return null;
|
|
16
16
|
return {
|
|
17
17
|
...entry,
|
|
18
|
-
availableVersions: Array.isArray(entry.availableVersions)
|
|
18
|
+
availableVersions: Array.isArray(entry.availableVersions)
|
|
19
|
+
? entry.availableVersions
|
|
20
|
+
: [entry.latestVersion],
|
|
19
21
|
};
|
|
20
22
|
}
|
|
21
23
|
async set(entry) {
|
|
22
24
|
const entries = await this.readEntries();
|
|
23
25
|
entries[this.getKey(entry.packageName, entry.target)] = entry;
|
|
24
|
-
await
|
|
25
|
-
await fs.writeFile(this.filePath, JSON.stringify(entries), "utf8");
|
|
26
|
+
await writeFileAtomic(this.filePath, JSON.stringify(entries));
|
|
26
27
|
}
|
|
27
28
|
async readEntries() {
|
|
28
29
|
try {
|
|
29
|
-
|
|
30
|
-
return JSON.parse(content);
|
|
30
|
+
return (await Bun.file(this.filePath).json());
|
|
31
31
|
}
|
|
32
32
|
catch {
|
|
33
33
|
return {};
|
|
@@ -93,7 +93,9 @@ class SqliteCacheStore {
|
|
|
93
93
|
}
|
|
94
94
|
ensureSchema() {
|
|
95
95
|
try {
|
|
96
|
-
const columns = this.db
|
|
96
|
+
const columns = this.db
|
|
97
|
+
.prepare("PRAGMA table_info(versions);")
|
|
98
|
+
.all();
|
|
97
99
|
const hasAvailableVersions = columns.some((column) => column.name === "available_versions");
|
|
98
100
|
if (!hasAvailableVersions) {
|
|
99
101
|
this.db.exec("ALTER TABLE versions ADD COLUMN available_versions TEXT;");
|
|
@@ -117,8 +119,8 @@ export class VersionCache {
|
|
|
117
119
|
this.fallbackReason = fallbackReason;
|
|
118
120
|
}
|
|
119
121
|
static async create(customPath) {
|
|
120
|
-
const basePath = customPath ??
|
|
121
|
-
if (
|
|
122
|
+
const basePath = customPath ?? getCacheDir();
|
|
123
|
+
if (readEnv("RAINY_UPDATES_CACHE_BACKEND") === "file") {
|
|
122
124
|
const jsonPath = path.join(basePath, "cache.json");
|
|
123
125
|
return new VersionCache(new FileCacheStore(jsonPath), "file", true, "forced via RAINY_UPDATES_CACHE_BACKEND=file");
|
|
124
126
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import
|
|
2
|
+
import { getRuntimeCwd } from "../../utils/runtime.js";
|
|
3
3
|
const SEVERITY_LEVELS = ["critical", "high", "medium", "low"];
|
|
4
4
|
const SOURCE_MODES = ["auto", "osv", "github", "all"];
|
|
5
5
|
export function parseSeverity(value) {
|
|
@@ -10,8 +10,13 @@ export function parseSeverity(value) {
|
|
|
10
10
|
}
|
|
11
11
|
export function parseAuditArgs(args) {
|
|
12
12
|
const options = {
|
|
13
|
-
cwd:
|
|
13
|
+
cwd: getRuntimeCwd(),
|
|
14
14
|
workspace: false,
|
|
15
|
+
affected: false,
|
|
16
|
+
staged: false,
|
|
17
|
+
baseRef: undefined,
|
|
18
|
+
headRef: undefined,
|
|
19
|
+
sinceRef: undefined,
|
|
15
20
|
severity: undefined,
|
|
16
21
|
fix: false,
|
|
17
22
|
dryRun: false,
|
|
@@ -39,6 +44,37 @@ export function parseAuditArgs(args) {
|
|
|
39
44
|
index += 1;
|
|
40
45
|
continue;
|
|
41
46
|
}
|
|
47
|
+
if (current === "--affected") {
|
|
48
|
+
options.affected = true;
|
|
49
|
+
index += 1;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (current === "--staged") {
|
|
53
|
+
options.staged = true;
|
|
54
|
+
index += 1;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (current === "--base" && next) {
|
|
58
|
+
options.baseRef = next;
|
|
59
|
+
index += 2;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (current === "--base")
|
|
63
|
+
throw new Error("Missing value for --base");
|
|
64
|
+
if (current === "--head" && next) {
|
|
65
|
+
options.headRef = next;
|
|
66
|
+
index += 2;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (current === "--head")
|
|
70
|
+
throw new Error("Missing value for --head");
|
|
71
|
+
if (current === "--since" && next) {
|
|
72
|
+
options.sinceRef = next;
|
|
73
|
+
index += 2;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (current === "--since")
|
|
77
|
+
throw new Error("Missing value for --since");
|
|
42
78
|
if (current === "--severity" && next) {
|
|
43
79
|
options.severity = parseSeverity(next);
|
|
44
80
|
index += 2;
|