@kb-labs/release-manager-core 2.116.14 → 2.118.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +50 -13
- package/dist/index.js +86 -83
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,19 @@ interface PluginLogger {
|
|
|
9
9
|
warn?(message: string, meta?: Record<string, unknown>): void;
|
|
10
10
|
error?(message: string, error?: Error, meta?: Record<string, unknown>): void;
|
|
11
11
|
}
|
|
12
|
+
/** Governed process facade supplied by the plugin runtime. */
|
|
13
|
+
interface ReleaseShell {
|
|
14
|
+
exec(command: string, args?: string[], options?: {
|
|
15
|
+
cwd?: string;
|
|
16
|
+
timeout?: number;
|
|
17
|
+
env?: Record<string, string>;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
code: number;
|
|
20
|
+
stdout: string;
|
|
21
|
+
stderr: string;
|
|
22
|
+
ok: boolean;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
12
25
|
type ReleaseStage = 'planning' | 'checking' | 'versioning' | 'publishing' | 'verifying' | 'rollback';
|
|
13
26
|
type VersionBump = 'patch' | 'minor' | 'major' | 'auto';
|
|
14
27
|
/**
|
|
@@ -38,6 +51,14 @@ interface PackageVersion {
|
|
|
38
51
|
bump: VersionBump;
|
|
39
52
|
isPublished: boolean;
|
|
40
53
|
dependencies?: string[];
|
|
54
|
+
/**
|
|
55
|
+
* `nextVersion` was adopted as-is from a bump that already exists on disk
|
|
56
|
+
* (see the trust-disk branch in planner.ts) rather than derived by bumping
|
|
57
|
+
* `currentVersion`. Downstream version resolution — notably lockstep — must
|
|
58
|
+
* treat it as final: re-deriving it would bump a second time on top of an
|
|
59
|
+
* already-applied bump.
|
|
60
|
+
*/
|
|
61
|
+
versionPinned?: boolean;
|
|
41
62
|
}
|
|
42
63
|
interface ReleasePlan {
|
|
43
64
|
packages: PackageVersion[];
|
|
@@ -45,6 +66,14 @@ interface ReleasePlan {
|
|
|
45
66
|
registry: string;
|
|
46
67
|
rollbackEnabled: boolean;
|
|
47
68
|
channel: ReleaseChannel;
|
|
69
|
+
/**
|
|
70
|
+
* The flow/scope this plan was computed for. Persisted with the plan
|
|
71
|
+
* artifact so a later pipeline step can tell whether the plan on disk is
|
|
72
|
+
* the one it is supposed to consume, instead of silently reusing another
|
|
73
|
+
* flow's plan (all flows share one scope-derived artifact path).
|
|
74
|
+
*/
|
|
75
|
+
flow?: string;
|
|
76
|
+
scope?: string;
|
|
48
77
|
}
|
|
49
78
|
interface CheckResultDetails {
|
|
50
79
|
/** Which package path this failure came from (for perPackage checks). */
|
|
@@ -61,6 +90,8 @@ interface CheckResultDetails {
|
|
|
61
90
|
interface CheckResult {
|
|
62
91
|
id: CheckId;
|
|
63
92
|
ok: boolean;
|
|
93
|
+
/** Mirrors CustomCheckConfig.optional — a failed optional check must not fail the overall run. */
|
|
94
|
+
optional?: boolean;
|
|
64
95
|
/** Structured failure details — present when ok=false. */
|
|
65
96
|
details?: CheckResultDetails;
|
|
66
97
|
hint?: string;
|
|
@@ -360,6 +391,7 @@ interface PipelineOptions {
|
|
|
360
391
|
/** Pass --no-verify to git push and pushTags. Default: false (hooks run normally). */
|
|
361
392
|
noVerify?: boolean;
|
|
362
393
|
logger?: PluginLogger;
|
|
394
|
+
shell: ReleaseShell;
|
|
363
395
|
onProgress?: (stage: ReleaseStage, message: string) => void;
|
|
364
396
|
}
|
|
365
397
|
interface PipelineResult {
|
|
@@ -655,29 +687,20 @@ declare function runReleasePipeline(options: PipelineOptions): Promise<PipelineR
|
|
|
655
687
|
* dependant can fail to resolve the dependency's subpath exports in a
|
|
656
688
|
* fresh worktree where nothing has a pre-existing dist/ yet.
|
|
657
689
|
*/
|
|
658
|
-
declare function buildPackages(packages: PackageVersion[], options
|
|
690
|
+
declare function buildPackages(packages: PackageVersion[], options: {
|
|
659
691
|
logger?: PluginLogger;
|
|
692
|
+
shell: ReleaseShell;
|
|
660
693
|
onProgress?: (pkg: string, result: BuildResult) => void;
|
|
661
694
|
}): Promise<BuildResult[]>;
|
|
662
695
|
/**
|
|
663
696
|
* Run build for a single package using safe temp-dir strategy when tsup is detected.
|
|
664
697
|
* Falls back to regular `pnpm run build` for non-tsup packages.
|
|
665
698
|
*/
|
|
666
|
-
declare function runSafeBuild(packagePath: string, packageName: string): Promise<BuildResult>;
|
|
699
|
+
declare function runSafeBuild(packagePath: string, packageName: string, shell: ReleaseShell): Promise<BuildResult>;
|
|
667
700
|
/**
|
|
668
701
|
* Check if a shell command is a build command that should use safe build.
|
|
669
702
|
*/
|
|
670
703
|
declare function isBuildCommand(command: string, args?: string[]): boolean;
|
|
671
|
-
interface SpawnResult extends Omit<BuildResult, 'name'> {
|
|
672
|
-
stdout: string;
|
|
673
|
-
stderr: string;
|
|
674
|
-
exitCode: number;
|
|
675
|
-
}
|
|
676
|
-
/**
|
|
677
|
-
* Spawn a shell command and collect results.
|
|
678
|
-
* Captures both stdout and stderr — build tools often write errors to stdout.
|
|
679
|
-
*/
|
|
680
|
-
declare function spawnCommand(command: string, cwd: string, timeoutMs?: number): Promise<SpawnResult>;
|
|
681
704
|
|
|
682
705
|
/**
|
|
683
706
|
* Unified check runner for release manager.
|
|
@@ -689,7 +712,21 @@ interface CheckRunnerOptions {
|
|
|
689
712
|
packagePaths: string[];
|
|
690
713
|
scopePath?: string;
|
|
691
714
|
logger?: Pick<PluginLogger, 'info' | 'warn'>;
|
|
715
|
+
shell: ReleaseShell;
|
|
692
716
|
}
|
|
717
|
+
/**
|
|
718
|
+
* Max parallel shell.exec calls for perPackage checks.
|
|
719
|
+
* Must match the plugin manifest's `shell.maxConcurrent` permission
|
|
720
|
+
* (plugins/release/manager-cli/src/manifest.ts) — the platform's process
|
|
721
|
+
* broker admits at most that many concurrent shells for this plugin, so
|
|
722
|
+
* batching above it just queues and can blow the per-check timeout.
|
|
723
|
+
*
|
|
724
|
+
* Kept low (not e.g. 8) because pack-install is not a cheap script: it packs
|
|
725
|
+
* the tarball and runs a real `npm install` of it into a throwaway consumer
|
|
726
|
+
* per package. At higher concurrency those installs contend for CPU/disk/npm
|
|
727
|
+
* registry and start blowing their own per-check timeout under load.
|
|
728
|
+
*/
|
|
729
|
+
declare const CHECKS_CONCURRENCY = 2;
|
|
693
730
|
/**
|
|
694
731
|
* Run all configured checks against packages.
|
|
695
732
|
* Handles: parser evaluation, script path resolution, perPackage/scopePath/repoRoot routing.
|
|
@@ -821,4 +858,4 @@ declare function verifyCleanInstall(tarballPath: string, packageName: string, ad
|
|
|
821
858
|
*/
|
|
822
859
|
declare function resolveScopePath(repoRoot: string, scope: string): Promise<string>;
|
|
823
860
|
|
|
824
|
-
export { type AuditSummary, type BuildConfig, type BuildResult, type ChangelogGenerator, type CheckId, type CheckResult, type CheckResultDetails, type CleanInstallResult, type CustomCheckConfig, DEFAULT_ROOT_CHANGELOG_PATH, DEFAULT_TAG_PATTERN, type FlowConfig, type PackagePublisher, type PackageVersion, type PackagesFilter, type PipelineOptions, type PipelineResult, type PlannerOptions, type PluginLogger, type PublishResult, type PublishablePackage, type ReleaseChannel, type ReleaseConfig, type ReleaseContext, type ReleasePlan, type ReleaseReport, type ReleaseResult, type ReleaseStage, type RollbackSnapshot, type StrategyOptions, type VerifyResult, type VersionBump, type VersionStrategy, applyCanarySuffix, applyVersionStrategy, buildPackages, buildReleaseTag, commitAndTagRelease, copyChangelogToPackages, createExecaShellAdapter, discoverCurrentPackages, findForbiddenDependencyProtocols, isBuildCommand, isVersionPublished, matchesPackagePattern, mergeConfigWithFlow, mergeRootChangelog, planRelease, renderJson, renderMarkdown, renderText, resolveFlowFromTag, resolvePublishRegistry, resolvePublishTag, resolveRootChangelogRelPath, resolveScopePath, restoreSnapshot, runReleaseChecks, runReleasePipeline, runSafeBuild, saveSnapshot,
|
|
861
|
+
export { type AuditSummary, type BuildConfig, type BuildResult, CHECKS_CONCURRENCY, type ChangelogGenerator, type CheckId, type CheckResult, type CheckResultDetails, type CleanInstallResult, type CustomCheckConfig, DEFAULT_ROOT_CHANGELOG_PATH, DEFAULT_TAG_PATTERN, type FlowConfig, type PackagePublisher, type PackageVersion, type PackagesFilter, type PipelineOptions, type PipelineResult, type PlannerOptions, type PluginLogger, type PublishResult, type PublishablePackage, type ReleaseChannel, type ReleaseConfig, type ReleaseContext, type ReleasePlan, type ReleaseReport, type ReleaseResult, type ReleaseShell, type ReleaseStage, type RollbackSnapshot, type StrategyOptions, type VerifyResult, type VersionBump, type VersionStrategy, applyCanarySuffix, applyVersionStrategy, buildPackages, buildReleaseTag, commitAndTagRelease, copyChangelogToPackages, createExecaShellAdapter, discoverCurrentPackages, findForbiddenDependencyProtocols, isBuildCommand, isVersionPublished, matchesPackagePattern, mergeConfigWithFlow, mergeRootChangelog, planRelease, renderJson, renderMarkdown, renderText, resolveFlowFromTag, resolvePublishRegistry, resolvePublishTag, resolveRootChangelogRelPath, resolveScopePath, restoreSnapshot, runReleaseChecks, runReleasePipeline, runSafeBuild, saveSnapshot, updatePackageVersion, updatePackageVersions, verifyAgainstRegistry, verifyCleanInstall, verifyExtractedTarball, verifyPackage, verifyPackages };
|
package/dist/index.js
CHANGED
|
@@ -6,9 +6,9 @@ import semver2 from 'semver';
|
|
|
6
6
|
import globby from 'globby';
|
|
7
7
|
import { discoverSubRepoPaths, useEnv } from '@kb-labs/sdk';
|
|
8
8
|
import { execa } from 'execa';
|
|
9
|
-
import { spawn, spawnSync } from 'child_process';
|
|
10
9
|
import { tmpdir } from 'os';
|
|
11
10
|
import { randomBytes } from 'crypto';
|
|
11
|
+
import { spawnSync } from 'child_process';
|
|
12
12
|
|
|
13
13
|
// src/planner.ts
|
|
14
14
|
function applyVersionStrategy(packages, options) {
|
|
@@ -24,12 +24,16 @@ function applyLockstep(packages) {
|
|
|
24
24
|
if (packages.length === 0) {
|
|
25
25
|
return packages;
|
|
26
26
|
}
|
|
27
|
-
const
|
|
28
|
-
if (
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
const pinned = packages.filter((p) => p.isPublished || p.versionPinned);
|
|
28
|
+
if (pinned.length > 0) {
|
|
29
|
+
const resolved = [...new Set(pinned.map((p) => p.nextVersion))];
|
|
30
|
+
if (resolved.length > 1) {
|
|
31
|
+
const detail = pinned.map((p) => `${p.name}@${p.nextVersion}`).join(", ");
|
|
32
|
+
throw new Error(
|
|
33
|
+
`Lockstep release has conflicting already-resolved versions: ${resolved.join(", ")} (${detail}). Reconcile package.json versions before releasing.`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const sharedVersion = resolved[0];
|
|
33
37
|
return packages.map((pkg) => ({ ...pkg, nextVersion: sharedVersion }));
|
|
34
38
|
}
|
|
35
39
|
const maxBump = getMaxBump(packages);
|
|
@@ -214,16 +218,19 @@ async function planRelease(options) {
|
|
|
214
218
|
})() : null;
|
|
215
219
|
if (headVersion && headVersion !== pkg.currentVersion) {
|
|
216
220
|
const alreadyPublished = await isVersionPublished(pkg.name, pkg.currentVersion, registry);
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
221
|
+
planPackages.push({
|
|
222
|
+
...pkg,
|
|
223
|
+
gitRoot,
|
|
224
|
+
nextVersion: pkg.currentVersion,
|
|
225
|
+
bump: detectBumpType(headVersion, pkg.currentVersion),
|
|
226
|
+
isPublished: alreadyPublished,
|
|
227
|
+
// Mark the version as final so lockstep/adaptive resolution below
|
|
228
|
+
// doesn't re-derive (and thus re-bump) it. `isPublished` alone is not
|
|
229
|
+
// enough to signal this: the bump can legitimately be on disk but not
|
|
230
|
+
// yet published — exactly the `release:version` → `release:git` case.
|
|
231
|
+
versionPinned: true
|
|
232
|
+
});
|
|
233
|
+
continue;
|
|
227
234
|
}
|
|
228
235
|
const nextVersion = await computeNextVersion(
|
|
229
236
|
pkg.path,
|
|
@@ -256,7 +263,9 @@ async function planRelease(options) {
|
|
|
256
263
|
strategy: config.strategy || "semver",
|
|
257
264
|
registry: config.registry || "https://registry.npmjs.org",
|
|
258
265
|
rollbackEnabled: config.rollback?.enabled ?? true,
|
|
259
|
-
channel
|
|
266
|
+
channel,
|
|
267
|
+
flow: options.flow,
|
|
268
|
+
scope
|
|
260
269
|
};
|
|
261
270
|
}
|
|
262
271
|
function mapBumpStrategyToVersionStrategy(bumpStrategy) {
|
|
@@ -625,6 +634,12 @@ function mergeChangelogBlock(existingChangelog, newBlock, versionPattern) {
|
|
|
625
634
|
}
|
|
626
635
|
return newBlock + (existingChangelog ? "\n" + existingChangelog : "");
|
|
627
636
|
}
|
|
637
|
+
function removeHistoricalDuplicateBullets(existingChangelog, newBlock) {
|
|
638
|
+
const historicalBullets = new Set(
|
|
639
|
+
existingChangelog.split("\n").map((line) => line.trim()).filter((line) => line.startsWith("- "))
|
|
640
|
+
);
|
|
641
|
+
return newBlock.split("\n").filter((line) => !line.trim().startsWith("- ") || !historicalBullets.has(line.trim())).join("\n");
|
|
642
|
+
}
|
|
628
643
|
var DEFAULT_ROOT_CHANGELOG_PATH = ".kb/release/CHANGELOG.md";
|
|
629
644
|
function resolveRootChangelogRelPath(outputPath) {
|
|
630
645
|
return outputPath && outputPath.trim().length > 0 ? outputPath : DEFAULT_ROOT_CHANGELOG_PATH;
|
|
@@ -647,7 +662,8 @@ async function mergeRootChangelog(options) {
|
|
|
647
662
|
existingChangelog = await readFile(changelogPath, "utf-8");
|
|
648
663
|
} catch {
|
|
649
664
|
}
|
|
650
|
-
const
|
|
665
|
+
const deduplicatedBlock = versionPattern.test(existingChangelog) ? changelog.trim() : removeHistoricalDuplicateBullets(existingChangelog, changelog.trim());
|
|
666
|
+
const updatedChangelog = mergeChangelogBlock(existingChangelog, deduplicatedBlock, versionPattern);
|
|
651
667
|
await mkdir(dirname(changelogPath), { recursive: true });
|
|
652
668
|
await writeFile(changelogPath, updatedChangelog.trim() + "\n", "utf-8");
|
|
653
669
|
}
|
|
@@ -1101,7 +1117,7 @@ async function buildPackages(packages, options) {
|
|
|
1101
1117
|
const ordered = topoSortForBuild(packages);
|
|
1102
1118
|
for (const pkg of ordered) {
|
|
1103
1119
|
options?.logger?.info?.(`Building ${pkg.name}...`);
|
|
1104
|
-
const result = await runSafeBuild(pkg.path, pkg.name);
|
|
1120
|
+
const result = await runSafeBuild(pkg.path, pkg.name, options.shell);
|
|
1105
1121
|
results.push({ ...result, name: pkg.name });
|
|
1106
1122
|
options?.onProgress?.(pkg.name, { ...result, name: pkg.name });
|
|
1107
1123
|
if (!result.success) {
|
|
@@ -1112,25 +1128,25 @@ async function buildPackages(packages, options) {
|
|
|
1112
1128
|
}
|
|
1113
1129
|
return results;
|
|
1114
1130
|
}
|
|
1115
|
-
async function runSafeBuild(packagePath, packageName) {
|
|
1131
|
+
async function runSafeBuild(packagePath, packageName, shell) {
|
|
1116
1132
|
const usesTsup = existsSync(join(packagePath, "tsup.config.ts")) || existsSync(join(packagePath, "tsup.config.js"));
|
|
1117
1133
|
if (usesTsup) {
|
|
1118
|
-
return runTsupSafeBuild(packagePath, packageName);
|
|
1134
|
+
return runTsupSafeBuild(packagePath, packageName, shell);
|
|
1119
1135
|
}
|
|
1120
|
-
return runDirectBuild(packagePath, packageName);
|
|
1136
|
+
return runDirectBuild(packagePath, packageName, shell);
|
|
1121
1137
|
}
|
|
1122
1138
|
function isBuildCommand(command, args) {
|
|
1123
1139
|
const full = [command, ...args ?? []].join(" ").trim();
|
|
1124
1140
|
return /\b(pnpm|npm|yarn)\s+(run\s+)?build\b/.test(full);
|
|
1125
1141
|
}
|
|
1126
|
-
async function runTsupSafeBuild(packagePath, packageName) {
|
|
1142
|
+
async function runTsupSafeBuild(packagePath, packageName, shell) {
|
|
1127
1143
|
const startTime = Date.now();
|
|
1128
1144
|
const buildId = randomBytes(6).toString("hex");
|
|
1129
1145
|
const tempDir = join(tmpdir(), `kb-release-build-${buildId}`);
|
|
1130
1146
|
const distDir = join(packagePath, "dist");
|
|
1131
1147
|
const backupDir = join(packagePath, `dist.bak-${buildId}`);
|
|
1132
1148
|
try {
|
|
1133
|
-
const buildResult = await
|
|
1149
|
+
const buildResult = await executeCommand(shell, "npx", ["tsup", "-d", tempDir], packagePath, 5 * 60 * 1e3);
|
|
1134
1150
|
if (!buildResult.success) {
|
|
1135
1151
|
await rm(tempDir, { recursive: true, force: true }).catch(() => {
|
|
1136
1152
|
});
|
|
@@ -1164,54 +1180,25 @@ async function runTsupSafeBuild(packagePath, packageName) {
|
|
|
1164
1180
|
};
|
|
1165
1181
|
}
|
|
1166
1182
|
}
|
|
1167
|
-
async function runDirectBuild(packagePath, packageName) {
|
|
1168
|
-
const result = await
|
|
1183
|
+
async function runDirectBuild(packagePath, packageName, shell) {
|
|
1184
|
+
const result = await executeCommand(shell, "pnpm", ["run", "build"], packagePath, 5 * 60 * 1e3, { NODE_ENV: "production" });
|
|
1169
1185
|
return { ...result, name: packageName };
|
|
1170
1186
|
}
|
|
1171
|
-
function
|
|
1187
|
+
async function executeCommand(shell, command, args, cwd, timeoutMs, env) {
|
|
1172
1188
|
const startTime = Date.now();
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
});
|
|
1185
|
-
child.stderr?.on("data", (data) => {
|
|
1186
|
-
stderr += data.toString();
|
|
1187
|
-
});
|
|
1188
|
-
child.on("close", (code) => {
|
|
1189
|
-
const exitCode = code ?? 1;
|
|
1190
|
-
const durationMs = Date.now() - startTime;
|
|
1191
|
-
if (exitCode === 0) {
|
|
1192
|
-
resolve3({ success: true, durationMs, stdout, stderr, exitCode });
|
|
1193
|
-
return;
|
|
1194
|
-
}
|
|
1195
|
-
const combined = (stderr || stdout).trim();
|
|
1196
|
-
const tail = combined.split("\n").slice(-30).join("\n");
|
|
1197
|
-
resolve3({
|
|
1198
|
-
success: false,
|
|
1199
|
-
error: tail || `Build failed with exit code ${exitCode}`,
|
|
1200
|
-
durationMs,
|
|
1201
|
-
stdout,
|
|
1202
|
-
stderr,
|
|
1203
|
-
exitCode
|
|
1204
|
-
});
|
|
1205
|
-
});
|
|
1206
|
-
child.on("error", (err) => {
|
|
1207
|
-
resolve3({ success: false, error: err.message, durationMs: Date.now() - startTime, stdout: "", stderr: "", exitCode: 1 });
|
|
1208
|
-
});
|
|
1209
|
-
setTimeout(() => {
|
|
1210
|
-
child.kill();
|
|
1211
|
-
resolve3({ success: false, error: `Timed out after ${timeoutMs / 1e3}s`, durationMs: Date.now() - startTime, stdout: "", stderr: "", exitCode: 1 });
|
|
1212
|
-
}, timeoutMs);
|
|
1213
|
-
});
|
|
1189
|
+
const result = await shell.exec(command, args, { cwd, timeout: timeoutMs, ...env ? { env } : {} });
|
|
1190
|
+
const exitCode = result.code;
|
|
1191
|
+
const combined = (result.stderr || result.stdout).trim();
|
|
1192
|
+
return {
|
|
1193
|
+
success: result.ok,
|
|
1194
|
+
error: result.ok ? void 0 : combined.split("\n").slice(-30).join("\n") || `Build failed with exit code ${exitCode}`,
|
|
1195
|
+
durationMs: Date.now() - startTime,
|
|
1196
|
+
stdout: result.stdout,
|
|
1197
|
+
stderr: result.stderr,
|
|
1198
|
+
exitCode
|
|
1199
|
+
};
|
|
1214
1200
|
}
|
|
1201
|
+
var CHECKS_CONCURRENCY = 2;
|
|
1215
1202
|
async function runReleaseChecks(checks, options) {
|
|
1216
1203
|
const results = [];
|
|
1217
1204
|
for (const check of checks) {
|
|
@@ -1234,33 +1221,32 @@ async function runSingleCheck(check, options) {
|
|
|
1234
1221
|
} else {
|
|
1235
1222
|
pathsToRun = options.packagePaths.length > 0 ? options.packagePaths : [options.repoRoot];
|
|
1236
1223
|
}
|
|
1237
|
-
const CONCURRENCY = 8;
|
|
1238
1224
|
const resolvedArgs = (check.args ?? []).map(
|
|
1239
1225
|
(arg) => arg.match(/\.(sh|js|ts|mjs|cjs)$/) ? join(options.repoRoot, arg) : arg
|
|
1240
1226
|
);
|
|
1241
|
-
const fullCommand = [check.command, ...resolvedArgs].join(" ");
|
|
1242
1227
|
const timeoutMs = check.timeoutMs ?? 12e4;
|
|
1243
1228
|
async function runForPath(pkgPath) {
|
|
1244
|
-
const
|
|
1245
|
-
const
|
|
1229
|
+
const startedAt = Date.now();
|
|
1230
|
+
const result = await options.shell.exec(check.command, resolvedArgs, { cwd: pkgPath, timeout: timeoutMs });
|
|
1231
|
+
const ok = evaluateParser(check, result.stdout, result.stderr, result.code);
|
|
1246
1232
|
return {
|
|
1247
1233
|
path: pkgPath,
|
|
1248
1234
|
ok,
|
|
1249
|
-
durationMs:
|
|
1235
|
+
durationMs: Date.now() - startedAt,
|
|
1250
1236
|
details: {
|
|
1251
1237
|
packagePath: pkgPath,
|
|
1252
1238
|
stdout: result.stdout || void 0,
|
|
1253
1239
|
stderr: result.stderr || void 0,
|
|
1254
|
-
exitCode: result.
|
|
1255
|
-
error:
|
|
1240
|
+
exitCode: result.code,
|
|
1241
|
+
error: !ok ? `exit code ${result.code}` : void 0
|
|
1256
1242
|
}
|
|
1257
1243
|
};
|
|
1258
1244
|
}
|
|
1259
1245
|
let pkgResults;
|
|
1260
1246
|
if (runIn === "perPackage" && pathsToRun.length > 1) {
|
|
1261
1247
|
pkgResults = [];
|
|
1262
|
-
for (let i = 0; i < pathsToRun.length; i +=
|
|
1263
|
-
const batch = pathsToRun.slice(i, i +
|
|
1248
|
+
for (let i = 0; i < pathsToRun.length; i += CHECKS_CONCURRENCY) {
|
|
1249
|
+
const batch = pathsToRun.slice(i, i + CHECKS_CONCURRENCY);
|
|
1264
1250
|
pkgResults.push(...await Promise.all(batch.map(runForPath)));
|
|
1265
1251
|
}
|
|
1266
1252
|
} else {
|
|
@@ -1273,6 +1259,7 @@ async function runSingleCheck(check, options) {
|
|
|
1273
1259
|
return {
|
|
1274
1260
|
id: check.id,
|
|
1275
1261
|
ok: allOk,
|
|
1262
|
+
optional: check.optional,
|
|
1276
1263
|
details: firstFailure,
|
|
1277
1264
|
hint: check.optional ? "optional" : void 0,
|
|
1278
1265
|
timingMs: totalDurationMs,
|
|
@@ -1528,11 +1515,25 @@ async function verifyOneAgainstRegistry(pkg, registry, timeout, retries, retryDe
|
|
|
1528
1515
|
try {
|
|
1529
1516
|
mkdirSync(tmpDir, { recursive: true });
|
|
1530
1517
|
const spec = `${pkg.name}@${pkg.version}`;
|
|
1531
|
-
|
|
1518
|
+
let packResult = spawnSync(
|
|
1532
1519
|
"npm",
|
|
1533
1520
|
["pack", spec, "--registry", registry, "--pack-destination", tmpDir],
|
|
1534
1521
|
{ stdio: "pipe", timeout }
|
|
1535
1522
|
);
|
|
1523
|
+
for (let attempt = 0; packResult.status !== 0 && attempt < retries; attempt++) {
|
|
1524
|
+
const delay = retryDelaysMs[Math.min(attempt, retryDelaysMs.length - 1)];
|
|
1525
|
+
logger?.warn?.(
|
|
1526
|
+
`${spec} is visible on ${registry} but \`npm pack\` still can't fetch it (attempt ${attempt + 1}/${retries + 1}), retrying in ${(delay / 1e3).toFixed(0)}s \u2014 likely tarball CDN propagation lag`
|
|
1527
|
+
);
|
|
1528
|
+
await new Promise((r) => {
|
|
1529
|
+
setTimeout(r, delay);
|
|
1530
|
+
});
|
|
1531
|
+
packResult = spawnSync(
|
|
1532
|
+
"npm",
|
|
1533
|
+
["pack", spec, "--registry", registry, "--pack-destination", tmpDir],
|
|
1534
|
+
{ stdio: "pipe", timeout }
|
|
1535
|
+
);
|
|
1536
|
+
}
|
|
1536
1537
|
if (packResult.status !== 0) {
|
|
1537
1538
|
const stderr = packResult.stderr?.toString().trim();
|
|
1538
1539
|
issues.push(`Could not pull ${spec} back from ${registry} for verification${stderr ? `: ${stderr}` : ""}`);
|
|
@@ -1662,7 +1663,8 @@ async function _runPipeline(ctx) {
|
|
|
1662
1663
|
changelogGen,
|
|
1663
1664
|
logger,
|
|
1664
1665
|
startTime,
|
|
1665
|
-
progress
|
|
1666
|
+
progress,
|
|
1667
|
+
options
|
|
1666
1668
|
} = ctx;
|
|
1667
1669
|
const channel = config.channel ?? "stable";
|
|
1668
1670
|
const publishTag = resolvePublishTag(config, channel);
|
|
@@ -1746,7 +1748,8 @@ async function _runPipeline(ctx) {
|
|
|
1746
1748
|
repoRoot,
|
|
1747
1749
|
packagePaths,
|
|
1748
1750
|
scopePath: scopeCwd,
|
|
1749
|
-
logger
|
|
1751
|
+
logger,
|
|
1752
|
+
shell: options.shell
|
|
1750
1753
|
});
|
|
1751
1754
|
const failed = checkResults.filter((r) => !r.ok && r.hint !== "optional");
|
|
1752
1755
|
if (failed.length > 0) {
|
|
@@ -1789,7 +1792,7 @@ async function _runPipeline(ctx) {
|
|
|
1789
1792
|
}
|
|
1790
1793
|
if (!skipBuild && !dryRun) {
|
|
1791
1794
|
progress("versioning", `Building ${plan.packages.length} package(s)...`);
|
|
1792
|
-
const buildResults = await buildPackages(plan.packages, { logger });
|
|
1795
|
+
const buildResults = await buildPackages(plan.packages, { logger, shell: options.shell });
|
|
1793
1796
|
const buildFailed = buildResults.filter((r) => !r.success);
|
|
1794
1797
|
if (buildFailed.length > 0) {
|
|
1795
1798
|
await restoreSnapshot(repoRoot);
|
|
@@ -2090,6 +2093,6 @@ async function resolveScopePath(repoRoot, scope) {
|
|
|
2090
2093
|
return join(repoRoot, scope);
|
|
2091
2094
|
}
|
|
2092
2095
|
|
|
2093
|
-
export { DEFAULT_ROOT_CHANGELOG_PATH, DEFAULT_TAG_PATTERN, applyCanarySuffix, applyVersionStrategy, buildPackages, buildReleaseTag, commitAndTagRelease, copyChangelogToPackages, createExecaShellAdapter, discoverCurrentPackages, findForbiddenDependencyProtocols, isBuildCommand, isVersionPublished, matchesPackagePattern, mergeConfigWithFlow, mergeRootChangelog, planRelease, renderJson, renderMarkdown, renderText, resolveFlowFromTag, resolvePublishRegistry, resolvePublishTag, resolveRootChangelogRelPath, resolveScopePath, restoreSnapshot, runReleaseChecks, runReleasePipeline, runSafeBuild, saveSnapshot,
|
|
2096
|
+
export { CHECKS_CONCURRENCY, DEFAULT_ROOT_CHANGELOG_PATH, DEFAULT_TAG_PATTERN, applyCanarySuffix, applyVersionStrategy, buildPackages, buildReleaseTag, commitAndTagRelease, copyChangelogToPackages, createExecaShellAdapter, discoverCurrentPackages, findForbiddenDependencyProtocols, isBuildCommand, isVersionPublished, matchesPackagePattern, mergeConfigWithFlow, mergeRootChangelog, planRelease, renderJson, renderMarkdown, renderText, resolveFlowFromTag, resolvePublishRegistry, resolvePublishTag, resolveRootChangelogRelPath, resolveScopePath, restoreSnapshot, runReleaseChecks, runReleasePipeline, runSafeBuild, saveSnapshot, updatePackageVersion, updatePackageVersions, verifyAgainstRegistry, verifyCleanInstall, verifyExtractedTarball, verifyPackage, verifyPackages };
|
|
2094
2097
|
//# sourceMappingURL=index.js.map
|
|
2095
2098
|
//# sourceMappingURL=index.js.map
|