@rainy-updates/cli 0.5.4 → 0.5.6
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 +84 -0
- package/README.md +5 -0
- package/dist/bin/cli.js +37 -1
- package/dist/commands/audit/runner.js +43 -26
- package/dist/commands/dashboard/parser.d.ts +2 -0
- package/dist/commands/dashboard/parser.js +59 -0
- package/dist/commands/dashboard/runner.d.ts +2 -0
- package/dist/commands/dashboard/runner.js +47 -0
- package/dist/commands/doctor/parser.js +6 -0
- package/dist/commands/ga/parser.d.ts +2 -0
- package/dist/commands/ga/parser.js +50 -0
- package/dist/commands/ga/runner.d.ts +2 -0
- package/dist/commands/ga/runner.js +129 -0
- package/dist/commands/resolve/runner.js +7 -3
- package/dist/commands/review/parser.js +6 -0
- package/dist/commands/review/runner.js +4 -3
- package/dist/core/analysis-bundle.d.ts +4 -0
- package/dist/core/analysis-bundle.js +241 -0
- package/dist/core/artifacts.d.ts +3 -0
- package/dist/core/artifacts.js +48 -0
- package/dist/core/check.js +6 -1
- package/dist/core/options.d.ts +7 -1
- package/dist/core/options.js +14 -0
- package/dist/core/review-model.js +51 -177
- package/dist/core/summary.js +13 -0
- package/dist/output/format.js +15 -0
- package/dist/output/github.js +8 -0
- package/dist/output/sarif.js +12 -0
- package/dist/types/index.d.ts +92 -0
- package/dist/ui/dashboard/DashboardTUI.d.ts +6 -0
- package/dist/ui/dashboard/DashboardTUI.js +34 -0
- package/dist/ui/dashboard/components/DetailPanel.d.ts +4 -0
- package/dist/ui/dashboard/components/DetailPanel.js +30 -0
- package/dist/ui/dashboard/components/Footer.d.ts +4 -0
- package/dist/ui/dashboard/components/Footer.js +9 -0
- package/dist/ui/dashboard/components/Header.d.ts +4 -0
- package/dist/ui/dashboard/components/Header.js +12 -0
- package/dist/ui/dashboard/components/Sidebar.d.ts +4 -0
- package/dist/ui/dashboard/components/Sidebar.js +23 -0
- package/dist/ui/dashboard/store.d.ts +34 -0
- package/dist/ui/dashboard/store.js +148 -0
- package/dist/ui/tui.d.ts +2 -2
- package/dist/ui/tui.js +310 -79
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,90 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.5.6] - 2026-03-01
|
|
6
|
+
|
|
7
|
+
GA readiness, shared analysis plumbing, and richer review operations.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **New `ga` command** for release and CI readiness auditing:
|
|
12
|
+
- package manager detection,
|
|
13
|
+
- workspace discovery,
|
|
14
|
+
- lockfile presence checks,
|
|
15
|
+
- cache backend inspection,
|
|
16
|
+
- dist build verification,
|
|
17
|
+
- benchmark gate presence,
|
|
18
|
+
- README / CHANGELOG contract checks.
|
|
19
|
+
- **Artifact run metadata**:
|
|
20
|
+
- stable `runId`,
|
|
21
|
+
- generated artifact manifests under `.artifacts/`,
|
|
22
|
+
- additive JSON / SARIF / GitHub output fields for run and decision metadata.
|
|
23
|
+
- **Review and doctor changelog-aware flags**:
|
|
24
|
+
- `review --show-changelog`
|
|
25
|
+
- `doctor --include-changelog`
|
|
26
|
+
- **Interactive review console upgrades**:
|
|
27
|
+
- filter rail,
|
|
28
|
+
- grouping and sorting modes,
|
|
29
|
+
- inline search,
|
|
30
|
+
- detail tabs,
|
|
31
|
+
- help overlay,
|
|
32
|
+
- bulk selection shortcuts,
|
|
33
|
+
- explicit policy and decision-state rendering.
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- `review` and `doctor` now consume a single shared analysis bundle across check, audit, resolve, health, licenses, and unused dependency signals.
|
|
38
|
+
- Update records now carry additive operator metadata:
|
|
39
|
+
- `policyAction`,
|
|
40
|
+
- `decisionState`,
|
|
41
|
+
- `releaseNotesSummary`,
|
|
42
|
+
- `workspaceGroup`,
|
|
43
|
+
- `groupKey`,
|
|
44
|
+
- `selectedByDefault`,
|
|
45
|
+
- `blockedReason`,
|
|
46
|
+
- `monitorReason`.
|
|
47
|
+
- Summary/output contracts now add:
|
|
48
|
+
- `runId`,
|
|
49
|
+
- `artifactManifest`,
|
|
50
|
+
- `blockedPackages`,
|
|
51
|
+
- `reviewPackages`,
|
|
52
|
+
- `monitorPackages`,
|
|
53
|
+
- `cacheBackend`,
|
|
54
|
+
- `degradedSources`,
|
|
55
|
+
- `gaReady`.
|
|
56
|
+
- `check` now records the active cache backend in summary output and attaches workspace grouping metadata to updates.
|
|
57
|
+
- CLI help now documents:
|
|
58
|
+
- `ga`,
|
|
59
|
+
- `--show-changelog`,
|
|
60
|
+
- `--include-changelog`,
|
|
61
|
+
- `--show-links`.
|
|
62
|
+
|
|
63
|
+
### Tests
|
|
64
|
+
|
|
65
|
+
- Added parser coverage for `ga`, `review --show-changelog`, and `doctor --include-changelog`.
|
|
66
|
+
- Added output coverage for new GitHub output fields.
|
|
67
|
+
- Added GA readiness command coverage.
|
|
68
|
+
|
|
69
|
+
## [0.5.5] - 2026-03-01
|
|
70
|
+
|
|
71
|
+
Interactive Dashboard TUI overhaul and domain logic integration.
|
|
72
|
+
|
|
73
|
+
### Added
|
|
74
|
+
|
|
75
|
+
- **Fully functional Interactive Dashboard TUI** (`dashboard` command):
|
|
76
|
+
- Built with Ink for a high-performance (60FPS+) CLI experience.
|
|
77
|
+
- Quick Actions directly bound to core CLI domain logic:
|
|
78
|
+
- **`[R]esolve`**: Runs peer-conflict resolution in the background and updates the UI with severity levels.
|
|
79
|
+
- **`[A]udit`**: Runs security audits in the background and surfaces CVE advisories and risk levels inline.
|
|
80
|
+
- **`<Enter>`**: Applies selected updates and exits the TUI to run the native package manager install.
|
|
81
|
+
- Zero-dependency atomic state manager (`useSyncExternalStore`) to ensure efficient rendering and avoid React Context cascading updates.
|
|
82
|
+
- Seamless background task execution with non-blocking modal overlays (`resolving`, `auditing`).
|
|
83
|
+
|
|
84
|
+
### Changed
|
|
85
|
+
|
|
86
|
+
- Added `silent: true` flag to `AuditOptions` and `ResolveOptions` to prevent standard stream pollution during background TUI operations.
|
|
87
|
+
- Modified `dashboard` command runner to natively hand-off installation duties to the core `upgrade` flow upon `<Enter>`.
|
|
88
|
+
|
|
5
89
|
## [0.5.4] - 2026-03-01
|
|
6
90
|
|
|
7
91
|
Production hotfix for interactive review stability.
|
package/README.md
CHANGED
|
@@ -107,6 +107,7 @@ npx @rainy-updates/cli ci --workspace --mode strict
|
|
|
107
107
|
- `doctor` — summarize the current dependency situation
|
|
108
108
|
- `review` — decide what to do with security, risk, peer, and policy context
|
|
109
109
|
- `upgrade` — apply the approved change set
|
|
110
|
+
- `ga` — audit GA and CI readiness for the current checkout
|
|
110
111
|
|
|
111
112
|
### Supporting workflow
|
|
112
113
|
|
|
@@ -136,6 +137,7 @@ rup doctor --workspace
|
|
|
136
137
|
# 3) Review and decide
|
|
137
138
|
npx @rainy-updates/cli review --security-only
|
|
138
139
|
rup review --interactive
|
|
140
|
+
rup review --show-changelog
|
|
139
141
|
|
|
140
142
|
# 4) Apply upgrades with workspace sync
|
|
141
143
|
npx @rainy-updates/cli upgrade --target latest --workspace --sync --install
|
|
@@ -181,6 +183,9 @@ rup bisect axios --cmd "bun test" # if installed
|
|
|
181
183
|
|
|
182
184
|
# 12) Focus review on high-risk changes
|
|
183
185
|
rup review --risk high --diff major
|
|
186
|
+
|
|
187
|
+
# 13) Audit GA / CI readiness
|
|
188
|
+
rup ga --workspace
|
|
184
189
|
```
|
|
185
190
|
|
|
186
191
|
## What it does in production
|
package/dist/bin/cli.js
CHANGED
|
@@ -12,6 +12,7 @@ import { initCiWorkflow } from "../core/init-ci.js";
|
|
|
12
12
|
import { diffBaseline, saveBaseline } from "../core/baseline.js";
|
|
13
13
|
import { applyFixPr } from "../core/fix-pr.js";
|
|
14
14
|
import { applyFixPrBatches } from "../core/fix-pr-batch.js";
|
|
15
|
+
import { createRunId, writeArtifactManifest } from "../core/artifacts.js";
|
|
15
16
|
import { renderResult } from "../output/format.js";
|
|
16
17
|
import { writeGitHubOutput } from "../output/github.js";
|
|
17
18
|
import { createSarifReport } from "../output/sarif.js";
|
|
@@ -128,6 +129,18 @@ async function main() {
|
|
|
128
129
|
process.exitCode = result.verdict === "safe" ? 0 : 1;
|
|
129
130
|
return;
|
|
130
131
|
}
|
|
132
|
+
if (parsed.command === "dashboard") {
|
|
133
|
+
const { runDashboard } = await import("../commands/dashboard/runner.js");
|
|
134
|
+
const result = await runDashboard(parsed.options);
|
|
135
|
+
process.exitCode = result.errors.length > 0 ? 1 : 0;
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (parsed.command === "ga") {
|
|
139
|
+
const { runGa } = await import("../commands/ga/runner.js");
|
|
140
|
+
const result = await runGa(parsed.options);
|
|
141
|
+
process.exitCode = result.ready ? 0 : 1;
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
131
144
|
if (parsed.options.interactive &&
|
|
132
145
|
(parsed.command === "check" ||
|
|
133
146
|
parsed.command === "upgrade" ||
|
|
@@ -141,10 +154,13 @@ async function main() {
|
|
|
141
154
|
applySelected: parsed.command === "upgrade",
|
|
142
155
|
});
|
|
143
156
|
process.exitCode =
|
|
144
|
-
result.summary.verdict === "safe" && result.updates.length === 0
|
|
157
|
+
result.summary.verdict === "safe" && result.updates.length === 0
|
|
158
|
+
? 0
|
|
159
|
+
: 1;
|
|
145
160
|
return;
|
|
146
161
|
}
|
|
147
162
|
const result = await runCommand(parsed);
|
|
163
|
+
result.summary.runId = createRunId(parsed.command, parsed.options, result);
|
|
148
164
|
if (parsed.options.fixPr &&
|
|
149
165
|
(parsed.command === "check" ||
|
|
150
166
|
parsed.command === "upgrade" ||
|
|
@@ -179,6 +195,10 @@ async function main() {
|
|
|
179
195
|
const markdown = renderPrReport(result);
|
|
180
196
|
await writeFileAtomic(parsed.options.prReportFile, markdown + "\n");
|
|
181
197
|
}
|
|
198
|
+
const artifactManifest = await writeArtifactManifest(parsed.command, parsed.options, result);
|
|
199
|
+
if (artifactManifest) {
|
|
200
|
+
result.summary.artifactManifest = artifactManifest.artifactManifestPath;
|
|
201
|
+
}
|
|
182
202
|
result.summary.failReason = resolveFailReason(result.updates, result.errors, parsed.options.failOn, parsed.options.maxUpdates, parsed.options.ci);
|
|
183
203
|
const renderStartedAt = Date.now();
|
|
184
204
|
let rendered = renderResult(result, parsed.options.format, {
|
|
@@ -265,6 +285,7 @@ Options:
|
|
|
265
285
|
--only-changed
|
|
266
286
|
--interactive
|
|
267
287
|
--show-impact
|
|
288
|
+
--show-links
|
|
268
289
|
--show-homepage
|
|
269
290
|
--lockfile-mode preserve|update|error
|
|
270
291
|
--log-level error|warn|info|debug
|
|
@@ -414,6 +435,7 @@ Options:
|
|
|
414
435
|
--risk critical|high|medium|low
|
|
415
436
|
--diff patch|minor|major|latest
|
|
416
437
|
--apply-selected
|
|
438
|
+
--show-changelog
|
|
417
439
|
--policy-file <path>
|
|
418
440
|
--json-file <path>
|
|
419
441
|
--concurrency <n>
|
|
@@ -428,7 +450,18 @@ Produce a fast summary verdict and point the operator to review when action is n
|
|
|
428
450
|
Options:
|
|
429
451
|
--workspace
|
|
430
452
|
--verdict-only
|
|
453
|
+
--include-changelog
|
|
431
454
|
--json-file <path>`;
|
|
455
|
+
}
|
|
456
|
+
if (isCommand && command === "ga") {
|
|
457
|
+
return `rainy-updates ga [options]
|
|
458
|
+
|
|
459
|
+
Audit release and CI readiness for Rainy Updates.
|
|
460
|
+
|
|
461
|
+
Options:
|
|
462
|
+
--workspace
|
|
463
|
+
--json-file <path>
|
|
464
|
+
--cwd <path>`;
|
|
432
465
|
}
|
|
433
466
|
return `rainy-updates (rup / rainy-up) <command> [options]
|
|
434
467
|
|
|
@@ -437,6 +470,7 @@ Commands:
|
|
|
437
470
|
doctor Summarize what matters
|
|
438
471
|
review Decide what to do
|
|
439
472
|
upgrade Apply the approved change set
|
|
473
|
+
dashboard Open the interactive DevOps dashboard (Ink TUI)
|
|
440
474
|
ci Run CI-focused orchestration
|
|
441
475
|
warm-cache Warm local cache for fast/offline checks
|
|
442
476
|
init-ci Scaffold GitHub Actions workflow
|
|
@@ -448,6 +482,7 @@ Commands:
|
|
|
448
482
|
resolve Check peer dependency conflicts (pure-TS, no subprocess)
|
|
449
483
|
licenses Scan dependency licenses and generate SPDX SBOM
|
|
450
484
|
snapshot Save, list, restore, and diff dependency state snapshots
|
|
485
|
+
ga Audit GA and CI readiness for this checkout
|
|
451
486
|
|
|
452
487
|
Global options:
|
|
453
488
|
--cwd <path>
|
|
@@ -468,6 +503,7 @@ Global options:
|
|
|
468
503
|
--only-changed
|
|
469
504
|
--interactive
|
|
470
505
|
--show-impact
|
|
506
|
+
--show-links
|
|
471
507
|
--show-homepage
|
|
472
508
|
--mode minimal|strict|enterprise
|
|
473
509
|
--fix-pr
|
|
@@ -54,7 +54,9 @@ export async function runAudit(options) {
|
|
|
54
54
|
result.warnings.push("No dependencies found to audit.");
|
|
55
55
|
return result;
|
|
56
56
|
}
|
|
57
|
-
|
|
57
|
+
if (!options.silent) {
|
|
58
|
+
process.stderr.write(`[audit] Querying ${describeSourceMode(options.sourceMode)} for ${targetResolution.targets.length} dependency version${targetResolution.targets.length === 1 ? "" : "s"}...\n`);
|
|
59
|
+
}
|
|
58
60
|
const fetched = await fetchAdvisories(targetResolution.targets, {
|
|
59
61
|
concurrency: options.concurrency,
|
|
60
62
|
registryTimeoutMs: options.registryTimeoutMs,
|
|
@@ -77,15 +79,17 @@ export async function runAudit(options) {
|
|
|
77
79
|
result.advisories = advisories;
|
|
78
80
|
result.packages = summarizeAdvisories(advisories);
|
|
79
81
|
result.autoFixable = advisories.filter((a) => a.patchedVersion !== null).length;
|
|
80
|
-
if (options.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
82
|
+
if (!options.silent) {
|
|
83
|
+
if (options.reportFormat === "summary") {
|
|
84
|
+
process.stdout.write(renderAuditSummary(result.packages) +
|
|
85
|
+
renderAuditSourceHealth(result.sourceHealth) +
|
|
86
|
+
"\n");
|
|
87
|
+
}
|
|
88
|
+
else if (options.reportFormat === "table" || !options.jsonFile) {
|
|
89
|
+
process.stdout.write(renderAuditTable(advisories) +
|
|
90
|
+
renderAuditSourceHealth(result.sourceHealth) +
|
|
91
|
+
"\n");
|
|
92
|
+
}
|
|
89
93
|
}
|
|
90
94
|
if (options.jsonFile) {
|
|
91
95
|
await writeFileAtomic(options.jsonFile, stableStringify({
|
|
@@ -97,7 +101,9 @@ export async function runAudit(options) {
|
|
|
97
101
|
errors: result.errors,
|
|
98
102
|
warnings: result.warnings,
|
|
99
103
|
}, 2) + "\n");
|
|
100
|
-
|
|
104
|
+
if (!options.silent) {
|
|
105
|
+
process.stderr.write(`[audit] JSON report written to ${options.jsonFile}\n`);
|
|
106
|
+
}
|
|
101
107
|
}
|
|
102
108
|
if (options.fix && result.autoFixable > 0) {
|
|
103
109
|
await applyFix(advisories, options);
|
|
@@ -120,27 +126,35 @@ async function applyFix(advisories, options) {
|
|
|
120
126
|
const installArgs = buildInstallArgs(pm, patchMap);
|
|
121
127
|
const installCmd = `${pm} ${installArgs.join(" ")}`;
|
|
122
128
|
if (options.dryRun) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
if (!options.silent) {
|
|
130
|
+
process.stderr.write(`[audit] --dry-run: would execute:\n ${installCmd}\n`);
|
|
131
|
+
if (options.commit) {
|
|
132
|
+
const msg = buildCommitMessage(patchMap);
|
|
133
|
+
process.stderr.write(`[audit] --dry-run: would commit:\n git commit -m "${msg}"\n`);
|
|
134
|
+
}
|
|
127
135
|
}
|
|
128
136
|
return;
|
|
129
137
|
}
|
|
130
|
-
|
|
131
|
-
|
|
138
|
+
if (!options.silent) {
|
|
139
|
+
process.stderr.write(`[audit] Applying ${patchMap.size} fix(es)...\n`);
|
|
140
|
+
process.stderr.write(` → ${installCmd}\n`);
|
|
141
|
+
}
|
|
132
142
|
try {
|
|
133
143
|
await runCommand(pm, installArgs, options.cwd);
|
|
134
144
|
}
|
|
135
145
|
catch (err) {
|
|
136
|
-
|
|
146
|
+
if (!options.silent) {
|
|
147
|
+
process.stderr.write(`[audit] Install failed: ${String(err)}\n`);
|
|
148
|
+
}
|
|
137
149
|
return;
|
|
138
150
|
}
|
|
139
|
-
|
|
151
|
+
if (!options.silent) {
|
|
152
|
+
process.stderr.write(`[audit] ✔ Patches applied successfully.\n`);
|
|
153
|
+
}
|
|
140
154
|
if (options.commit) {
|
|
141
|
-
await commitFix(patchMap, options.cwd);
|
|
155
|
+
await commitFix(patchMap, options.cwd, options.silent);
|
|
142
156
|
}
|
|
143
|
-
else {
|
|
157
|
+
else if (!options.silent) {
|
|
144
158
|
process.stderr.write(`[audit] Tip: run with --commit to automatically commit the changes.\n`);
|
|
145
159
|
}
|
|
146
160
|
}
|
|
@@ -157,7 +171,7 @@ function buildInstallArgs(pm, patchMap) {
|
|
|
157
171
|
return ["install", ...packages]; // npm
|
|
158
172
|
}
|
|
159
173
|
}
|
|
160
|
-
async function commitFix(patchMap, cwd) {
|
|
174
|
+
async function commitFix(patchMap, cwd, silent) {
|
|
161
175
|
const msg = buildCommitMessage(patchMap);
|
|
162
176
|
try {
|
|
163
177
|
// Stage all modified files (package.json + lockfiles)
|
|
@@ -171,12 +185,15 @@ async function commitFix(patchMap, cwd) {
|
|
|
171
185
|
"bun.lockb",
|
|
172
186
|
], cwd, true);
|
|
173
187
|
await runCommand("git", ["commit", "-m", msg], cwd);
|
|
174
|
-
|
|
188
|
+
if (!silent)
|
|
189
|
+
process.stderr.write(`[audit] ✔ Committed: "${msg}"\n`);
|
|
175
190
|
}
|
|
176
191
|
catch (err) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
192
|
+
if (!silent) {
|
|
193
|
+
process.stderr.write(`[audit] Git commit failed: ${String(err)}\n`);
|
|
194
|
+
process.stderr.write(`[audit] Changes are applied — commit manually with:\n`);
|
|
195
|
+
process.stderr.write(` git add -A && git commit -m "${msg}"\n`);
|
|
196
|
+
}
|
|
180
197
|
}
|
|
181
198
|
}
|
|
182
199
|
function buildCommitMessage(patchMap) {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export function parseDashboardArgs(args) {
|
|
2
|
+
const options = {
|
|
3
|
+
cwd: process.cwd(),
|
|
4
|
+
target: "latest",
|
|
5
|
+
includeKinds: [
|
|
6
|
+
"dependencies",
|
|
7
|
+
"devDependencies",
|
|
8
|
+
"optionalDependencies",
|
|
9
|
+
"peerDependencies",
|
|
10
|
+
],
|
|
11
|
+
cacheTtlSeconds: 3600,
|
|
12
|
+
ci: false,
|
|
13
|
+
format: "table",
|
|
14
|
+
workspace: false,
|
|
15
|
+
concurrency: 16,
|
|
16
|
+
registryTimeoutMs: 8000,
|
|
17
|
+
registryRetries: 3,
|
|
18
|
+
offline: false,
|
|
19
|
+
stream: false,
|
|
20
|
+
logLevel: "info",
|
|
21
|
+
groupBy: "none",
|
|
22
|
+
onlyChanged: false,
|
|
23
|
+
ciProfile: "minimal",
|
|
24
|
+
lockfileMode: "preserve",
|
|
25
|
+
interactive: true,
|
|
26
|
+
showImpact: false,
|
|
27
|
+
showHomepage: true,
|
|
28
|
+
};
|
|
29
|
+
for (let i = 0; i < args.length; i++) {
|
|
30
|
+
const arg = args[i];
|
|
31
|
+
const nextArg = args[i + 1];
|
|
32
|
+
if (arg === "--view" && nextArg) {
|
|
33
|
+
if (nextArg === "dependencies" ||
|
|
34
|
+
nextArg === "security" ||
|
|
35
|
+
nextArg === "health") {
|
|
36
|
+
options.view = nextArg;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
throw new Error(`Invalid --view: ${nextArg}`);
|
|
40
|
+
}
|
|
41
|
+
i++;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (arg === "--view") {
|
|
45
|
+
throw new Error("Missing value for --view");
|
|
46
|
+
}
|
|
47
|
+
// Pass through common workspace / cwd args
|
|
48
|
+
if (arg === "--workspace") {
|
|
49
|
+
options.workspace = true;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (arg === "--cwd" && nextArg) {
|
|
53
|
+
options.cwd = nextArg;
|
|
54
|
+
i++;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return options;
|
|
59
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "ink";
|
|
3
|
+
import { loadConfig } from "../../config/loader.js";
|
|
4
|
+
import { DashboardTUI } from "../../ui/dashboard/DashboardTUI.js";
|
|
5
|
+
// We'll need to load initial state or data before or during the render
|
|
6
|
+
import { check } from "../../core/check.js";
|
|
7
|
+
export async function runDashboard(options) {
|
|
8
|
+
// Load configuration
|
|
9
|
+
const resolvedConfig = await loadConfig(options.cwd);
|
|
10
|
+
// Create an initial check result. In a real scenario, this could run
|
|
11
|
+
// progressively in the TUI, but for simplicity we fetch initial data first.
|
|
12
|
+
const checkResult = await check({
|
|
13
|
+
...options,
|
|
14
|
+
// We do not want `check` to exit or log heavily here, the UI will take over.
|
|
15
|
+
logLevel: "error",
|
|
16
|
+
});
|
|
17
|
+
// Render the interactive Ink Dashboard
|
|
18
|
+
const { waitUntilExit } = render(React.createElement(DashboardTUI, {
|
|
19
|
+
options,
|
|
20
|
+
initialResult: checkResult,
|
|
21
|
+
}));
|
|
22
|
+
await waitUntilExit();
|
|
23
|
+
const finalStore = await import("../../ui/dashboard/store.js");
|
|
24
|
+
const finalState = finalStore.getStore()?.getState();
|
|
25
|
+
if (finalState?.shouldApply) {
|
|
26
|
+
process.stderr.write("[dashboard] Applying updates...\n");
|
|
27
|
+
const { applySelectedUpdates } = await import("../../core/upgrade.js");
|
|
28
|
+
const { detectPackageManager } = await import("../../pm/detect.js");
|
|
29
|
+
const { installDependencies } = await import("../../pm/install.js");
|
|
30
|
+
await applySelectedUpdates({
|
|
31
|
+
...options,
|
|
32
|
+
install: false, // We handle installation explicitly below
|
|
33
|
+
packageManager: "auto",
|
|
34
|
+
sync: true,
|
|
35
|
+
lockfileMode: options.lockfileMode || "preserve",
|
|
36
|
+
}, finalState.updates);
|
|
37
|
+
// Install using the correct package manager if desired
|
|
38
|
+
const detected = await detectPackageManager(options.cwd);
|
|
39
|
+
await installDependencies(options.cwd, "auto", detected);
|
|
40
|
+
process.stderr.write("[dashboard] Successfully applied updates and installed dependencies.\n");
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
completed: true,
|
|
44
|
+
errors: [],
|
|
45
|
+
warnings: [],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -42,6 +42,7 @@ export function parseDoctorArgs(args) {
|
|
|
42
42
|
showImpact: true,
|
|
43
43
|
showHomepage: true,
|
|
44
44
|
verdictOnly: false,
|
|
45
|
+
includeChangelog: false,
|
|
45
46
|
};
|
|
46
47
|
for (let i = 0; i < args.length; i += 1) {
|
|
47
48
|
const current = args[i];
|
|
@@ -61,6 +62,10 @@ export function parseDoctorArgs(args) {
|
|
|
61
62
|
options.verdictOnly = true;
|
|
62
63
|
continue;
|
|
63
64
|
}
|
|
65
|
+
if (current === "--include-changelog") {
|
|
66
|
+
options.includeChangelog = true;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
64
69
|
if (current === "--json-file" && next) {
|
|
65
70
|
options.jsonFile = path.resolve(options.cwd, next);
|
|
66
71
|
i += 1;
|
|
@@ -86,6 +91,7 @@ Usage:
|
|
|
86
91
|
|
|
87
92
|
Options:
|
|
88
93
|
--verdict-only Print the 3-line quick verdict without counts
|
|
94
|
+
--include-changelog Include release note summaries in the aggregated review data
|
|
89
95
|
--workspace Scan all workspace packages
|
|
90
96
|
--json-file <path> Write JSON doctor report to file
|
|
91
97
|
--cwd <path>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
export function parseGaArgs(args) {
|
|
4
|
+
const options = {
|
|
5
|
+
cwd: process.cwd(),
|
|
6
|
+
workspace: false,
|
|
7
|
+
jsonFile: undefined,
|
|
8
|
+
};
|
|
9
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
10
|
+
const current = args[i];
|
|
11
|
+
const next = args[i + 1];
|
|
12
|
+
if (current === "--cwd" && next) {
|
|
13
|
+
options.cwd = path.resolve(next);
|
|
14
|
+
i += 1;
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (current === "--cwd")
|
|
18
|
+
throw new Error("Missing value for --cwd");
|
|
19
|
+
if (current === "--workspace") {
|
|
20
|
+
options.workspace = true;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (current === "--json-file" && next) {
|
|
24
|
+
options.jsonFile = path.resolve(options.cwd, next);
|
|
25
|
+
i += 1;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (current === "--json-file")
|
|
29
|
+
throw new Error("Missing value for --json-file");
|
|
30
|
+
if (current === "--help" || current === "-h") {
|
|
31
|
+
process.stdout.write(GA_HELP);
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
if (current.startsWith("-"))
|
|
35
|
+
throw new Error(`Unknown ga option: ${current}`);
|
|
36
|
+
throw new Error(`Unexpected ga argument: ${current}`);
|
|
37
|
+
}
|
|
38
|
+
return options;
|
|
39
|
+
}
|
|
40
|
+
const GA_HELP = `
|
|
41
|
+
rup ga — Audit release and CI readiness for Rainy Updates
|
|
42
|
+
|
|
43
|
+
Usage:
|
|
44
|
+
rup ga [options]
|
|
45
|
+
|
|
46
|
+
Options:
|
|
47
|
+
--workspace Evaluate workspace package coverage
|
|
48
|
+
--json-file <path> Write JSON GA report to file
|
|
49
|
+
--cwd <path>
|
|
50
|
+
`.trimStart();
|