@kb-labs/release-manager-core 0.6.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.
@@ -0,0 +1,550 @@
1
+ import { ShellAPI } from '@kb-labs/sdk';
2
+
3
+ /**
4
+ * Core types for @kb-labs/release-manager-core
5
+ */
6
+ type ReleaseStage = 'planning' | 'checking' | 'versioning' | 'publishing' | 'verifying' | 'rollback';
7
+ type VersionBump = 'patch' | 'minor' | 'major' | 'auto';
8
+ interface ReleaseContext {
9
+ repo: string;
10
+ cwd: string;
11
+ branch: string;
12
+ profile?: string;
13
+ dryRun?: boolean;
14
+ }
15
+ interface PackageVersion {
16
+ name: string;
17
+ path: string;
18
+ currentVersion: string;
19
+ nextVersion: string;
20
+ bump: VersionBump;
21
+ isPublished: boolean;
22
+ dependencies?: string[];
23
+ }
24
+ interface ReleasePlan {
25
+ packages: PackageVersion[];
26
+ strategy: 'semver';
27
+ registry: string;
28
+ rollbackEnabled: boolean;
29
+ }
30
+ interface CheckResult {
31
+ id: CheckId;
32
+ ok: boolean;
33
+ details?: unknown;
34
+ hint?: string;
35
+ timingMs?: number;
36
+ }
37
+ type CheckId = string;
38
+ /**
39
+ * Custom check configuration
40
+ * Allows defining checks declaratively through config
41
+ */
42
+ interface CustomCheckConfig {
43
+ id: string;
44
+ /** Human-readable name shown in UI. Falls back to id if not set. */
45
+ name?: string;
46
+ command: string;
47
+ args?: string[];
48
+ parser?: 'json' | 'exitcode' | ((stdout: string, stderr: string, exitCode: number) => boolean);
49
+ timeoutMs?: number;
50
+ optional?: boolean;
51
+ /**
52
+ * Run this check once in a single directory instead of once per package.
53
+ * "repoRoot" — run in the git repo root (default for monorepo builds)
54
+ * "scopePath" — run in the scope directory (monorepo root like kb-labs-core/)
55
+ * If omitted, check runs in each package directory (original behaviour).
56
+ */
57
+ runIn?: 'repoRoot' | 'scopePath' | 'perPackage';
58
+ }
59
+ interface ReleaseResult {
60
+ ok: boolean;
61
+ version?: string;
62
+ published?: string[];
63
+ skipped?: string[];
64
+ changelog?: string;
65
+ checks?: Partial<Record<CheckId, CheckResult>>;
66
+ checksPerPackage?: Record<string, Partial<Record<CheckId, CheckResult>>>;
67
+ versionUpdates?: Array<{
68
+ package: string;
69
+ from: string;
70
+ to: string;
71
+ updated: boolean;
72
+ }>;
73
+ git?: {
74
+ committed: boolean;
75
+ tagged: string[];
76
+ pushed: boolean;
77
+ };
78
+ timingMs: number;
79
+ errors?: string[];
80
+ }
81
+ interface ReleaseReport {
82
+ schemaVersion: '1.0';
83
+ ts: string;
84
+ context: ReleaseContext;
85
+ stage: ReleaseStage;
86
+ plan?: ReleasePlan;
87
+ result: ReleaseResult;
88
+ }
89
+ interface PackagesFilter {
90
+ /** Glob dirs to scan, e.g. ['packages/*', 'apps/*'].
91
+ * Defaults to full tree scan when omitted. */
92
+ paths?: string[];
93
+ /** If set — only packages matching any pattern are included. */
94
+ include?: string[];
95
+ /** Packages matching any pattern are excluded (applied after include). */
96
+ exclude?: string[];
97
+ }
98
+ interface ReleaseConfig {
99
+ registry?: string;
100
+ strategy?: 'semver';
101
+ bump?: VersionBump;
102
+ versioningStrategy?: 'lockstep' | 'independent' | 'adaptive';
103
+ strict?: boolean;
104
+ verify?: CheckId[];
105
+ checks?: CustomCheckConfig[];
106
+ publish?: {
107
+ npm?: boolean;
108
+ github?: boolean;
109
+ /** npm publish --access. Default: 'public'. */
110
+ access?: 'public' | 'restricted';
111
+ /** Package manager to use for publishing. Default: 'pnpm'. */
112
+ packageManager?: 'pnpm' | 'npm' | 'yarn';
113
+ };
114
+ /** Filter which packages are discovered and released. */
115
+ packages?: PackagesFilter;
116
+ /** Per-scope overrides — packages filter merged with global, checks replace global entirely. */
117
+ scopes?: Record<string, {
118
+ packages?: PackagesFilter;
119
+ /** If set, replaces global `checks` for this scope. */
120
+ checks?: CustomCheckConfig[];
121
+ }>;
122
+ rollback?: {
123
+ enabled?: boolean;
124
+ maxHistory?: number;
125
+ };
126
+ output?: {
127
+ json?: boolean;
128
+ md?: boolean;
129
+ text?: boolean;
130
+ };
131
+ changelog?: {
132
+ enabled?: boolean;
133
+ includeTypes?: string[];
134
+ excludeTypes?: string[];
135
+ ignoreAuthors?: string[];
136
+ scopeMap?: Record<string, string>;
137
+ collapseMerges?: boolean;
138
+ collapseReverts?: boolean;
139
+ preferMergeSummary?: boolean;
140
+ bumpStrategy?: 'independent' | 'ripple' | 'lockstep';
141
+ workspace?: boolean;
142
+ perPackage?: boolean;
143
+ format?: 'json' | 'md' | 'both';
144
+ level?: 'compact' | 'standard' | 'detailed';
145
+ template?: string | null;
146
+ locale?: 'en' | 'ru';
147
+ cache?: boolean;
148
+ requireAudit?: boolean;
149
+ requireSignedTags?: boolean;
150
+ redactPatterns?: string[];
151
+ maxBodyLength?: number;
152
+ stabilityGuards?: {
153
+ experimental?: {
154
+ allowMajor?: boolean;
155
+ };
156
+ };
157
+ ignoreSubmodules?: boolean;
158
+ metadata?: Record<string, unknown>;
159
+ };
160
+ git?: {
161
+ provider?: 'auto' | 'github' | 'gitlab' | 'generic';
162
+ baseUrl?: string | null;
163
+ autoUnshallow?: boolean;
164
+ requireSignedTags?: boolean;
165
+ };
166
+ }
167
+ interface AuditSummary {
168
+ ok: boolean;
169
+ checks: Partial<Record<string, {
170
+ ok: boolean;
171
+ code?: string;
172
+ hint?: string;
173
+ }>>;
174
+ overall?: {
175
+ ok: boolean;
176
+ failReasons: string[];
177
+ };
178
+ }
179
+ interface BuildResult {
180
+ name: string;
181
+ success: boolean;
182
+ error?: string;
183
+ durationMs: number;
184
+ }
185
+ interface VerifyResult {
186
+ name: string;
187
+ success: boolean;
188
+ issues: string[];
189
+ }
190
+ interface PublishablePackage {
191
+ name: string;
192
+ version: string;
193
+ path: string;
194
+ }
195
+ interface PublishResult {
196
+ published: string[];
197
+ skipped: string[];
198
+ errors: string[];
199
+ }
200
+ /** Injected by CLI (OTP) or REST (token-based) */
201
+ interface PackagePublisher {
202
+ publish(packages: PublishablePackage[], options: {
203
+ dryRun?: boolean;
204
+ access?: string;
205
+ }): Promise<PublishResult>;
206
+ }
207
+ /** Injected by caller — generates changelog */
208
+ interface ChangelogGenerator {
209
+ generate(plan: ReleasePlan, options: {
210
+ repoRoot: string;
211
+ gitCwd: string;
212
+ config: ReleaseConfig;
213
+ }): Promise<string>;
214
+ }
215
+ interface PipelineOptions {
216
+ cwd: string;
217
+ repoRoot: string;
218
+ /** Resolved absolute path to the monorepo being released (e.g. infra/kb-labs-adapters).
219
+ * Planner uses this as cwd for package discovery. */
220
+ scopeCwd: string;
221
+ /** Original scope name for display/reporting only */
222
+ scope?: string;
223
+ config: ReleaseConfig;
224
+ dryRun?: boolean;
225
+ skipChecks?: boolean;
226
+ skipBuild?: boolean;
227
+ skipVerify?: boolean;
228
+ /** Custom check configs from kb.config.json */
229
+ checks?: CustomCheckConfig[];
230
+ /** Injected publisher (CLI = interactive OTP, REST = programmatic token) */
231
+ publisher: PackagePublisher;
232
+ /** Injected changelog generator (with or without LLM) */
233
+ changelog?: ChangelogGenerator;
234
+ logger?: {
235
+ info?: (...args: any[]) => void;
236
+ warn?: (...args: any[]) => void;
237
+ error?: (...args: any[]) => void;
238
+ };
239
+ onProgress?: (stage: ReleaseStage, message: string) => void;
240
+ }
241
+ interface PipelineResult {
242
+ success: boolean;
243
+ report: ReleaseReport;
244
+ plan: ReleasePlan;
245
+ }
246
+
247
+ /**
248
+ * Release planner - detects changes and suggests version bumps
249
+ */
250
+
251
+ interface PlannerOptions {
252
+ cwd: string;
253
+ config: ReleaseConfig;
254
+ scope?: string;
255
+ bumpOverride?: VersionBump;
256
+ }
257
+ /**
258
+ * Plan release by detecting changes and computing version bumps
259
+ */
260
+ declare function planRelease(options: PlannerOptions): Promise<ReleasePlan>;
261
+ /**
262
+ * Match a package against a list of patterns.
263
+ * - Patterns starting with '@' or without '/' → matched against package name.
264
+ * - Patterns containing '/' (non-scoped) → matched against relative path.
265
+ * - Supports '*' wildcard (single path segment, not separator).
266
+ */
267
+ declare function matchesPackagePattern(pkgName: string, relativePath: string, patterns: string[]): boolean;
268
+
269
+ interface PublisherOptions {
270
+ cwd: string;
271
+ plan: ReleasePlan;
272
+ dryRun?: boolean;
273
+ shell?: ShellAPI;
274
+ config?: ReleaseConfig;
275
+ }
276
+ interface PublishingResult {
277
+ published: string[];
278
+ skipped: string[];
279
+ errors: string[];
280
+ versionUpdates: Array<{
281
+ package: string;
282
+ from: string;
283
+ to: string;
284
+ updated: boolean;
285
+ }>;
286
+ }
287
+ /**
288
+ * Publish packages according to plan
289
+ */
290
+ declare function publishPackages(options: PublisherOptions): Promise<PublishingResult>;
291
+ /**
292
+ * Update package.json version to nextVersion
293
+ * Should be called BEFORE generating changelog so versions match
294
+ */
295
+ declare function updatePackageVersion(pkg: PackageVersion): Promise<void>;
296
+ /**
297
+ * Update versions for all packages in the plan
298
+ */
299
+ declare function updatePackageVersions(plan: ReleasePlan): Promise<Array<{
300
+ package: string;
301
+ from: string;
302
+ to: string;
303
+ updated: boolean;
304
+ }>>;
305
+ /**
306
+ * Generate changelog entry for release
307
+ * Note: This is a simplified wrapper. Full changelog generation is handled by @kb-labs/release-manager-changelog
308
+ */
309
+ declare function generateChangelog(options: {
310
+ cwd: string;
311
+ plan: ReleasePlan;
312
+ }): Promise<string>;
313
+ /**
314
+ * Generate enhanced changelog using @kb-labs/release-manager-changelog
315
+ * This is the recommended approach for full-featured changelog generation
316
+ *
317
+ * Note: Full integration available via @kb-labs/release-manager-changelog package and CLI command
318
+ */
319
+ declare function generateEnhancedChangelog(options: {
320
+ cwd: string;
321
+ plan: ReleasePlan;
322
+ from?: string;
323
+ to?: string;
324
+ config?: any;
325
+ }): Promise<{
326
+ changelog: string;
327
+ manifest: any;
328
+ }>;
329
+ /**
330
+ * Copy changelog to each package directory
331
+ * This writes CHANGELOG.md per package with proper header
332
+ */
333
+ declare function copyChangelogToPackages(options: {
334
+ cwd: string;
335
+ plan: ReleasePlan;
336
+ changelog: string;
337
+ }): Promise<void>;
338
+ /**
339
+ * Commit and tag release changes
340
+ *
341
+ * Each package is committed inside its own git repo (supports submodules).
342
+ * After all packages are committed, tags are created in cwd (the monorepo root).
343
+ */
344
+ declare function commitAndTagRelease(options: {
345
+ cwd: string;
346
+ plan: ReleasePlan;
347
+ dryRun?: boolean;
348
+ }): Promise<{
349
+ committed: boolean;
350
+ tagged: string[];
351
+ pushed: boolean;
352
+ }>;
353
+
354
+ /**
355
+ * Rollback - manages release snapshots and recovery
356
+ */
357
+
358
+ interface RollbackSnapshot {
359
+ ts: string;
360
+ packages: PackageVersion[];
361
+ }
362
+ /**
363
+ * Save current state for potential rollback
364
+ */
365
+ declare function saveSnapshot(options: {
366
+ cwd: string;
367
+ plan: ReleasePlan;
368
+ }): Promise<void>;
369
+ /**
370
+ * Restore from snapshot
371
+ */
372
+ declare function restoreSnapshot(cwd: string): Promise<void>;
373
+
374
+ /**
375
+ * Main release runner - orchestrates full release lifecycle
376
+ */
377
+
378
+ interface RunnerOptions {
379
+ config: ReleaseConfig;
380
+ context: ReleaseContext;
381
+ runChecks?: (stage: ReleaseStage) => Promise<Partial<Record<CheckId, CheckResult>>>;
382
+ executePlan?: () => Promise<void>;
383
+ onStageChange?: (stage: ReleaseStage) => void;
384
+ }
385
+ /**
386
+ * Run full release process
387
+ */
388
+ declare function runRelease(options: RunnerOptions): Promise<ReleaseResult>;
389
+
390
+ /**
391
+ * JSON reporter for release reports
392
+ */
393
+
394
+ declare function renderJson(report: ReleaseReport): string;
395
+
396
+ /**
397
+ * Markdown reporter for release reports
398
+ */
399
+
400
+ declare function renderMarkdown(report: ReleaseReport): string;
401
+
402
+ /**
403
+ * Text reporter for release reports
404
+ */
405
+
406
+ declare function renderText(report: ReleaseReport): string;
407
+
408
+ /**
409
+ * @module @kb-labs/release-manager-core/shell-adapter
410
+ * Shell adapter for release-core - wraps execa with SDK types
411
+ */
412
+
413
+ /**
414
+ * Create a ShellAPI adapter using execa
415
+ * This is used in core libraries where ctx.runtime.shell is not available
416
+ */
417
+ declare function createExecaShellAdapter(): ShellAPI;
418
+
419
+ /**
420
+ * Versioning strategies for monorepo package releases
421
+ *
422
+ * - lockstep: All packages get the same version (maximum bump)
423
+ * - independent: Each package has its own version
424
+ * - adaptive: Lockstep if breaking changes, otherwise independent
425
+ */
426
+
427
+ type VersionStrategy = 'lockstep' | 'independent' | 'adaptive';
428
+ interface StrategyOptions {
429
+ strategy: VersionStrategy;
430
+ umbrellaPath?: string;
431
+ }
432
+ /**
433
+ * Apply versioning strategy to packages
434
+ */
435
+ declare function applyVersionStrategy(packages: PackageVersion[], options: StrategyOptions): PackageVersion[];
436
+
437
+ /**
438
+ * Unified release pipeline — single orchestrator for CLI and REST.
439
+ *
440
+ * Flow: plan → snapshot → checks → build → verify → version bump → changelog → publish → git → report
441
+ */
442
+
443
+ /**
444
+ * Run the complete release pipeline.
445
+ * Both CLI and REST call this with different injected publishers/changelog generators.
446
+ */
447
+ declare function runReleasePipeline(options: PipelineOptions): Promise<PipelineResult>;
448
+
449
+ /**
450
+ * Safe build — builds into temp dir, then atomically swaps dist/.
451
+ * Prevents crashing running services whose dist/ is wiped by tsup's `clean: true`.
452
+ */
453
+
454
+ /**
455
+ * Build all packages in a plan using safe build strategy.
456
+ * Stops on first failure.
457
+ */
458
+ declare function buildPackages(packages: PackageVersion[], options?: {
459
+ logger?: {
460
+ info?: (...args: any[]) => void;
461
+ warn?: (...args: any[]) => void;
462
+ error?: (...args: any[]) => void;
463
+ };
464
+ onProgress?: (pkg: string, result: BuildResult) => void;
465
+ }): Promise<BuildResult[]>;
466
+ /**
467
+ * Run build for a single package using safe temp-dir strategy when tsup is detected.
468
+ * Falls back to regular `pnpm run build` for non-tsup packages.
469
+ */
470
+ declare function runSafeBuild(packagePath: string, packageName: string): Promise<BuildResult>;
471
+ /**
472
+ * Check if a shell command is a build command that should use safe build.
473
+ */
474
+ declare function isBuildCommand(command: string, args?: string[]): boolean;
475
+ interface SpawnResult extends Omit<BuildResult, 'name'> {
476
+ stdout: string;
477
+ stderr: string;
478
+ exitCode: number;
479
+ }
480
+ /**
481
+ * Spawn a shell command and collect results.
482
+ * Captures both stdout and stderr — build tools often write errors to stdout.
483
+ */
484
+ declare function spawnCommand(command: string, cwd: string, timeoutMs?: number): Promise<SpawnResult>;
485
+
486
+ /**
487
+ * Unified check runner for release manager.
488
+ * Reads config.checks[], supports parser field, script path resolution, perPackage routing.
489
+ */
490
+
491
+ interface CheckRunnerOptions {
492
+ repoRoot: string;
493
+ packagePaths: string[];
494
+ scopePath?: string;
495
+ logger?: {
496
+ info?: (...args: any[]) => void;
497
+ warn?: (...args: any[]) => void;
498
+ };
499
+ }
500
+ /**
501
+ * Run all configured checks against packages.
502
+ * Handles: parser evaluation, script path resolution, perPackage/scopePath/repoRoot routing.
503
+ */
504
+ declare function runReleaseChecks(checks: CustomCheckConfig[], options: CheckRunnerOptions): Promise<CheckResult[]>;
505
+
506
+ /**
507
+ * Package verifier — npm pack → extract → verify artifacts before publish.
508
+ * Catches: directory imports, test file leaks, missing exports, syntax errors.
509
+ */
510
+
511
+ /**
512
+ * Verify all packages in a plan are publishable.
513
+ */
514
+ declare function verifyPackages(packages: PackageVersion[], options?: {
515
+ logger?: {
516
+ info?: (...args: any[]) => void;
517
+ };
518
+ onProgress?: (pkg: string, result: VerifyResult) => void;
519
+ }): Promise<VerifyResult[]>;
520
+ /**
521
+ * Verify a single package is publishable.
522
+ * npm pack → extract → check exports, directory imports, test leaks, syntax.
523
+ */
524
+ declare function verifyPackage(packagePath: string, packageName?: string): VerifyResult;
525
+
526
+ /**
527
+ * Scope utilities — resolve scope name to filesystem path.
528
+ *
529
+ * "scope" is a filter/selector concept (e.g. "@kb-labs/release-manager", "installer/kb-labs-create").
530
+ * "scopePath" is the resolved absolute filesystem path used for checks (runIn: scopePath) and git ops.
531
+ *
532
+ * Discovery (planRelease) always uses repoRoot + scope filter — never scopePath directly.
533
+ */
534
+ /**
535
+ * Resolve a scope name to an absolute filesystem path.
536
+ *
537
+ * - 'root' → repoRoot
538
+ * - '@kb-labs/foo' → directory containing package.json with that name
539
+ * - 'installer/kb-labs-create' → repoRoot/installer/kb-labs-create (direct path)
540
+ *
541
+ * Used only where a physical path is required:
542
+ * - checks with runIn: 'scopePath'
543
+ * - git commit/tag cwd
544
+ * - changelog gitCwd
545
+ *
546
+ * NOT used for package discovery — planRelease always takes (repoRoot, scope).
547
+ */
548
+ declare function resolveScopePath(repoRoot: string, scope: string): Promise<string>;
549
+
550
+ export { type AuditSummary, type BuildResult, type ChangelogGenerator, type CheckId, type CheckResult, type CustomCheckConfig, type PackagePublisher, type PackageVersion, type PackagesFilter, type PipelineOptions, type PipelineResult, type PlannerOptions, type PublishResult, type PublishablePackage, type PublisherOptions, type PublishingResult, type ReleaseConfig, type ReleaseContext, type ReleasePlan, type ReleaseReport, type ReleaseResult, type ReleaseStage, type RollbackSnapshot, type RunnerOptions, type StrategyOptions, type VerifyResult, type VersionBump, type VersionStrategy, applyVersionStrategy, buildPackages, commitAndTagRelease, copyChangelogToPackages, createExecaShellAdapter, generateChangelog, generateEnhancedChangelog, isBuildCommand, matchesPackagePattern, planRelease, publishPackages, renderJson, renderMarkdown, renderText, resolveScopePath, restoreSnapshot, runRelease, runReleaseChecks, runReleasePipeline, runSafeBuild, saveSnapshot, spawnCommand, updatePackageVersion, updatePackageVersions, verifyPackage, verifyPackages };