@kb-labs/release-manager-cli 0.5.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/README.md +211 -0
- package/dist/cli/commands/changelog.d.ts +17 -0
- package/dist/cli/commands/changelog.js +156 -0
- package/dist/cli/commands/changelog.js.map +1 -0
- package/dist/cli/commands/plan.d.ts +12 -0
- package/dist/cli/commands/plan.js +117 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/publish.d.ts +15 -0
- package/dist/cli/commands/publish.js +486 -0
- package/dist/cli/commands/publish.js.map +1 -0
- package/dist/cli/commands/report.d.ts +9 -0
- package/dist/cli/commands/report.js +77 -0
- package/dist/cli/commands/report.js.map +1 -0
- package/dist/cli/commands/rollback.d.ts +9 -0
- package/dist/cli/commands/rollback.js +42 -0
- package/dist/cli/commands/rollback.js.map +1 -0
- package/dist/cli/commands/run.d.ts +16 -0
- package/dist/cli/commands/run.js +539 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +14 -0
- package/dist/cli/commands/verify.js +106 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/contracts/release.schema.d.ts +503 -0
- package/dist/contracts/release.schema.js +45 -0
- package/dist/contracts/release.schema.js.map +1 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.js +689 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +292 -0
- package/dist/manifest.js +604 -0
- package/dist/manifest.js.map +1 -0
- package/dist/rest/handlers/build-handler.d.ts +20 -0
- package/dist/rest/handlers/build-handler.js +68 -0
- package/dist/rest/handlers/build-handler.js.map +1 -0
- package/dist/rest/handlers/changelog-generate-handler.d.ts +20 -0
- package/dist/rest/handlers/changelog-generate-handler.js +169 -0
- package/dist/rest/handlers/changelog-generate-handler.js.map +1 -0
- package/dist/rest/handlers/changelog-handler.d.ts +16 -0
- package/dist/rest/handlers/changelog-handler.js +50 -0
- package/dist/rest/handlers/changelog-handler.js.map +1 -0
- package/dist/rest/handlers/changelog-save-handler.d.ts +13 -0
- package/dist/rest/handlers/changelog-save-handler.js +42 -0
- package/dist/rest/handlers/changelog-save-handler.js.map +1 -0
- package/dist/rest/handlers/checklist-handler.d.ts +39 -0
- package/dist/rest/handlers/checklist-handler.js +155 -0
- package/dist/rest/handlers/checklist-handler.js.map +1 -0
- package/dist/rest/handlers/generate-handler.d.ts +35 -0
- package/dist/rest/handlers/generate-handler.js +206 -0
- package/dist/rest/handlers/generate-handler.js.map +1 -0
- package/dist/rest/handlers/get-checks-handler.d.ts +15 -0
- package/dist/rest/handlers/get-checks-handler.js +22 -0
- package/dist/rest/handlers/get-checks-handler.js.map +1 -0
- package/dist/rest/handlers/git-timeline-handler.d.ts +26 -0
- package/dist/rest/handlers/git-timeline-handler.js +209 -0
- package/dist/rest/handlers/git-timeline-handler.js.map +1 -0
- package/dist/rest/handlers/history-changelog-handler.d.ts +14 -0
- package/dist/rest/handlers/history-changelog-handler.js +34 -0
- package/dist/rest/handlers/history-changelog-handler.js.map +1 -0
- package/dist/rest/handlers/history-handler.d.ts +20 -0
- package/dist/rest/handlers/history-handler.js +75 -0
- package/dist/rest/handlers/history-handler.js.map +1 -0
- package/dist/rest/handlers/history-plan-handler.d.ts +30 -0
- package/dist/rest/handlers/history-plan-handler.js +34 -0
- package/dist/rest/handlers/history-plan-handler.js.map +1 -0
- package/dist/rest/handlers/history-report-handler.d.ts +64 -0
- package/dist/rest/handlers/history-report-handler.js +34 -0
- package/dist/rest/handlers/history-report-handler.js.map +1 -0
- package/dist/rest/handlers/plan-handler.d.ts +29 -0
- package/dist/rest/handlers/plan-handler.js +75 -0
- package/dist/rest/handlers/plan-handler.js.map +1 -0
- package/dist/rest/handlers/preview-handler.d.ts +26 -0
- package/dist/rest/handlers/preview-handler.js +127 -0
- package/dist/rest/handlers/preview-handler.js.map +1 -0
- package/dist/rest/handlers/report-handler.d.ts +65 -0
- package/dist/rest/handlers/report-handler.js +48 -0
- package/dist/rest/handlers/report-handler.js.map +1 -0
- package/dist/rest/handlers/reset-handler.d.ts +12 -0
- package/dist/rest/handlers/reset-handler.js +38 -0
- package/dist/rest/handlers/reset-handler.js.map +1 -0
- package/dist/rest/handlers/run-checks-handler.d.ts +20 -0
- package/dist/rest/handlers/run-checks-handler.js +58 -0
- package/dist/rest/handlers/run-checks-handler.js.map +1 -0
- package/dist/rest/handlers/run-handler.d.ts +68 -0
- package/dist/rest/handlers/run-handler.js +274 -0
- package/dist/rest/handlers/run-handler.js.map +1 -0
- package/dist/rest/handlers/scopes-handler.d.ts +20 -0
- package/dist/rest/handlers/scopes-handler.js +63 -0
- package/dist/rest/handlers/scopes-handler.js.map +1 -0
- package/dist/rest/handlers/status-handler.d.ts +24 -0
- package/dist/rest/handlers/status-handler.js +120 -0
- package/dist/rest/handlers/status-handler.js.map +1 -0
- package/dist/setup/handler.d.ts +19 -0
- package/dist/setup/handler.js +103 -0
- package/dist/setup/handler.js.map +1 -0
- package/dist/widgets/220.js +446 -0
- package/dist/widgets/220.js.map +1 -0
- package/dist/widgets/331.js +2 -0
- package/dist/widgets/331.js.map +1 -0
- package/dist/widgets/403.js +2 -0
- package/dist/widgets/403.js.map +1 -0
- package/dist/widgets/406.js +35 -0
- package/dist/widgets/406.js.map +1 -0
- package/dist/widgets/455.js +2 -0
- package/dist/widgets/455.js.map +1 -0
- package/dist/widgets/482.js +2 -0
- package/dist/widgets/482.js.map +1 -0
- package/dist/widgets/485.js +2 -0
- package/dist/widgets/485.js.map +1 -0
- package/dist/widgets/527.js +2 -0
- package/dist/widgets/527.js.map +1 -0
- package/dist/widgets/628.js +2 -0
- package/dist/widgets/628.js.map +1 -0
- package/dist/widgets/694.js +2 -0
- package/dist/widgets/694.js.map +1 -0
- package/dist/widgets/712.js +2 -0
- package/dist/widgets/712.js.map +1 -0
- package/dist/widgets/866.js +2 -0
- package/dist/widgets/866.js.map +1 -0
- package/dist/widgets/915.js +39 -0
- package/dist/widgets/915.js.map +1 -0
- package/dist/widgets/957.js +10 -0
- package/dist/widgets/957.js.map +1 -0
- package/dist/widgets/983.js +2 -0
- package/dist/widgets/983.js.map +1 -0
- package/dist/widgets/@mf-types.d.ts +3 -0
- package/dist/widgets/@mf-types.zip +0 -0
- package/dist/widgets/__federation_expose_ReleasePage.js +2 -0
- package/dist/widgets/__federation_expose_ReleasePage.js.map +1 -0
- package/dist/widgets/mf-manifest.json +260 -0
- package/dist/widgets/mf-stats.json +302 -0
- package/dist/widgets/remoteEntry.js +7 -0
- package/dist/widgets/remoteEntry.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
import { defineCommand, findRepoRoot, useLoader, useConfig, useLogger } from '@kb-labs/sdk';
|
|
2
|
+
import { planRelease } from '@kb-labs/release-manager-core';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import 'fs/promises';
|
|
5
|
+
import 'globby';
|
|
6
|
+
import { spawn } from 'child_process';
|
|
7
|
+
import { readFileSync, readdirSync, writeFileSync } from 'fs';
|
|
8
|
+
import * as readline from 'readline/promises';
|
|
9
|
+
|
|
10
|
+
// src/cli/commands/publish.ts
|
|
11
|
+
function resolveToken(token) {
|
|
12
|
+
return token ?? process.env.NPM_TOKEN ?? process.env.NODE_AUTH_TOKEN;
|
|
13
|
+
}
|
|
14
|
+
function publishSinglePackage(options) {
|
|
15
|
+
const { packagePath, token, otp, dryRun, tag, access, registry } = options;
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const args = ["publish"];
|
|
18
|
+
if (dryRun) {
|
|
19
|
+
args.push("--dry-run");
|
|
20
|
+
}
|
|
21
|
+
if (tag) {
|
|
22
|
+
args.push(`--tag=${tag}`);
|
|
23
|
+
}
|
|
24
|
+
if (access) {
|
|
25
|
+
args.push(`--access=${access}`);
|
|
26
|
+
}
|
|
27
|
+
if (registry) {
|
|
28
|
+
args.push(`--registry=${registry}`);
|
|
29
|
+
}
|
|
30
|
+
if (otp) {
|
|
31
|
+
args.push(`--otp=${otp}`);
|
|
32
|
+
}
|
|
33
|
+
const env = { ...process.env };
|
|
34
|
+
if (token) {
|
|
35
|
+
env["NODE_AUTH_TOKEN"] = token;
|
|
36
|
+
}
|
|
37
|
+
const child = spawn("npm", args, {
|
|
38
|
+
cwd: packagePath,
|
|
39
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
40
|
+
shell: true,
|
|
41
|
+
env
|
|
42
|
+
});
|
|
43
|
+
let stdout = "";
|
|
44
|
+
let stderr = "";
|
|
45
|
+
child.stdout?.on("data", (data) => {
|
|
46
|
+
stdout += data.toString();
|
|
47
|
+
});
|
|
48
|
+
child.stderr?.on("data", (data) => {
|
|
49
|
+
stderr += data.toString();
|
|
50
|
+
});
|
|
51
|
+
child.on("close", (code) => {
|
|
52
|
+
if (code === 0) {
|
|
53
|
+
resolve();
|
|
54
|
+
} else {
|
|
55
|
+
reject(new Error(stderr || stdout || `npm publish exited with code ${code}`));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
child.on("error", (err) => {
|
|
59
|
+
reject(err);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
async function publishPackagesProgrammatic(options) {
|
|
64
|
+
const { packages, dryRun, otp, tag, access, registry } = options;
|
|
65
|
+
const logger = useLogger();
|
|
66
|
+
const token = resolveToken(options.token);
|
|
67
|
+
if (!token && !dryRun) {
|
|
68
|
+
const error = "No npm token found. Set NPM_TOKEN (or NODE_AUTH_TOKEN) in environment.";
|
|
69
|
+
logger.error(error);
|
|
70
|
+
return {
|
|
71
|
+
results: [],
|
|
72
|
+
published: [],
|
|
73
|
+
failed: packages.map((p) => `${p.name}@${p.version}`),
|
|
74
|
+
skipped: [],
|
|
75
|
+
errors: [error]
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const results = [];
|
|
79
|
+
const versionMap = new Map(packages.map((p) => [p.name, p.version]));
|
|
80
|
+
for (const pkg of packages) {
|
|
81
|
+
logger.info(`Publishing ${pkg.name}@${pkg.version}`, { path: pkg.path, dryRun });
|
|
82
|
+
const pkgJsonPath = join(pkg.path, "package.json");
|
|
83
|
+
const originalPkgJson = readFileSync(pkgJsonPath, "utf-8");
|
|
84
|
+
let restored = false;
|
|
85
|
+
try {
|
|
86
|
+
const pkgJson = JSON.parse(originalPkgJson);
|
|
87
|
+
let modified = false;
|
|
88
|
+
for (const section of ["dependencies", "peerDependencies"]) {
|
|
89
|
+
const deps = pkgJson[section];
|
|
90
|
+
if (!deps) continue;
|
|
91
|
+
for (const [depName, depValue] of Object.entries(deps)) {
|
|
92
|
+
if (typeof depValue !== "string") continue;
|
|
93
|
+
const val = depValue;
|
|
94
|
+
if (val.startsWith("link:")) {
|
|
95
|
+
const planVersion = versionMap.get(depName);
|
|
96
|
+
if (planVersion) {
|
|
97
|
+
deps[depName] = `^${planVersion}`;
|
|
98
|
+
modified = true;
|
|
99
|
+
} else {
|
|
100
|
+
try {
|
|
101
|
+
const linkPath = val.replace("link:", "");
|
|
102
|
+
const linkedPkg = JSON.parse(readFileSync(join(pkg.path, linkPath, "package.json"), "utf-8"));
|
|
103
|
+
deps[depName] = `^${linkedPkg.version}`;
|
|
104
|
+
modified = true;
|
|
105
|
+
} catch {
|
|
106
|
+
deps[depName] = "*";
|
|
107
|
+
modified = true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} else if (val.startsWith("workspace:")) {
|
|
111
|
+
const planVersion = versionMap.get(depName);
|
|
112
|
+
if (planVersion) {
|
|
113
|
+
deps[depName] = val === "workspace:*" ? `^${planVersion}` : val.replace("workspace:", "");
|
|
114
|
+
modified = true;
|
|
115
|
+
} else {
|
|
116
|
+
try {
|
|
117
|
+
const repoRoot = join(pkg.path, "..");
|
|
118
|
+
const candidates = readdirSync(repoRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => join(repoRoot, d.name, "package.json"));
|
|
119
|
+
for (const candidate of candidates) {
|
|
120
|
+
try {
|
|
121
|
+
const cPkg = JSON.parse(readFileSync(candidate, "utf-8"));
|
|
122
|
+
if (cPkg.name === depName) {
|
|
123
|
+
deps[depName] = `^${cPkg.version}`;
|
|
124
|
+
modified = true;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
} catch {
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} catch {
|
|
131
|
+
deps[depName] = "*";
|
|
132
|
+
modified = true;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (modified) {
|
|
139
|
+
writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2) + "\n");
|
|
140
|
+
logger.info(`Replaced link: deps for ${pkg.name}`);
|
|
141
|
+
}
|
|
142
|
+
await publishSinglePackage({
|
|
143
|
+
packagePath: pkg.path,
|
|
144
|
+
token,
|
|
145
|
+
otp,
|
|
146
|
+
dryRun,
|
|
147
|
+
tag,
|
|
148
|
+
access: access ?? "public",
|
|
149
|
+
registry
|
|
150
|
+
});
|
|
151
|
+
results.push({ name: pkg.name, version: pkg.version, success: true });
|
|
152
|
+
logger.info(`Published ${pkg.name}@${pkg.version}`);
|
|
153
|
+
} catch (error) {
|
|
154
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
155
|
+
logger.error(`Failed to publish ${pkg.name}@${pkg.version}`, void 0, { error: message });
|
|
156
|
+
results.push({
|
|
157
|
+
name: pkg.name,
|
|
158
|
+
version: pkg.version,
|
|
159
|
+
success: false,
|
|
160
|
+
error: message
|
|
161
|
+
});
|
|
162
|
+
} finally {
|
|
163
|
+
if (!restored) {
|
|
164
|
+
writeFileSync(pkgJsonPath, originalPkgJson);
|
|
165
|
+
restored = true;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const published = results.filter((r) => r.success).map((r) => `${r.name}@${r.version}`);
|
|
170
|
+
const failed = results.filter((r) => !r.success).map((r) => `${r.name}@${r.version}`);
|
|
171
|
+
const errors = results.filter((r) => !r.success && r.error).map((r) => `${r.name}: ${r.error}`);
|
|
172
|
+
return {
|
|
173
|
+
results,
|
|
174
|
+
published,
|
|
175
|
+
failed,
|
|
176
|
+
skipped: dryRun ? packages.map((p) => `${p.name}@${p.version} (dry-run)`) : [],
|
|
177
|
+
errors
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
async function publishPackagesWithOTP(options) {
|
|
181
|
+
const { packages, dryRun, tag, access, ui, logger } = options;
|
|
182
|
+
let otp = options.otp;
|
|
183
|
+
const results = [];
|
|
184
|
+
const versionMap = new Map(packages.map((p) => [p.name, p.version]));
|
|
185
|
+
for (const pkg of packages) {
|
|
186
|
+
logger?.info("Publishing package", { name: pkg.name, version: pkg.version });
|
|
187
|
+
const pkgJsonPath = join(pkg.path, "package.json");
|
|
188
|
+
const originalPkgJson = readFileSync(pkgJsonPath, "utf-8");
|
|
189
|
+
let restored = false;
|
|
190
|
+
try {
|
|
191
|
+
const pkgJson = JSON.parse(originalPkgJson);
|
|
192
|
+
let modified = false;
|
|
193
|
+
for (const section of ["dependencies", "peerDependencies"]) {
|
|
194
|
+
const deps = pkgJson[section];
|
|
195
|
+
if (!deps) continue;
|
|
196
|
+
for (const [depName, depValue] of Object.entries(deps)) {
|
|
197
|
+
if (typeof depValue !== "string") continue;
|
|
198
|
+
const val = depValue;
|
|
199
|
+
if (val.startsWith("link:")) {
|
|
200
|
+
const planVersion = versionMap.get(depName);
|
|
201
|
+
if (planVersion) {
|
|
202
|
+
deps[depName] = `^${planVersion}`;
|
|
203
|
+
modified = true;
|
|
204
|
+
} else {
|
|
205
|
+
try {
|
|
206
|
+
const linkPath = val.replace("link:", "");
|
|
207
|
+
const linkedPkg = JSON.parse(readFileSync(join(pkg.path, linkPath, "package.json"), "utf-8"));
|
|
208
|
+
deps[depName] = `^${linkedPkg.version}`;
|
|
209
|
+
modified = true;
|
|
210
|
+
} catch {
|
|
211
|
+
deps[depName] = "*";
|
|
212
|
+
modified = true;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
} else if (val.startsWith("workspace:")) {
|
|
216
|
+
const planVersion = versionMap.get(depName);
|
|
217
|
+
if (planVersion) {
|
|
218
|
+
deps[depName] = val === "workspace:*" ? `^${planVersion}` : val.replace("workspace:", "");
|
|
219
|
+
modified = true;
|
|
220
|
+
} else {
|
|
221
|
+
try {
|
|
222
|
+
const repoRoot = join(pkg.path, "..");
|
|
223
|
+
const candidates = readdirSync(repoRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => join(repoRoot, d.name, "package.json"));
|
|
224
|
+
for (const candidate of candidates) {
|
|
225
|
+
try {
|
|
226
|
+
const cPkg = JSON.parse(readFileSync(candidate, "utf-8"));
|
|
227
|
+
if (cPkg.name === depName) {
|
|
228
|
+
deps[depName] = `^${cPkg.version}`;
|
|
229
|
+
modified = true;
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
} catch {
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
} catch {
|
|
236
|
+
deps[depName] = "*";
|
|
237
|
+
modified = true;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (modified) {
|
|
244
|
+
writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2) + "\n");
|
|
245
|
+
logger?.info(`Replaced link: deps for ${pkg.name}`);
|
|
246
|
+
}
|
|
247
|
+
const loader = useLoader(`Publishing ${pkg.name}@${pkg.version}...`);
|
|
248
|
+
loader.start();
|
|
249
|
+
let attempts = 0;
|
|
250
|
+
const maxAttempts = 3;
|
|
251
|
+
let published2 = false;
|
|
252
|
+
while (!published2 && attempts < maxAttempts) {
|
|
253
|
+
attempts++;
|
|
254
|
+
try {
|
|
255
|
+
await publishSinglePackage2({
|
|
256
|
+
packagePath: pkg.path,
|
|
257
|
+
otp,
|
|
258
|
+
dryRun,
|
|
259
|
+
tag,
|
|
260
|
+
access
|
|
261
|
+
});
|
|
262
|
+
published2 = true;
|
|
263
|
+
results.push({ name: pkg.name, version: pkg.version, success: true });
|
|
264
|
+
const successMsg = dryRun ? `Dry-run succeeded for ${pkg.name}@${pkg.version}` : `Published ${pkg.name}@${pkg.version}`;
|
|
265
|
+
loader.succeed(successMsg);
|
|
266
|
+
logger?.info("Package published successfully", {
|
|
267
|
+
name: pkg.name,
|
|
268
|
+
version: pkg.version,
|
|
269
|
+
dryRun
|
|
270
|
+
});
|
|
271
|
+
} catch (error) {
|
|
272
|
+
const errorMessage = error.message || String(error);
|
|
273
|
+
if (errorMessage.includes("EOTP") || errorMessage.includes("one-time password")) {
|
|
274
|
+
if (attempts < maxAttempts) {
|
|
275
|
+
loader.succeed(`\u{1F510} 2FA required for ${pkg.name}`);
|
|
276
|
+
logger?.info("OTP required for publishing", {
|
|
277
|
+
name: pkg.name,
|
|
278
|
+
attempt: attempts
|
|
279
|
+
});
|
|
280
|
+
const rl = readline.createInterface({
|
|
281
|
+
input: process.stdin,
|
|
282
|
+
output: process.stdout
|
|
283
|
+
});
|
|
284
|
+
try {
|
|
285
|
+
otp = await rl.question(" Enter OTP code: ");
|
|
286
|
+
rl.close();
|
|
287
|
+
if (!otp || otp.trim().length !== 6) {
|
|
288
|
+
ui.write?.(" \u26A0\uFE0F Invalid OTP code (must be 6 digits)\n");
|
|
289
|
+
logger?.warn("Invalid OTP code provided", { length: otp?.trim().length });
|
|
290
|
+
otp = void 0;
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
loader.update({ text: `Publishing ${pkg.name}@${pkg.version} with OTP...` });
|
|
294
|
+
loader.start();
|
|
295
|
+
logger?.debug("Retrying with OTP");
|
|
296
|
+
} catch (e) {
|
|
297
|
+
rl.close();
|
|
298
|
+
throw e;
|
|
299
|
+
}
|
|
300
|
+
} else {
|
|
301
|
+
loader.fail("Max OTP attempts reached");
|
|
302
|
+
logger?.error("Max OTP attempts reached", {
|
|
303
|
+
name: pkg.name,
|
|
304
|
+
attempts: maxAttempts
|
|
305
|
+
});
|
|
306
|
+
results.push({
|
|
307
|
+
name: pkg.name,
|
|
308
|
+
version: pkg.version,
|
|
309
|
+
success: false,
|
|
310
|
+
error: "Max OTP attempts reached"
|
|
311
|
+
});
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
} else {
|
|
315
|
+
loader.fail(`Failed: ${errorMessage}`);
|
|
316
|
+
logger?.error("Package publish failed", {
|
|
317
|
+
name: pkg.name,
|
|
318
|
+
version: pkg.version,
|
|
319
|
+
error: errorMessage
|
|
320
|
+
});
|
|
321
|
+
results.push({
|
|
322
|
+
name: pkg.name,
|
|
323
|
+
version: pkg.version,
|
|
324
|
+
success: false,
|
|
325
|
+
error: errorMessage
|
|
326
|
+
});
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
} finally {
|
|
332
|
+
if (!restored) {
|
|
333
|
+
writeFileSync(pkgJsonPath, originalPkgJson);
|
|
334
|
+
restored = true;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
const published = results.filter((r) => r.success).map((r) => `${r.name}@${r.version}`);
|
|
339
|
+
const failed = results.filter((r) => !r.success).map((r) => `${r.name}@${r.version}`);
|
|
340
|
+
const errors = results.filter((r) => !r.success && r.error).map((r) => `${r.name}: ${r.error}`);
|
|
341
|
+
return {
|
|
342
|
+
results,
|
|
343
|
+
published,
|
|
344
|
+
failed,
|
|
345
|
+
skipped: dryRun ? packages.map((p) => `${p.name}@${p.version} (dry-run)`) : [],
|
|
346
|
+
errors
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
function publishSinglePackage2(options) {
|
|
350
|
+
const { packagePath, otp, dryRun, tag, access } = options;
|
|
351
|
+
return new Promise((resolve, reject) => {
|
|
352
|
+
const args = ["publish"];
|
|
353
|
+
if (dryRun) {
|
|
354
|
+
args.push("--dry-run");
|
|
355
|
+
}
|
|
356
|
+
if (otp) {
|
|
357
|
+
args.push(`--otp=${otp}`);
|
|
358
|
+
}
|
|
359
|
+
if (tag) {
|
|
360
|
+
args.push(`--tag=${tag}`);
|
|
361
|
+
}
|
|
362
|
+
if (access) {
|
|
363
|
+
args.push(`--access=${access}`);
|
|
364
|
+
}
|
|
365
|
+
const child = spawn("npm", args, {
|
|
366
|
+
cwd: packagePath,
|
|
367
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
368
|
+
shell: true
|
|
369
|
+
});
|
|
370
|
+
let stdout = "";
|
|
371
|
+
let stderr = "";
|
|
372
|
+
child.stdout?.on("data", (data) => {
|
|
373
|
+
stdout += data.toString();
|
|
374
|
+
});
|
|
375
|
+
child.stderr?.on("data", (data) => {
|
|
376
|
+
stderr += data.toString();
|
|
377
|
+
});
|
|
378
|
+
child.on("close", (code) => {
|
|
379
|
+
if (code === 0) {
|
|
380
|
+
resolve();
|
|
381
|
+
} else {
|
|
382
|
+
const errorOutput = stderr || stdout;
|
|
383
|
+
reject(new Error(errorOutput));
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
child.on("error", (err) => {
|
|
387
|
+
reject(err);
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// src/cli/commands/publish.ts
|
|
393
|
+
var publish_default = defineCommand({
|
|
394
|
+
id: "release:publish",
|
|
395
|
+
description: "Publish packages to npm registry",
|
|
396
|
+
handler: {
|
|
397
|
+
async execute(ctx, input) {
|
|
398
|
+
const { flags } = input;
|
|
399
|
+
const { scope, otp: initialOtp, tag, access, json } = flags;
|
|
400
|
+
const dryRun = flags["dry-run"];
|
|
401
|
+
const token = flags.token ?? process.env.NPM_TOKEN ?? process.env.NODE_AUTH_TOKEN;
|
|
402
|
+
const cwd = ctx.cwd || process.cwd();
|
|
403
|
+
const repoRoot = await findRepoRoot(cwd);
|
|
404
|
+
const discoveryLoader = useLoader("Discovering packages...");
|
|
405
|
+
discoveryLoader.start();
|
|
406
|
+
const fileConfig = await useConfig();
|
|
407
|
+
const config = fileConfig ?? {};
|
|
408
|
+
const plan = await planRelease({ cwd: repoRoot, config, scope });
|
|
409
|
+
const packages = plan.packages.map((pkg) => ({
|
|
410
|
+
name: pkg.name,
|
|
411
|
+
version: pkg.nextVersion,
|
|
412
|
+
path: pkg.path
|
|
413
|
+
}));
|
|
414
|
+
discoveryLoader.succeed(`Found ${packages.length} package(s)`);
|
|
415
|
+
if (packages.length === 0) {
|
|
416
|
+
const msg = `No packages found to publish${scope ? ` matching scope: ${scope}` : ""}`;
|
|
417
|
+
if (json) {
|
|
418
|
+
ctx.ui?.json?.({ error: msg });
|
|
419
|
+
} else {
|
|
420
|
+
ctx.ui?.write?.(msg);
|
|
421
|
+
}
|
|
422
|
+
return { exitCode: 1, summary: { total: 0, successful: 0, failed: 0 } };
|
|
423
|
+
}
|
|
424
|
+
let result;
|
|
425
|
+
if (token) {
|
|
426
|
+
result = await publishPackagesProgrammatic({
|
|
427
|
+
packages,
|
|
428
|
+
dryRun,
|
|
429
|
+
otp: initialOtp,
|
|
430
|
+
tag,
|
|
431
|
+
access,
|
|
432
|
+
token
|
|
433
|
+
});
|
|
434
|
+
} else {
|
|
435
|
+
result = await publishPackagesWithOTP({
|
|
436
|
+
packages,
|
|
437
|
+
dryRun,
|
|
438
|
+
otp: initialOtp,
|
|
439
|
+
tag,
|
|
440
|
+
access: access ?? "public",
|
|
441
|
+
ui: ctx.ui,
|
|
442
|
+
logger: ctx.platform?.logger
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
const successful = result.results.filter((r) => r.success).length;
|
|
446
|
+
const failed = result.results.filter((r) => !r.success).length;
|
|
447
|
+
const publishResult = {
|
|
448
|
+
exitCode: failed === 0 ? 0 : 1,
|
|
449
|
+
published: result.results.filter((r) => r.success).map((r) => ({ name: r.name, version: r.version })),
|
|
450
|
+
failed: result.results.filter((r) => !r.success).map((r) => ({
|
|
451
|
+
name: r.name,
|
|
452
|
+
version: r.version,
|
|
453
|
+
error: r.error || "Unknown error"
|
|
454
|
+
})),
|
|
455
|
+
summary: { total: result.results.length, successful, failed }
|
|
456
|
+
};
|
|
457
|
+
if (json) {
|
|
458
|
+
ctx.ui?.json?.(publishResult);
|
|
459
|
+
return publishResult;
|
|
460
|
+
}
|
|
461
|
+
const sections = [];
|
|
462
|
+
if (successful > 0) {
|
|
463
|
+
const successItems = [];
|
|
464
|
+
for (const r of result.results.filter((r2) => r2.success)) {
|
|
465
|
+
successItems.push(`${ctx.ui.symbols.success} ${r.name}@${r.version}`);
|
|
466
|
+
successItems.push(` \u2514\u2500 https://www.npmjs.com/package/${r.name}`);
|
|
467
|
+
}
|
|
468
|
+
sections.push({ header: "Published", items: successItems });
|
|
469
|
+
}
|
|
470
|
+
if (failed > 0) {
|
|
471
|
+
const failItems = result.results.filter((r) => !r.success).map((r) => `${ctx.ui.symbols.error} ${r.name}@${r.version} - ${r.error}`);
|
|
472
|
+
sections.push({ header: "Failed", items: failItems });
|
|
473
|
+
}
|
|
474
|
+
ctx.ui.sideBox({
|
|
475
|
+
title: dryRun ? "Publish Dry-Run" : "Publish Summary",
|
|
476
|
+
sections,
|
|
477
|
+
status: failed === 0 ? "success" : "error"
|
|
478
|
+
});
|
|
479
|
+
return publishResult;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
export { publish_default as default };
|
|
485
|
+
//# sourceMappingURL=publish.js.map
|
|
486
|
+
//# sourceMappingURL=publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/shared/publish-programmatic.ts","../../../src/shared/publish-with-otp.ts","../../../src/cli/commands/publish.ts"],"names":["join","readFileSync","readdirSync","writeFileSync","published","publishSinglePackage","spawn","useLoader","r"],"mappings":"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","file":"publish.js","sourcesContent":["/**\n * Programmatic npm publishing for REST handlers (non-interactive context)\n *\n * Uses `npm publish` CLI via spawn with NODE_AUTH_TOKEN env variable.\n * This is the correct approach for granular access tokens (classic tokens\n * were revoked by npm in December 2025).\n *\n * Token resolution order:\n * 1. options.token (explicit override)\n * 2. NPM_TOKEN env variable\n * 3. NODE_AUTH_TOKEN env variable\n */\n\nimport { spawn } from 'node:child_process';\nimport { readFileSync, writeFileSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { useLogger } from '@kb-labs/sdk';\n\nexport interface PackageToPublish {\n name: string;\n version: string;\n path: string;\n}\n\nexport interface ProgrammaticPublishOptions {\n packages: PackageToPublish[];\n dryRun?: boolean;\n otp?: string;\n tag?: string;\n access?: 'public' | 'restricted';\n registry?: string;\n token?: string;\n}\n\nexport interface PublishResult {\n name: string;\n version: string;\n success: boolean;\n error?: string;\n}\n\nexport interface ProgrammaticPublishResult {\n results: PublishResult[];\n published: string[];\n failed: string[];\n skipped: string[];\n errors: string[];\n}\n\n/**\n * Resolve npm auth token from options or environment\n */\nfunction resolveToken(token?: string): string | undefined {\n return token ?? process.env.NPM_TOKEN ?? process.env.NODE_AUTH_TOKEN;\n}\n\n/**\n * Publish a single package using npm CLI\n * Passes auth token via NODE_AUTH_TOKEN env (recommended for granular tokens)\n */\nfunction publishSinglePackage(options: {\n packagePath: string;\n token: string | undefined;\n otp?: string;\n dryRun?: boolean;\n tag?: string;\n access?: string;\n registry?: string;\n}): Promise<void> {\n const { packagePath, token, otp, dryRun, tag, access, registry } = options;\n\n return new Promise((resolve, reject) => {\n const args = ['publish'];\n\n if (dryRun) {\n args.push('--dry-run');\n }\n\n if (tag) {\n args.push(`--tag=${tag}`);\n }\n\n if (access) {\n args.push(`--access=${access}`);\n }\n\n if (registry) {\n args.push(`--registry=${registry}`);\n }\n\n if (otp) {\n args.push(`--otp=${otp}`);\n }\n\n // Pass token via env — this is the correct way for granular tokens\n const env: NodeJS.ProcessEnv = { ...process.env };\n if (token) {\n env['NODE_AUTH_TOKEN'] = token;\n }\n\n const child = spawn('npm', args, {\n cwd: packagePath,\n stdio: ['ignore', 'pipe', 'pipe'],\n shell: true,\n env,\n });\n\n let stdout = '';\n let stderr = '';\n\n child.stdout?.on('data', (data: Buffer) => {\n stdout += data.toString();\n });\n\n child.stderr?.on('data', (data: Buffer) => {\n stderr += data.toString();\n });\n\n child.on('close', (code: number | null) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(stderr || stdout || `npm publish exited with code ${code}`));\n }\n });\n\n child.on('error', (err: Error) => {\n reject(err);\n });\n });\n}\n\n/**\n * Publish packages programmatically (non-interactive, for REST handlers)\n * Uses npm CLI with NODE_AUTH_TOKEN — works with granular access tokens.\n */\nexport async function publishPackagesProgrammatic(\n options: ProgrammaticPublishOptions\n): Promise<ProgrammaticPublishResult> {\n const { packages, dryRun, otp, tag, access, registry } = options;\n const logger = useLogger();\n\n const token = resolveToken(options.token);\n\n if (!token && !dryRun) {\n const error = 'No npm token found. Set NPM_TOKEN (or NODE_AUTH_TOKEN) in environment.';\n logger.error(error);\n return {\n results: [],\n published: [],\n failed: packages.map((p) => `${p.name}@${p.version}`),\n skipped: [],\n errors: [error],\n };\n }\n\n const results: PublishResult[] = [];\n\n // Build version map from all packages in this release for link: → ^version replacement\n const versionMap = new Map(packages.map(p => [p.name, p.version]));\n\n for (const pkg of packages) {\n logger.info(`Publishing ${pkg.name}@${pkg.version}`, { path: pkg.path, dryRun });\n\n // Replace link: deps with real versions before publish, restore after\n const pkgJsonPath = join(pkg.path, 'package.json');\n const originalPkgJson = readFileSync(pkgJsonPath, 'utf-8');\n let restored = false;\n\n try {\n const pkgJson = JSON.parse(originalPkgJson);\n let modified = false;\n\n for (const section of ['dependencies', 'peerDependencies'] as const) {\n const deps = pkgJson[section];\n if (!deps) continue;\n for (const [depName, depValue] of Object.entries(deps)) {\n if (typeof depValue !== 'string') continue;\n const val = depValue as string;\n\n if (val.startsWith('link:')) {\n // Cross-repo link: → ^version from plan or linked package.json\n const planVersion = versionMap.get(depName);\n if (planVersion) {\n deps[depName] = `^${planVersion}`;\n modified = true;\n } else {\n try {\n const linkPath = val.replace('link:', '');\n const linkedPkg = JSON.parse(readFileSync(join(pkg.path, linkPath, 'package.json'), 'utf-8'));\n deps[depName] = `^${linkedPkg.version}`;\n modified = true;\n } catch {\n deps[depName] = '*';\n modified = true;\n }\n }\n } else if (val.startsWith('workspace:')) {\n // Intra-repo workspace:* → ^version (pnpm does this automatically, but npm doesn't)\n const planVersion = versionMap.get(depName);\n if (planVersion) {\n deps[depName] = val === 'workspace:*' ? `^${planVersion}` : val.replace('workspace:', '');\n modified = true;\n } else {\n // Not in plan — resolve from current version in monorepo\n try {\n // Find the package in the same repo by scanning packages/*/package.json\n const repoRoot = join(pkg.path, '..');\n const candidates = readdirSync(repoRoot, { withFileTypes: true })\n .filter(d => d.isDirectory())\n .map(d => join(repoRoot, d.name, 'package.json'));\n for (const candidate of candidates) {\n try {\n const cPkg = JSON.parse(readFileSync(candidate, 'utf-8'));\n if (cPkg.name === depName) {\n deps[depName] = `^${cPkg.version}`;\n modified = true;\n break;\n }\n } catch { /* skip */ }\n }\n } catch {\n deps[depName] = '*';\n modified = true;\n }\n }\n }\n }\n }\n\n if (modified) {\n writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2) + '\\n');\n logger.info(`Replaced link: deps for ${pkg.name}`);\n }\n\n await publishSinglePackage({\n packagePath: pkg.path,\n token,\n otp,\n dryRun,\n tag,\n access: access ?? 'public',\n registry,\n });\n\n results.push({ name: pkg.name, version: pkg.version, success: true });\n logger.info(`Published ${pkg.name}@${pkg.version}`);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n\n logger.error(`Failed to publish ${pkg.name}@${pkg.version}`, undefined, { error: message });\n\n results.push({\n name: pkg.name,\n version: pkg.version,\n success: false,\n error: message,\n });\n } finally {\n // Always restore original package.json\n if (!restored) {\n writeFileSync(pkgJsonPath, originalPkgJson);\n restored = true;\n }\n }\n }\n\n const published = results.filter((r) => r.success).map((r) => `${r.name}@${r.version}`);\n const failed = results.filter((r) => !r.success).map((r) => `${r.name}@${r.version}`);\n const errors = results.filter((r) => !r.success && r.error).map((r) => `${r.name}: ${r.error}`);\n\n return {\n results,\n published,\n failed,\n skipped: dryRun ? packages.map((p) => `${p.name}@${p.version} (dry-run)`) : [],\n errors,\n };\n}\n","/**\n * Shared publishing logic with interactive OTP support\n * Used by both `release:run` and `release publish` commands\n */\n\nimport { spawn } from 'node:child_process';\nimport { readFileSync, writeFileSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport * as readline from 'node:readline/promises';\nimport { useLoader } from '@kb-labs/sdk';\n\nexport interface PackageToPublish {\n name: string;\n version: string;\n path: string;\n}\n\nexport interface PublishWithOTPOptions {\n packages: PackageToPublish[];\n dryRun?: boolean;\n otp?: string;\n tag?: string;\n access?: string;\n ui: {\n write?: (text: string) => void;\n };\n logger?: {\n info: (msg: string, meta?: any) => void;\n warn: (msg: string, meta?: any) => void;\n error: (msg: string, meta?: any) => void;\n debug: (msg: string, meta?: any) => void;\n };\n}\n\nexport interface PublishResult {\n name: string;\n version: string;\n success: boolean;\n error?: string;\n}\n\nexport interface PublishWithOTPResult {\n results: PublishResult[];\n published: string[];\n failed: string[];\n skipped: string[];\n errors: string[];\n}\n\n/**\n * Publish packages with interactive OTP support\n */\nexport async function publishPackagesWithOTP(\n options: PublishWithOTPOptions\n): Promise<PublishWithOTPResult> {\n const { packages, dryRun, tag, access, ui, logger } = options;\n let otp = options.otp;\n\n const results: PublishResult[] = [];\n\n // Build version map from all packages in this release for link: → ^version replacement\n const versionMap = new Map(packages.map(p => [p.name, p.version]));\n\n for (const pkg of packages) {\n logger?.info('Publishing package', { name: pkg.name, version: pkg.version });\n\n // Replace link: deps with real versions before publish, restore after\n const pkgJsonPath = join(pkg.path, 'package.json');\n const originalPkgJson = readFileSync(pkgJsonPath, 'utf-8');\n let restored = false;\n\n try {\n const pkgJson = JSON.parse(originalPkgJson);\n let modified = false;\n\n for (const section of ['dependencies', 'peerDependencies'] as const) {\n const deps = pkgJson[section];\n if (!deps) continue;\n for (const [depName, depValue] of Object.entries(deps)) {\n if (typeof depValue !== 'string') continue;\n const val = depValue as string;\n\n if (val.startsWith('link:')) {\n const planVersion = versionMap.get(depName);\n if (planVersion) {\n deps[depName] = `^${planVersion}`;\n modified = true;\n } else {\n try {\n const linkPath = val.replace('link:', '');\n const linkedPkg = JSON.parse(readFileSync(join(pkg.path, linkPath, 'package.json'), 'utf-8'));\n deps[depName] = `^${linkedPkg.version}`;\n modified = true;\n } catch {\n deps[depName] = '*';\n modified = true;\n }\n }\n } else if (val.startsWith('workspace:')) {\n const planVersion = versionMap.get(depName);\n if (planVersion) {\n deps[depName] = val === 'workspace:*' ? `^${planVersion}` : val.replace('workspace:', '');\n modified = true;\n } else {\n try {\n const repoRoot = join(pkg.path, '..');\n const candidates = readdirSync(repoRoot, { withFileTypes: true })\n .filter(d => d.isDirectory())\n .map(d => join(repoRoot, d.name, 'package.json'));\n for (const candidate of candidates) {\n try {\n const cPkg = JSON.parse(readFileSync(candidate, 'utf-8'));\n if (cPkg.name === depName) {\n deps[depName] = `^${cPkg.version}`;\n modified = true;\n break;\n }\n } catch { /* skip */ }\n }\n } catch {\n deps[depName] = '*';\n modified = true;\n }\n }\n }\n }\n }\n\n if (modified) {\n writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2) + '\\n');\n logger?.info(`Replaced link: deps for ${pkg.name}`);\n }\n\n const loader = useLoader(`Publishing ${pkg.name}@${pkg.version}...`);\n loader.start();\n\n let attempts = 0;\n const maxAttempts = 3;\n let published = false;\n\n while (!published && attempts < maxAttempts) {\n attempts++;\n\n try {\n await publishSinglePackage({\n packagePath: pkg.path,\n otp,\n dryRun,\n tag,\n access,\n });\n\n published = true;\n results.push({ name: pkg.name, version: pkg.version, success: true });\n\n const successMsg = dryRun\n ? `Dry-run succeeded for ${pkg.name}@${pkg.version}`\n : `Published ${pkg.name}@${pkg.version}`;\n\n loader.succeed(successMsg);\n logger?.info('Package published successfully', {\n name: pkg.name,\n version: pkg.version,\n dryRun,\n });\n } catch (error: any) {\n const errorMessage = error.message || String(error);\n\n // Check if OTP is required\n if (errorMessage.includes('EOTP') || errorMessage.includes('one-time password')) {\n if (attempts < maxAttempts) {\n loader.succeed(`🔐 2FA required for ${pkg.name}`);\n logger?.info('OTP required for publishing', {\n name: pkg.name,\n attempt: attempts,\n });\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n try {\n otp = await rl.question(' Enter OTP code: ');\n rl.close();\n\n if (!otp || otp.trim().length !== 6) {\n ui.write?.(' ⚠️ Invalid OTP code (must be 6 digits)\\n');\n logger?.warn('Invalid OTP code provided', { length: otp?.trim().length });\n otp = undefined;\n continue;\n }\n\n loader.update({ text: `Publishing ${pkg.name}@${pkg.version} with OTP...` });\n loader.start();\n logger?.debug('Retrying with OTP');\n } catch (e) {\n rl.close();\n throw e;\n }\n } else {\n loader.fail('Max OTP attempts reached');\n logger?.error('Max OTP attempts reached', {\n name: pkg.name,\n attempts: maxAttempts,\n });\n results.push({\n name: pkg.name,\n version: pkg.version,\n success: false,\n error: 'Max OTP attempts reached',\n });\n break;\n }\n } else {\n loader.fail(`Failed: ${errorMessage}`);\n logger?.error('Package publish failed', {\n name: pkg.name,\n version: pkg.version,\n error: errorMessage,\n });\n results.push({\n name: pkg.name,\n version: pkg.version,\n success: false,\n error: errorMessage,\n });\n break;\n }\n }\n }\n } finally {\n // Always restore original package.json\n if (!restored) {\n writeFileSync(pkgJsonPath, originalPkgJson);\n restored = true;\n }\n }\n }\n\n // Build result summary\n const published = results\n .filter((r) => r.success)\n .map((r) => `${r.name}@${r.version}`);\n const failed = results\n .filter((r) => !r.success)\n .map((r) => `${r.name}@${r.version}`);\n const errors = results\n .filter((r) => !r.success && r.error)\n .map((r) => `${r.name}: ${r.error}`);\n\n return {\n results,\n published,\n failed,\n skipped: dryRun ? packages.map((p) => `${p.name}@${p.version} (dry-run)`) : [],\n errors,\n };\n}\n\ninterface PublishSingleOptions {\n packagePath: string;\n otp?: string;\n dryRun?: boolean;\n tag?: string;\n access?: string;\n}\n\n/**\n * Publish a single package using npm CLI\n */\nfunction publishSinglePackage(options: PublishSingleOptions): Promise<void> {\n const { packagePath, otp, dryRun, tag, access } = options;\n\n return new Promise((resolve, reject) => {\n const args = ['publish'];\n\n if (dryRun) {\n args.push('--dry-run');\n }\n\n if (otp) {\n args.push(`--otp=${otp}`);\n }\n\n if (tag) {\n args.push(`--tag=${tag}`);\n }\n\n if (access) {\n args.push(`--access=${access}`);\n }\n\n const child = spawn('npm', args, {\n cwd: packagePath,\n stdio: ['inherit', 'pipe', 'pipe'],\n shell: true,\n });\n\n let stdout = '';\n let stderr = '';\n\n child.stdout?.on('data', (data) => {\n stdout += data.toString();\n });\n\n child.stderr?.on('data', (data) => {\n stderr += data.toString();\n });\n\n child.on('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n const errorOutput = stderr || stdout;\n reject(new Error(errorOutput));\n }\n });\n\n child.on('error', (err) => {\n reject(err);\n });\n });\n}\n","/**\n * Standalone npm publish command — thin adapter over planRelease + publish.\n * No build/verify steps (those belong in release:run pipeline).\n *\n * Token-first (programmatic), OTP fallback for interactive terminal.\n */\n\nimport { defineCommand, type CLIInput, type PluginContextV3, useLoader, useConfig } from '@kb-labs/sdk';\nimport { planRelease, type ReleaseConfig } from '@kb-labs/release-manager-core';\nimport { findRepoRoot } from '../../shared/utils';\nimport { publishPackagesProgrammatic, type ProgrammaticPublishResult } from '../../shared/publish-programmatic';\nimport { publishPackagesWithOTP, type PublishWithOTPResult } from '../../shared/publish-with-otp';\n\ninterface PublishFlags {\n scope?: string;\n otp?: string;\n 'dry-run'?: boolean;\n tag?: string;\n access?: string;\n token?: string;\n json?: boolean;\n}\n\ninterface PublishResult {\n exitCode: number;\n published?: Array<{ name: string; version: string }>;\n failed?: Array<{ name: string; version: string; error: string }>;\n summary?: {\n total: number;\n successful: number;\n failed: number;\n };\n}\n\nexport default defineCommand({\n id: 'release:publish',\n description: 'Publish packages to npm registry',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<PublishFlags>): Promise<PublishResult> {\n const { flags } = input;\n const { scope, otp: initialOtp, tag, access, json } = flags;\n const dryRun = flags['dry-run'];\n const token = flags.token ?? process.env.NPM_TOKEN ?? process.env.NODE_AUTH_TOKEN;\n\n const cwd = ctx.cwd || process.cwd();\n const repoRoot = await findRepoRoot(cwd);\n\n // 1. Discover packages via planRelease\n const discoveryLoader = useLoader('Discovering packages...');\n discoveryLoader.start();\n\n const fileConfig = await useConfig<ReleaseConfig>();\n const config: ReleaseConfig = fileConfig ?? {};\n const plan = await planRelease({ cwd: repoRoot, config, scope });\n\n const packages = plan.packages.map(pkg => ({\n name: pkg.name,\n version: pkg.nextVersion,\n path: pkg.path,\n }));\n\n discoveryLoader.succeed(`Found ${packages.length} package(s)`);\n\n if (packages.length === 0) {\n const msg = `No packages found to publish${scope ? ` matching scope: ${scope}` : ''}`;\n if (json) {\n ctx.ui?.json?.({ error: msg });\n } else {\n ctx.ui?.write?.(msg);\n }\n return { exitCode: 1, summary: { total: 0, successful: 0, failed: 0 } };\n }\n\n // 2. Publish — token-first (programmatic), OTP fallback for interactive terminal\n let result: ProgrammaticPublishResult | PublishWithOTPResult;\n if (token) {\n result = await publishPackagesProgrammatic({\n packages,\n dryRun,\n otp: initialOtp,\n tag,\n access: access as 'public' | 'restricted' | undefined,\n token,\n });\n } else {\n result = await publishPackagesWithOTP({\n packages,\n dryRun,\n otp: initialOtp,\n tag,\n access: access ?? 'public',\n ui: ctx.ui,\n logger: ctx.platform?.logger,\n });\n }\n\n // 3. Format output\n const successful = result.results.filter((r) => r.success).length;\n const failed = result.results.filter((r) => !r.success).length;\n\n const publishResult: PublishResult = {\n exitCode: failed === 0 ? 0 : 1,\n published: result.results.filter((r) => r.success).map((r) => ({ name: r.name, version: r.version })),\n failed: result.results.filter((r) => !r.success).map((r) => ({\n name: r.name,\n version: r.version,\n error: r.error || 'Unknown error',\n })),\n summary: { total: result.results.length, successful, failed },\n };\n\n if (json) {\n ctx.ui?.json?.(publishResult);\n return publishResult;\n }\n\n const sections: Array<{ header?: string; items: string[] }> = [];\n\n if (successful > 0) {\n const successItems: string[] = [];\n for (const r of result.results.filter((r) => r.success)) {\n successItems.push(`${ctx.ui.symbols.success} ${r.name}@${r.version}`);\n successItems.push(` └─ https://www.npmjs.com/package/${r.name}`);\n }\n sections.push({ header: 'Published', items: successItems });\n }\n\n if (failed > 0) {\n const failItems = result.results\n .filter((r) => !r.success)\n .map((r) => `${ctx.ui.symbols.error} ${r.name}@${r.version} - ${r.error}`);\n sections.push({ header: 'Failed', items: failItems });\n }\n\n ctx.ui.sideBox({\n title: dryRun ? 'Publish Dry-Run' : 'Publish Summary',\n sections,\n status: failed === 0 ? 'success' : 'error',\n });\n\n return publishResult;\n },\n },\n});\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { CLIInput } from '@kb-labs/sdk';
|
|
3
|
+
|
|
4
|
+
interface ReportFlags {
|
|
5
|
+
json?: boolean;
|
|
6
|
+
}
|
|
7
|
+
declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, CLIInput<ReportFlags>, unknown>;
|
|
8
|
+
|
|
9
|
+
export { _default as default };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { defineCommand, findRepoRoot } from '@kb-labs/sdk';
|
|
4
|
+
import 'globby';
|
|
5
|
+
|
|
6
|
+
// src/cli/commands/report.ts
|
|
7
|
+
|
|
8
|
+
// src/cli/commands/report.ts
|
|
9
|
+
var report_default = defineCommand({
|
|
10
|
+
id: "release:report",
|
|
11
|
+
description: "Show last release report",
|
|
12
|
+
handler: {
|
|
13
|
+
async execute(ctx, input) {
|
|
14
|
+
const { flags } = input;
|
|
15
|
+
const cwd = ctx.cwd || process.cwd();
|
|
16
|
+
const repoRoot = await findRepoRoot(cwd);
|
|
17
|
+
const reportPath = join(repoRoot, ".kb", "release", "report.json");
|
|
18
|
+
try {
|
|
19
|
+
const reportContent = await readFile(reportPath, "utf-8");
|
|
20
|
+
const report = JSON.parse(reportContent);
|
|
21
|
+
ctx.platform?.logger?.info?.("Release report completed", {
|
|
22
|
+
stage: report.stage,
|
|
23
|
+
ok: report.result.ok
|
|
24
|
+
});
|
|
25
|
+
if (flags.json) {
|
|
26
|
+
ctx.ui?.json?.(report);
|
|
27
|
+
} else {
|
|
28
|
+
if (!ctx.ui) {
|
|
29
|
+
throw new Error("UI not available");
|
|
30
|
+
}
|
|
31
|
+
const sections = [
|
|
32
|
+
{
|
|
33
|
+
header: "Summary",
|
|
34
|
+
items: [
|
|
35
|
+
`Timestamp: ${report.ts}`,
|
|
36
|
+
`Stage: ${report.stage}`,
|
|
37
|
+
`Result: ${report.result.ok ? "SUCCESS" : "FAILED"}`
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
];
|
|
41
|
+
if (report.result.errors && report.result.errors.length > 0) {
|
|
42
|
+
const errorItems = [];
|
|
43
|
+
for (const error of report.result.errors) {
|
|
44
|
+
errorItems.push(error);
|
|
45
|
+
}
|
|
46
|
+
sections.push({
|
|
47
|
+
header: "Errors",
|
|
48
|
+
items: errorItems
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const status = report.result.ok ? "success" : "error";
|
|
52
|
+
ctx.ui.sideBox({
|
|
53
|
+
title: "Release Report",
|
|
54
|
+
sections,
|
|
55
|
+
status
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return { exitCode: report.result.ok ? 0 : 1, report };
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (error.code === "ENOENT") {
|
|
61
|
+
ctx.platform?.logger?.warn?.("No release report found");
|
|
62
|
+
if (flags.json) {
|
|
63
|
+
ctx.ui?.json?.({ exitCode: 3, meta: { error: "No release report found" } });
|
|
64
|
+
} else {
|
|
65
|
+
ctx.ui?.error?.(new Error('No release report found. Run "kb release run" first.'));
|
|
66
|
+
}
|
|
67
|
+
return { exitCode: 3, meta: { error: "No release report found" } };
|
|
68
|
+
}
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
export { report_default as default };
|
|
76
|
+
//# sourceMappingURL=report.js.map
|
|
77
|
+
//# sourceMappingURL=report.js.map
|