@rightkit/release 0.6.10 → 0.6.12
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 +7 -5
- package/admission-files.mjs +3 -0
- package/admission.mjs +2 -2
- package/advisory-exceptions.mjs +41 -5
- package/android-play-upload.mjs +16 -15
- package/app-check.mjs +13 -9
- package/bin/rightkit-gate.mjs +772 -355
- package/broker-pins.mjs +152 -0
- package/build-release.mjs +80 -27
- package/cargo-ledger.mjs +62 -0
- package/cargo-target-shim.mjs +98 -26
- package/cli/right-release.mjs +28 -4
- package/clippy-equivalence.mjs +202 -0
- package/clippy-route.mjs +543 -0
- package/committed-source.mjs +39 -5
- package/crate-workspaces.mjs +87 -0
- package/create-mac-updater.mjs +14 -2
- package/deterministic-scans.mjs +196 -21
- package/development.mjs +13 -4
- package/direct-receipt.mjs +135 -0
- package/door-policy.mjs +10 -0
- package/door.mjs +6 -6
- package/freshness-census.mjs +257 -0
- package/gate-stages.mjs +76 -10
- package/hook-retirement.mjs +65 -0
- package/init-command.mjs +1 -1
- package/inventory-check.mjs +11 -8
- package/ios-upload.mjs +20 -15
- package/local-publish.mjs +77 -41
- package/local-qualify.mjs +5 -3
- package/local-runtime.mjs +5 -4
- package/mac-package-recipe.mjs +4 -1
- package/mirror-root-artifact.mjs +18 -5
- package/ownership-class-rules.mjs +1 -1
- package/ownership-evidence.mjs +37 -13
- package/ownership-hooks.mjs +20 -59
- package/ownership-lockfiles.mjs +14 -1
- package/ownership-policy-bundle.mjs +3 -2
- package/ownership-staged.mjs +2 -1
- package/ownership.mjs +24 -0
- package/package-recipe-targets.mjs +35 -6
- package/package.json +1 -1
- package/pipeline-admission.mjs +4 -4
- package/preflight.mjs +27 -4
- package/publish-cargo.mjs +4 -3
- package/recipe-build.mjs +38 -14
- package/release-artifact-path.mjs +341 -0
- package/release-invocation.mjs +8 -1
- package/release-qa-command.mjs +25 -9
- package/release-source-brand.mjs +17 -0
- package/release-source-identity.mjs +171 -0
- package/release.mjs +44 -17
- package/rightkit-versions.json +63 -42
- package/runtime-budgets.mjs +6 -2
- package/scan-digest.mjs +71 -5
- package/sign-updater.mjs +6 -3
- package/snapshot-broker.mjs +172 -0
- package/snapshot-check.mjs +12 -6
- package/snapshot-request.mjs +207 -5
- package/snapshot.mjs +123 -10
- package/source-split.mjs +73 -0
- package/stage-commands.mjs +2 -2
- package/stage-ledger.mjs +204 -0
- package/stage-sidecar-command.mjs +5 -1
- package/stage-sidecar.mjs +100 -20
- package/swap-helper-bundle.mjs +5 -2
- package/unit-gate.mjs +45 -3
- package/web-build.mjs +6 -4
- package/win-package-recipe.mjs +20 -7
package/release.mjs
CHANGED
|
@@ -14,6 +14,8 @@ import { assertQaAdoption, assertQaBackdoorContract } from "./qa-contract.mjs";
|
|
|
14
14
|
import { assertLegalReleaseContract } from "./legal-contract.mjs";
|
|
15
15
|
import { DECLARED_UNRELATED_POLICY, declaredUnrelatedRefusal, releaseArtifactPaths } from "./hosted-workflow-policy.mjs";
|
|
16
16
|
import { assertNativeIosPrepareHasManifest, assertPrimaryReleaseCheckout, dirtyBuildInputs, resolveReleaseBuildInputs } from "./release-invocation.mjs";
|
|
17
|
+
import { resolveReleaseSource, sourceRootOf } from "./release-source-identity.mjs";
|
|
18
|
+
import { ArtifactPathError, assertSplitCommandPaths, releaseCommandSteps, resolveArtifactPath, splitArtifactContext } from "./release-artifact-path.mjs";
|
|
17
19
|
import { declaredCargoManifest, hasDefaultTauriManifest, resolveNativeCargoLayout } from "./native-cargo-layout.mjs";
|
|
18
20
|
import {
|
|
19
21
|
canonicalPackageIdentity,
|
|
@@ -275,10 +277,17 @@ const nativeFinalizer = resolveNativeFinalizerConfig(nativeAssembly);
|
|
|
275
277
|
// state root and admission record; a snapshot from anywhere else is refused. The standalone doctor resolves live.
|
|
276
278
|
const rightKitSnapshotFile = process.env[SNAPSHOT_ENV] || null;
|
|
277
279
|
let rightKitResolution = null; // null when the registry resolution failed (recorded as the `rightkit-registry` finding)
|
|
280
|
+
// The worker of a door split (row 7.04): its cwd is the snapshot, which has no git directory. Its commit and source root are the selected
|
|
281
|
+
// commit's and the snapshot's (release-source-identity.mjs); the checkout route reads them from git as before.
|
|
282
|
+
let workerSource = null;
|
|
283
|
+
let artifactPathContext = null; // the declared-artifact resolver's context (artifactContext, row 7.04c)
|
|
284
|
+
if (!opts.doctor && process.env.RK_GATE_CHECKOUT) {
|
|
285
|
+
try { workerSource = resolveReleaseSource({ cwd: process.cwd() }); } catch (error) { fail(`${error.code ?? "RK_SOURCE_IDENTITY"}: ${error.message}`); }
|
|
286
|
+
}
|
|
278
287
|
try {
|
|
279
288
|
const lockInventory = () => {
|
|
280
289
|
try {
|
|
281
|
-
const repoRoot = git(root, ["rev-parse", "--show-toplevel"]);
|
|
290
|
+
const repoRoot = workerSource ? sourceRootOf(workerSource) : git(root, ["rev-parse", "--show-toplevel"]);
|
|
282
291
|
let canonicalTarget = config.targets?.[opts.platform];
|
|
283
292
|
try { canonicalTarget = expandPackageRecipeTarget(canonicalTarget, { platform: opts.platform, appRoot: root, config }); } catch { /* reported later */ }
|
|
284
293
|
const inputs = resolveReleaseBuildInputs({ repoRoot, appRoot: root, configPath, config, target: canonicalTarget });
|
|
@@ -292,7 +301,7 @@ try {
|
|
|
292
301
|
if (!rightKitSnapshotFile) throw new RightKitRegistryError("no-admission", "no admitted RightKit registry snapshot was handed to the release worker; run it through `right-release build`, which admits the release");
|
|
293
302
|
const stateRoot = process.env.RIGHT_RELEASE_STATE_ROOT;
|
|
294
303
|
if (!stateRoot) throw new RightKitRegistryError("no-admission", "RIGHT_RELEASE_STATE_ROOT is not set; the admitted RightKit registry snapshot cannot be located");
|
|
295
|
-
const commit = git(root, ["rev-parse", "HEAD"]);
|
|
304
|
+
const commit = workerSource ? workerSource.commit : git(root, ["rev-parse", "HEAD"]);
|
|
296
305
|
boundSnapshot = loadAdmittedSnapshot(stateRoot, { releaseId: `${config.app}-${config.version}-${commit.slice(0, 8)}`, commit, platform: opts.platform, snapshotFile: rightKitSnapshotFile });
|
|
297
306
|
}
|
|
298
307
|
rightKitResolution = await prepareRightKitResolution({
|
|
@@ -348,6 +357,12 @@ await check("target", [], () => {
|
|
|
348
357
|
if (!expanded) throw new Error(`${config.app ?? "app"} has no ${opts.platform} release target`);
|
|
349
358
|
target = expanded;
|
|
350
359
|
});
|
|
360
|
+
// Row 7.04c (R-T1, R-T4): in a door split each Cargo manifest's target is bound now, once, before any step runs, and no step the app owns may name
|
|
361
|
+
// a target-relative path (the snapshot has no target directory). Checkout mode checks nothing here.
|
|
362
|
+
await check("split-artifact-paths", ["target"], () => {
|
|
363
|
+
if (!workerSource) return;
|
|
364
|
+
assertSplitCommandPaths(releaseCommandSteps({ target, config, root }), artifactContext());
|
|
365
|
+
});
|
|
351
366
|
const legalCheck = await check("legal-contract", [], () => (config.legal
|
|
352
367
|
? assertLegalReleaseContract(root, config.legal, config.app ?? path.basename(root), opts.platform)
|
|
353
368
|
: null));
|
|
@@ -636,7 +651,7 @@ if (opts.platform === "win" && target.signingContract === MSIX_SIGNING_CONTRACT)
|
|
|
636
651
|
// writes the App Installer route and the seal record. Never a second signer.
|
|
637
652
|
await runCommand(target.prePackage, root);
|
|
638
653
|
// Raw payload scan BEFORE the package is packed (a packed MSIX is only readable through its ZIP directory).
|
|
639
|
-
assertNoQaControlBinaries("msix staged payload", [
|
|
654
|
+
assertNoQaControlBinaries("msix staged payload", [resolveDeclaredPath(root, target.msix.stageDir)], { requireBinary: true, prePack: true });
|
|
640
655
|
const options = msixBuildOptions({ root, target, app: config.app, dryRun: opts.dryRun, receipts: {
|
|
641
656
|
pe: windowsReceiptPath(root, "raw-exe"), msix: windowsReceiptPath(root, "installer"),
|
|
642
657
|
dir: path.dirname(windowsReceiptPath(root, "raw-exe")) } });
|
|
@@ -645,7 +660,7 @@ if (opts.platform === "win" && target.signingContract === MSIX_SIGNING_CONTRACT)
|
|
|
645
660
|
// Second layer: read the finished package through its ZIP central directory (stored and deflate entries).
|
|
646
661
|
if (!built.dryRun) assertNoQaControlBinaries("msix package", [options.out], { requireBinary: true });
|
|
647
662
|
} else if (opts.platform === "win") {
|
|
648
|
-
const rawFiles = target.sign.prePackageFiles.map((p) =>
|
|
663
|
+
const rawFiles = target.sign.prePackageFiles.map((p) => resolveDeclaredPath(root, p));
|
|
649
664
|
const sidecarPlan = await prepareMediaSidecar(root);
|
|
650
665
|
const externalPlan = await prepareExternalBin(root);
|
|
651
666
|
await runCommand(target.prePackage, root);
|
|
@@ -894,15 +909,25 @@ function assertNoWebBundleMocksInFrontend(phase, { required }) {
|
|
|
894
909
|
} catch (error) { fail(error.message); }
|
|
895
910
|
}
|
|
896
911
|
|
|
912
|
+
// Row 7.04c (R-T2): one resolver for every declared artifact path. Checkout mode is the historical rule, byte for byte (the app root, then
|
|
913
|
+
// RIGHT_RELEASE_ARTIFACT_DIR); a door split maps a target-prefixed path to its bound Cargo target and never reads the checkout.
|
|
914
|
+
function artifactContext() {
|
|
915
|
+
artifactPathContext ??= splitArtifactContext({
|
|
916
|
+
cwd: root, env: process.env, nativeLayout, config, target: config.targets?.[opts.platform],
|
|
917
|
+
...(workerSource?.mode === "snapshot" ? { snapshotRoot: workerSource.snapshot } : {}),
|
|
918
|
+
});
|
|
919
|
+
return artifactPathContext;
|
|
920
|
+
}
|
|
921
|
+
|
|
897
922
|
function resolveReleaseArtifactPath(root, declared) {
|
|
898
|
-
|
|
899
|
-
if (
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
return
|
|
923
|
+
try { return resolveArtifactPath(declared, artifactContext()); }
|
|
924
|
+
catch (error) { if (error instanceof ArtifactPathError) fail(error.message); throw error; }
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/** A declared path that never fell back to the managed artifact directory (a staged payload, a raw EXE): the app root, or in a split the same resolver. */
|
|
928
|
+
function resolveDeclaredPath(root, declared) {
|
|
929
|
+
const context = artifactContext();
|
|
930
|
+
return context.mode === "split" ? resolveReleaseArtifactPath(root, declared) : path.resolve(root, declared);
|
|
906
931
|
}
|
|
907
932
|
|
|
908
933
|
function fail(message) {
|
|
@@ -1042,11 +1067,13 @@ function nativeSignedArtifacts(files, root) {
|
|
|
1042
1067
|
return values.map((value) => {
|
|
1043
1068
|
const declared = typeof value === "string" ? value : value?.path ?? value?.file;
|
|
1044
1069
|
if (!declared) fail("native finalizer signed artifact path is missing");
|
|
1045
|
-
const absolute =
|
|
1046
|
-
|
|
1070
|
+
const absolute = resolveDeclaredPath(root, declared);
|
|
1071
|
+
// A split's bound target lies outside the app: its absolute path is the evidence there.
|
|
1072
|
+
const evidencePath = () => { const relative = path.relative(root, absolute).replaceAll("\\", "/"); return relative.startsWith("..") ? absolute.replaceAll("\\", "/") : relative; };
|
|
1073
|
+
if (opts.dryRun) return { path: evidencePath() };
|
|
1047
1074
|
if (!existsSync(absolute)) fail(`native finalizer signed artifact missing: ${absolute}`);
|
|
1048
1075
|
return {
|
|
1049
|
-
path:
|
|
1076
|
+
path: evidencePath(),
|
|
1050
1077
|
sha256: createHash("sha256").update(readFileSync(absolute)).digest("hex"),
|
|
1051
1078
|
sizeBytes: readFileSync(absolute).length,
|
|
1052
1079
|
};
|
|
@@ -1080,7 +1107,7 @@ function nativeArchiveCandidates({ root, target, nativeAssembly }) {
|
|
|
1080
1107
|
...(target.installer?.artifacts ?? []).map((artifact) => artifact.file),
|
|
1081
1108
|
...(target.updater?.artifacts ?? []).map((artifact) => artifact.file),
|
|
1082
1109
|
].filter((value) => typeof value === "string" && value.trim());
|
|
1083
|
-
return [...new Set(declared.map((value) =>
|
|
1110
|
+
return [...new Set(declared.map((value) => resolveDeclaredPath(root, value)))];
|
|
1084
1111
|
}
|
|
1085
1112
|
|
|
1086
1113
|
function nativeFinalizerOutputPath({ finalizer, target, root }) {
|
|
@@ -1906,7 +1933,7 @@ async function verifyWindowsEmbedding({ root, target, files, markers }) {
|
|
|
1906
1933
|
console.log("dry-run: verify installer embeds the signed raw EXE");
|
|
1907
1934
|
return;
|
|
1908
1935
|
}
|
|
1909
|
-
const rawFile =
|
|
1936
|
+
const rawFile = resolveDeclaredPath(root, target.sign.prePackageFiles[0]);
|
|
1910
1937
|
const rawReceiptPath = windowsReceiptPath(root, "raw-exe");
|
|
1911
1938
|
let rawReceipt;
|
|
1912
1939
|
try { rawReceipt = JSON.parse(readFileSync(rawReceiptPath, "utf8")); } catch { fail(`missing raw EXE signing receipt: ${rawReceiptPath}`); }
|
package/rightkit-versions.json
CHANGED
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"@rightkit/outdated": "0.3.0",
|
|
30
30
|
"@rightkit/pdf-ui": "0.2.0",
|
|
31
31
|
"@rightkit/platform-ui": "0.4.0",
|
|
32
|
-
"@rightkit/qa": "0.6.
|
|
32
|
+
"@rightkit/qa": "0.6.2",
|
|
33
33
|
"@rightkit/qa-chrome": "0.1.12",
|
|
34
34
|
"@rightkit/react-shell": "0.7.2",
|
|
35
|
-
"@rightkit/release": "0.6.
|
|
35
|
+
"@rightkit/release": "0.6.12",
|
|
36
36
|
"@rightkit/settings-ui": "0.7.0",
|
|
37
37
|
"@rightkit/tauri": "0.3.0",
|
|
38
38
|
"@rightkit/tauri-shell": "0.1.3",
|
|
@@ -236,7 +236,8 @@
|
|
|
236
236
|
"0.4.9",
|
|
237
237
|
"0.5.0",
|
|
238
238
|
"0.5.1",
|
|
239
|
-
"0.5.2"
|
|
239
|
+
"0.5.2",
|
|
240
|
+
"0.6.1"
|
|
240
241
|
],
|
|
241
242
|
"@rightkit/qa-chrome": [
|
|
242
243
|
"0.1.0",
|
|
@@ -376,7 +377,9 @@
|
|
|
376
377
|
"0.6.5",
|
|
377
378
|
"0.6.6",
|
|
378
379
|
"0.6.7",
|
|
379
|
-
"0.6.8"
|
|
380
|
+
"0.6.8",
|
|
381
|
+
"0.6.10",
|
|
382
|
+
"0.6.11"
|
|
380
383
|
],
|
|
381
384
|
"@rightkit/settings-ui": [
|
|
382
385
|
"0.1.0",
|
|
@@ -457,56 +460,57 @@
|
|
|
457
460
|
"rightkit-asr": "0.3.1",
|
|
458
461
|
"rightkit-audio": "0.3.1",
|
|
459
462
|
"rightkit-automation": "0.6.1",
|
|
460
|
-
"rightkit-browser": "0.3.
|
|
463
|
+
"rightkit-browser": "0.3.7",
|
|
461
464
|
"rightkit-cache": "0.2.3",
|
|
462
|
-
"rightkit-channel-memory": "0.2.
|
|
465
|
+
"rightkit-channel-memory": "0.2.2",
|
|
463
466
|
"rightkit-child-process": "0.5.7",
|
|
464
467
|
"rightkit-compose": "0.2.0",
|
|
465
|
-
"rightkit-contracts": "0.1.
|
|
468
|
+
"rightkit-contracts": "0.1.8",
|
|
466
469
|
"rightkit-crash": "0.3.6",
|
|
467
470
|
"rightkit-credentials": "0.4.2",
|
|
468
471
|
"rightkit-crypto": "0.1.0",
|
|
469
472
|
"rightkit-daemon": "0.4.0",
|
|
470
|
-
"rightkit-db": "0.5.
|
|
473
|
+
"rightkit-db": "0.5.3",
|
|
471
474
|
"rightkit-device": "0.4.0",
|
|
472
|
-
"rightkit-docs": "0.1.
|
|
473
|
-
"rightkit-embed": "0.6.
|
|
475
|
+
"rightkit-docs": "0.1.3",
|
|
476
|
+
"rightkit-embed": "0.6.2",
|
|
474
477
|
"rightkit-ffmpeg": "0.2.11",
|
|
475
|
-
"rightkit-file-watch": "0.4.
|
|
478
|
+
"rightkit-file-watch": "0.4.2",
|
|
476
479
|
"rightkit-fs": "0.4.7",
|
|
477
|
-
"rightkit-fsindex": "0.
|
|
480
|
+
"rightkit-fsindex": "0.6.0",
|
|
478
481
|
"rightkit-google-identity": "0.2.0",
|
|
479
482
|
"rightkit-hooks": "0.2.0",
|
|
480
483
|
"rightkit-hotkeys": "0.1.2",
|
|
481
|
-
"rightkit-http": "0.3.
|
|
484
|
+
"rightkit-http": "0.3.9",
|
|
482
485
|
"rightkit-identity": "0.1.0",
|
|
483
486
|
"rightkit-job-queue": "0.5.1",
|
|
484
487
|
"rightkit-license": "0.2.5",
|
|
485
488
|
"rightkit-llm": "0.3.1",
|
|
486
|
-
"rightkit-logs": "0.3.
|
|
487
|
-
"rightkit-mcp": "0.7.
|
|
488
|
-
"rightkit-models": "0.5.
|
|
489
|
+
"rightkit-logs": "0.3.6",
|
|
490
|
+
"rightkit-mcp": "0.7.1",
|
|
491
|
+
"rightkit-models": "0.5.2",
|
|
489
492
|
"rightkit-motion": "0.2.0",
|
|
490
493
|
"rightkit-oauth": "0.10.0",
|
|
491
494
|
"rightkit-ocr": "0.2.3",
|
|
492
495
|
"rightkit-onnx": "0.2.8",
|
|
493
496
|
"rightkit-overlay": "0.2.0",
|
|
494
497
|
"rightkit-overlay-win": "0.1.0",
|
|
495
|
-
"rightkit-ownership": "0.4.
|
|
496
|
-
"rightkit-pdf": "0.3.
|
|
498
|
+
"rightkit-ownership": "0.4.3",
|
|
499
|
+
"rightkit-pdf": "0.3.4",
|
|
497
500
|
"rightkit-platform-rules": "0.1.0",
|
|
498
501
|
"rightkit-playback": "0.3.0",
|
|
502
|
+
"rightkit-qa": "0.9.2",
|
|
499
503
|
"rightkit-qa-driver": "0.7.0",
|
|
500
504
|
"rightkit-record": "0.3.3",
|
|
501
505
|
"rightkit-review": "0.4.0",
|
|
502
506
|
"rightkit-sandbox": "0.6.1",
|
|
503
|
-
"rightkit-search": "0.4.
|
|
504
|
-
"rightkit-send": "0.
|
|
507
|
+
"rightkit-search": "0.4.1",
|
|
508
|
+
"rightkit-send": "0.3.0",
|
|
505
509
|
"rightkit-sidecar": "0.3.0",
|
|
506
510
|
"rightkit-speech-client": "0.4.0",
|
|
507
511
|
"rightkit-spend": "0.2.0",
|
|
508
512
|
"rightkit-sync": "0.2.2",
|
|
509
|
-
"rightkit-tauri-shell": "0.
|
|
513
|
+
"rightkit-tauri-shell": "0.7.0",
|
|
510
514
|
"rightkit-time": "0.1.0",
|
|
511
515
|
"rightkit-transcript": "0.4.0",
|
|
512
516
|
"rightkit-tts": "0.2.3",
|
|
@@ -542,7 +546,7 @@
|
|
|
542
546
|
"rightkit-browser": "0.3.6",
|
|
543
547
|
"rightkit-cache": "0.2.3",
|
|
544
548
|
"rightkit-channel-memory": "0.2.1",
|
|
545
|
-
"rightkit-child-process": "0.5.
|
|
549
|
+
"rightkit-child-process": "0.5.7",
|
|
546
550
|
"rightkit-compose": "0.2.0",
|
|
547
551
|
"rightkit-contracts": "0.1.7",
|
|
548
552
|
"rightkit-control": "0.3.0",
|
|
@@ -631,13 +635,13 @@
|
|
|
631
635
|
"@rightkit/logs": "0.1.6",
|
|
632
636
|
"@rightkit/media-ui": "0.3.4",
|
|
633
637
|
"@rightkit/onboarding": "0.6.3",
|
|
634
|
-
"@rightkit/outdated": "0.
|
|
638
|
+
"@rightkit/outdated": "0.3.0",
|
|
635
639
|
"@rightkit/pdf-ui": "0.2.0",
|
|
636
640
|
"@rightkit/platform-ui": "0.4.0",
|
|
637
641
|
"@rightkit/qa": "0.6.1",
|
|
638
|
-
"@rightkit/qa-chrome": "0.1.
|
|
642
|
+
"@rightkit/qa-chrome": "0.1.12",
|
|
639
643
|
"@rightkit/react-shell": "0.7.2",
|
|
640
|
-
"@rightkit/release": "0.6.
|
|
644
|
+
"@rightkit/release": "0.6.11",
|
|
641
645
|
"@rightkit/settings-ui": "0.7.0",
|
|
642
646
|
"@rightkit/shell": "0.1.1",
|
|
643
647
|
"@rightkit/tauri": "0.3.0",
|
|
@@ -652,7 +656,8 @@
|
|
|
652
656
|
"0.2.1",
|
|
653
657
|
"0.3.1",
|
|
654
658
|
"0.4.0",
|
|
655
|
-
"0.4.1"
|
|
659
|
+
"0.4.1",
|
|
660
|
+
"0.4.2"
|
|
656
661
|
],
|
|
657
662
|
"rightkit-browser": [
|
|
658
663
|
"0.2.0",
|
|
@@ -661,7 +666,8 @@
|
|
|
661
666
|
"0.3.0",
|
|
662
667
|
"0.3.1",
|
|
663
668
|
"0.3.4",
|
|
664
|
-
"0.3.5"
|
|
669
|
+
"0.3.5",
|
|
670
|
+
"0.3.6"
|
|
665
671
|
],
|
|
666
672
|
"rightkit-models": [
|
|
667
673
|
"0.2.1",
|
|
@@ -674,7 +680,8 @@
|
|
|
674
680
|
"0.3.0",
|
|
675
681
|
"0.3.1",
|
|
676
682
|
"0.3.2",
|
|
677
|
-
"0.4.4"
|
|
683
|
+
"0.4.4",
|
|
684
|
+
"0.5.1"
|
|
678
685
|
],
|
|
679
686
|
"rightkit-audio": [
|
|
680
687
|
"0.1.0",
|
|
@@ -690,7 +697,8 @@
|
|
|
690
697
|
"0.3.1",
|
|
691
698
|
"0.4.0",
|
|
692
699
|
"0.4.3",
|
|
693
|
-
"0.5.1"
|
|
700
|
+
"0.5.1",
|
|
701
|
+
"0.5.2"
|
|
694
702
|
],
|
|
695
703
|
"rightkit-embed": [
|
|
696
704
|
"0.2.1",
|
|
@@ -700,7 +708,8 @@
|
|
|
700
708
|
"0.3.2",
|
|
701
709
|
"0.4.0",
|
|
702
710
|
"0.5.0",
|
|
703
|
-
"0.6.0"
|
|
711
|
+
"0.6.0",
|
|
712
|
+
"0.6.1"
|
|
704
713
|
],
|
|
705
714
|
"rightkit-jobs": [
|
|
706
715
|
"0.2.1",
|
|
@@ -720,7 +729,8 @@
|
|
|
720
729
|
"0.5.1",
|
|
721
730
|
"0.5.2",
|
|
722
731
|
"0.5.3",
|
|
723
|
-
"0.6.0"
|
|
732
|
+
"0.6.0",
|
|
733
|
+
"0.7.0"
|
|
724
734
|
],
|
|
725
735
|
"rightkit-media": [
|
|
726
736
|
"0.2.2",
|
|
@@ -772,7 +782,8 @@
|
|
|
772
782
|
"0.7.0",
|
|
773
783
|
"0.7.1",
|
|
774
784
|
"0.8.0",
|
|
775
|
-
"0.9.0"
|
|
785
|
+
"0.9.0",
|
|
786
|
+
"0.9.1"
|
|
776
787
|
],
|
|
777
788
|
"rightkit-sandbox": [
|
|
778
789
|
"0.1.0",
|
|
@@ -833,7 +844,8 @@
|
|
|
833
844
|
"0.3.0",
|
|
834
845
|
"0.3.5",
|
|
835
846
|
"0.3.6",
|
|
836
|
-
"0.3.7"
|
|
847
|
+
"0.3.7",
|
|
848
|
+
"0.3.8"
|
|
837
849
|
],
|
|
838
850
|
"rightkit-fs": [
|
|
839
851
|
"0.1.0",
|
|
@@ -869,7 +881,8 @@
|
|
|
869
881
|
"rightkit-pdf": [
|
|
870
882
|
"0.1.0",
|
|
871
883
|
"0.3.0",
|
|
872
|
-
"0.3.2"
|
|
884
|
+
"0.3.2",
|
|
885
|
+
"0.3.3"
|
|
873
886
|
],
|
|
874
887
|
"rightkit-speech-client": [
|
|
875
888
|
"0.3.0",
|
|
@@ -898,7 +911,8 @@
|
|
|
898
911
|
"0.2.0",
|
|
899
912
|
"0.2.1",
|
|
900
913
|
"0.3.0",
|
|
901
|
-
"0.4.1"
|
|
914
|
+
"0.4.1",
|
|
915
|
+
"0.5.0"
|
|
902
916
|
],
|
|
903
917
|
"rightkit-asr": [
|
|
904
918
|
"0.0.2",
|
|
@@ -912,7 +926,8 @@
|
|
|
912
926
|
"0.2.2",
|
|
913
927
|
"0.3.0",
|
|
914
928
|
"0.3.2",
|
|
915
|
-
"0.3.3"
|
|
929
|
+
"0.3.3",
|
|
930
|
+
"0.3.5"
|
|
916
931
|
],
|
|
917
932
|
"rightkit-ocr": [
|
|
918
933
|
"0.1.2",
|
|
@@ -998,13 +1013,15 @@
|
|
|
998
1013
|
"0.1.1"
|
|
999
1014
|
],
|
|
1000
1015
|
"rightkit-channel-memory": [
|
|
1001
|
-
"0.1.0"
|
|
1016
|
+
"0.1.0",
|
|
1017
|
+
"0.2.1"
|
|
1002
1018
|
],
|
|
1003
1019
|
"rightkit-compose": [
|
|
1004
1020
|
"0.1.0"
|
|
1005
1021
|
],
|
|
1006
1022
|
"rightkit-contracts": [
|
|
1007
|
-
"0.1.5"
|
|
1023
|
+
"0.1.5",
|
|
1024
|
+
"0.1.7"
|
|
1008
1025
|
],
|
|
1009
1026
|
"rightkit-hooks": [
|
|
1010
1027
|
"0.1.0",
|
|
@@ -1068,7 +1085,8 @@
|
|
|
1068
1085
|
],
|
|
1069
1086
|
"rightkit-docs": [
|
|
1070
1087
|
"0.1.0",
|
|
1071
|
-
"0.1.1"
|
|
1088
|
+
"0.1.1",
|
|
1089
|
+
"0.1.2"
|
|
1072
1090
|
],
|
|
1073
1091
|
"rightkit-tts-qwen": [
|
|
1074
1092
|
"0.2.6"
|
|
@@ -1078,10 +1096,12 @@
|
|
|
1078
1096
|
"0.2.2"
|
|
1079
1097
|
],
|
|
1080
1098
|
"rightkit-send": [
|
|
1081
|
-
"0.1.0"
|
|
1099
|
+
"0.1.0",
|
|
1100
|
+
"0.2.0"
|
|
1082
1101
|
],
|
|
1083
1102
|
"rightkit-file-watch": [
|
|
1084
|
-
"0.4.0"
|
|
1103
|
+
"0.4.0",
|
|
1104
|
+
"0.4.1"
|
|
1085
1105
|
],
|
|
1086
1106
|
"rightkit-sync": [
|
|
1087
1107
|
"0.1.1"
|
|
@@ -1092,7 +1112,8 @@
|
|
|
1092
1112
|
"0.3.3",
|
|
1093
1113
|
"0.4.0",
|
|
1094
1114
|
"0.5.0",
|
|
1095
|
-
"0.5.1"
|
|
1115
|
+
"0.5.1",
|
|
1116
|
+
"0.6.0"
|
|
1096
1117
|
],
|
|
1097
1118
|
"rightkit-android": [
|
|
1098
1119
|
"0.2.0"
|
package/runtime-budgets.mjs
CHANGED
|
@@ -251,10 +251,13 @@ const posix = (p) => p.split(path.sep).join("/");
|
|
|
251
251
|
* The git pathspecs (relative to the workspace root) whose change makes a measurement stale: the
|
|
252
252
|
* crate's src, benches, Cargo.toml (features) and build.rs, plus src, Cargo.toml and build.rs of every
|
|
253
253
|
* workspace crate it reaches through `path` dependencies (transitively). Returns { root, specs, problems }.
|
|
254
|
+
* Every crate is its own Cargo workspace (rightkit#1285), so `root` is the crate directory (its own Cargo.toml and Cargo.lock)
|
|
255
|
+
* and a sibling crate's paths are `../<x>/...`. `deps.base` names the directory the specs are relative to (default: the
|
|
256
|
+
* workspace root); a caller that runs git at the repository root passes it so the specs read crates/<x>/....
|
|
254
257
|
* Callers must refuse incomplete metadata rather than using a partial dependency scope.
|
|
255
258
|
*/
|
|
256
259
|
export function measuredPathspecs(crateDir, deps = {}) {
|
|
257
|
-
const { exists = existsSync, readFile = readFileSync } = deps;
|
|
260
|
+
const { exists = existsSync, readFile = readFileSync, base } = deps;
|
|
258
261
|
const problems = [];
|
|
259
262
|
// Workspace discovery deliberately tolerates bad ancestor manifests elsewhere. Freshness cannot:
|
|
260
263
|
// a swallowed read/parse failure could hide inherited dependencies and shrink the measured graph.
|
|
@@ -271,7 +274,7 @@ export function measuredPathspecs(crateDir, deps = {}) {
|
|
|
271
274
|
const checked = { exists, readFile: checkedRead };
|
|
272
275
|
let root = path.resolve(crateDir);
|
|
273
276
|
const specs = [];
|
|
274
|
-
const add = (dir, names) => { for (const name of names) specs.push(posix(path.relative(root, path.join(dir, name)))); };
|
|
277
|
+
const add = (dir, names) => { for (const name of names) specs.push(posix(path.relative(base ? path.resolve(base) : root, path.join(dir, name)))); };
|
|
275
278
|
try {
|
|
276
279
|
root = findWorkspaceRoot(crateDir, checked) ?? root;
|
|
277
280
|
add(path.resolve(crateDir), CRATE_PATHS);
|
|
@@ -365,6 +368,7 @@ export function measurementStaleness(commit, crateDir, git = defaultGit, deps =
|
|
|
365
368
|
}
|
|
366
369
|
} catch (error) { return `cannot resolve Cargo.lock package identity: ${error.message}`; }
|
|
367
370
|
if (name) {
|
|
371
|
+
// The crate's own workspace lock: root is the crate directory when the crate is its own workspace (#1285).
|
|
368
372
|
const lockPath = path.join(root, "Cargo.lock");
|
|
369
373
|
let now;
|
|
370
374
|
try { now = exists(lockPath) ? readFile(lockPath, "utf8") : null; }
|
package/scan-digest.mjs
CHANGED
|
@@ -54,6 +54,60 @@ export function rustCratePlan(own = {}) {
|
|
|
54
54
|
return { lintSets, defaultCheck, checkSets };
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
// ---- Clippy batching (GATE-CONTRACT §1 "Clippy route & batching"; item 8 rows 8.6, 8.8, 8.15) -----------------------------------------
|
|
58
|
+
// Lives here, beside the scan ids, so the credentialed verifiers (requiredScanIds) and the planner (planScans) spell a batch's id from
|
|
59
|
+
// one function. Pure: no file reads.
|
|
60
|
+
|
|
61
|
+
/** The feature flags that mean the same thing on every package they are applied to: any other set names features of one crate. */
|
|
62
|
+
export const CLIPPY_UNIVERSAL_FEATURE_FLAGS = Object.freeze(["--all-features", "--no-default-features"]);
|
|
63
|
+
const optionValue = (set, names) => {
|
|
64
|
+
for (let i = 0; i < set.length; i += 1) for (const n of names) { if (set[i] === n) return set[i + 1] ?? null; if (set[i].startsWith(`${n}=`)) return set[i].slice(n.length + 1); }
|
|
65
|
+
return null;
|
|
66
|
+
};
|
|
67
|
+
/** The target and profile a feature-set argv selects (null: the toolchain's host target and the dev profile). */
|
|
68
|
+
export const clippySelectionOf = (set) => ({ target: optionValue(set, ["--target"]), profile: set.includes("--release") || set.includes("-r") ? "release" : optionValue(set, ["--profile"]) });
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Groups the Clippy configurations of a plan into invocations. `entries`: `[{ name, crate, ws, set, count, env }]`, one per crate
|
|
72
|
+
* and lint feature set (`count` is how many sets the crate declares). Entries are batched when workspace, feature set, target,
|
|
73
|
+
* profile, lint policy, toolchain and environment are all equal (they share one `-p` list); an entry is its own invocation, with
|
|
74
|
+
* the reason recorded, when:
|
|
75
|
+
* - its crate is in `solo` (ci/shards.json `solo`: a crate that always gets a job of its own);
|
|
76
|
+
* - it is in `separate` (a name to a reason): batching changed what compiles for it (feature unification, item 8 row 8.7);
|
|
77
|
+
* - its feature set names crate-specific features (anything but --all-features / --no-default-features): such a set is
|
|
78
|
+
* per-configuration by construction, for example rightkit-db's SQLCipher variants or rightkit-qa-driver's wv2 generations
|
|
79
|
+
* (ci/gate.config.json featureSets);
|
|
80
|
+
* - its crate is sidecar-bound: it is scheduled after every independent batch and never joins one.
|
|
81
|
+
* A batch never widens a package set: it names exactly its members with `-p`. A batch's id is `clippy:batch:[<ws>:]<8 hex>` over its
|
|
82
|
+
* workspace, feature set, target, profile, lint policy and member list (never the toolchain or the output directory, which a
|
|
83
|
+
* verifier does not know), so the planner and requiredScanIds agree and the id names exactly the crates it covers. Returns
|
|
84
|
+
* `{ batches, notes }`; batches are ordered independent first, then sidecar-bound, each group by workspace then key.
|
|
85
|
+
*/
|
|
86
|
+
export function clippyBatchPlan(entries, { solo = [], separate = new Map(), sidecarBound = new Set(), toolchain = null, lint = ["-D", "warnings"] } = {}) {
|
|
87
|
+
const soloSet = new Set(solo);
|
|
88
|
+
const groups = new Map();
|
|
89
|
+
for (const e of entries) {
|
|
90
|
+
const set = [...e.set];
|
|
91
|
+
const crate = e.crate ?? e.name;
|
|
92
|
+
const sel = clippySelectionOf(set);
|
|
93
|
+
let reason = null;
|
|
94
|
+
if (soloSet.has(e.name) || soloSet.has(crate)) reason = "ci/shards.json solo: the crate always gets an invocation of its own";
|
|
95
|
+
else if (separate instanceof Map && separate.has(e.name)) reason = separate.get(e.name);
|
|
96
|
+
else if (set.some((w) => !CLIPPY_UNIVERSAL_FEATURE_FLAGS.includes(w))) reason = `ci/gate.config.json featureSets names crate-specific features (${set.join(" ")})${e.count > 1 ? `; ${crate} declares ${e.count} feature configurations that are separate invocations by construction` : ""}`;
|
|
97
|
+
const bound = sidecarBound.has(e.name) || sidecarBound.has(crate);
|
|
98
|
+
const identity = { ws: e.ws, set, target: sel.target, profile: sel.profile, lint, ...(reason || bound ? { only: e.name, sidecar: bound } : {}) };
|
|
99
|
+
const key = canonicalJson({ ...identity, toolchain, env: e.env ?? null });
|
|
100
|
+
if (!groups.has(key)) groups.set(key, { key, identity: canonicalJson(identity), ws: e.ws, set, target: sel.target, profile: sel.profile, units: [], crates: [], reason: reason ?? (bound ? "sidecar-bound: scheduled after its sidecar prerequisite, never batched with independent crates" : null), order: bound ? "sidecar" : "independent" });
|
|
101
|
+
const g = groups.get(key);
|
|
102
|
+
g.units.push(e.name); if (!g.crates.includes(crate)) g.crates.push(crate);
|
|
103
|
+
}
|
|
104
|
+
const batches = [...groups.values()].map((g) => ({ ...g, units: g.units.sort(), crates: g.crates.sort() })).map((g) => ({ ...g, id: `clippy:batch:${g.ws === "." ? "" : `${g.ws}:`}${sha256(`${g.identity}\0${g.units.join("\0")}`).slice(0, 8)}` }));
|
|
105
|
+
batches.sort((a, b) => (a.order === b.order ? (a.ws === b.ws ? (a.key < b.key ? -1 : 1) : a.ws < b.ws ? -1 : 1) : a.order === "independent" ? -1 : 1));
|
|
106
|
+
const notes = batches.filter((b) => b.reason).map((b) => `clippy batching: ${b.units.join(", ")} (${b.set.join(" ") || "default features"}) stays its own invocation: ${b.reason}`);
|
|
107
|
+
notes.push(`clippy batching: ${entries.length} crate configuration(s) in ${batches.length} invocation(s), each \`-p\` list exactly its members, \`--locked\` and \`--no-deps\` on every one; no batch is \`--workspace\``);
|
|
108
|
+
return { batches, notes };
|
|
109
|
+
}
|
|
110
|
+
|
|
57
111
|
/** Scan ids every scan of the whole repository always has when it holds Rust units (cargo.toml, workflows, YAML, JSON and licences). */
|
|
58
112
|
export const WORKSPACE_SCAN_IDS = Object.freeze(["cargo-metadata", "cargo-deny", "cargo-audit", "actionlint", "yaml-parse", "toml-parse", "json-parse", "license", "secret-scan"]);
|
|
59
113
|
/** Prefixes at least one scan id must carry (rustfmt groups by edition, so its exact ids depend on the files). */
|
|
@@ -62,25 +116,35 @@ export const REQUIRED_SCAN_PREFIXES = Object.freeze(["rustfmt:"]);
|
|
|
62
116
|
/**
|
|
63
117
|
* The scan ids a LOCAL scan record must contain, each with status pass, for these publishable Rust `units` ([names], crates/<name>).
|
|
64
118
|
* `exists(repoPath)` answers from the AUTHENTICATED source (never from the record): src/lib.rs decides `doc`, CHANGELOG.md decides
|
|
65
|
-
* `changelog-version`, and the repository's own ci/advisory-exceptions.json, ownership catalog and docs generator decide theirs.
|
|
119
|
+
* `changelog-version`, and the repository's own ci/advisory-exceptions.json (or, per crate, crates/<name>/.rightkit/advisory-exceptions.json), ownership catalog and docs generator decide theirs.
|
|
66
120
|
* `crateFeatures` is ci/gate.config.json `rust`. `includeTests` adds the per-feature-set test scans. Extra scans in a record are
|
|
67
121
|
* allowed; a missing one is not. planScans builds its ids from the same helpers, and a test holds the two in agreement.
|
|
68
122
|
*/
|
|
69
|
-
export function requiredScanIds({ units, crateFeatures = {}, exists, includeTests = false }) {
|
|
123
|
+
export function requiredScanIds({ units, crateFeatures = {}, exists, includeTests = false, perCrateWorkspaces = undefined, clippyBatching = false, shardSolo = [], clippySeparate = new Map(), sidecarBound = new Set() }) {
|
|
70
124
|
if (!Array.isArray(units) || units.length === 0 || !units.every((n) => typeof n === "string" && n)) throw new TypeError("requiredScanIds: units must be a non-empty array of names");
|
|
71
125
|
if (typeof exists !== "function") throw new TypeError("requiredScanIds: exists(repoPath) is required");
|
|
72
|
-
|
|
73
|
-
|
|
126
|
+
// One Cargo workspace and lock per crate (rightkit#1285): every unit has its own crates/<name>/Cargo.lock, so the per-workspace scans
|
|
127
|
+
// (metadata, deny, audit and the advisory ledger where the crate has one) are required per unit and carry the crate name; there is no
|
|
128
|
+
// repository-level ledger. A repository with one root workspace has no per-crate lock and keeps the unsuffixed ids.
|
|
129
|
+
const perCrate = perCrateWorkspaces ?? units.every((n) => exists(`crates/${n}/Cargo.lock`));
|
|
130
|
+
const ids = new Set(WORKSPACE_SCAN_IDS.filter((id) => !(perCrate && /^cargo-(metadata|deny|audit)$/.test(id))));
|
|
131
|
+
if (!perCrate && exists("ci/advisory-exceptions.json")) ids.add("advisory-exceptions");
|
|
74
132
|
if (exists("packages/release/rightkit-ownership.json") && exists("crates/rightkit-ownership/catalog/ownership-catalog.json")) ids.add("ownership-catalog");
|
|
75
133
|
if (exists("scripts/generate-index.mjs")) ids.add("generated-docs");
|
|
134
|
+
const clippyEntries = [];
|
|
76
135
|
for (const name of units) {
|
|
77
136
|
const own = crateFeatures?.[name] ?? {};
|
|
78
137
|
const { lintSets, defaultCheck, checkSets } = rustCratePlan(own);
|
|
138
|
+
if (perCrate) {
|
|
139
|
+
for (const id of ["cargo-metadata", "cargo-deny", "cargo-audit"]) ids.add(`${id}:${name}`);
|
|
140
|
+
if (exists(`crates/${name}/.rightkit/advisory-exceptions.json`)) ids.add(`advisory-exceptions:${name}`);
|
|
141
|
+
}
|
|
79
142
|
ids.add(rustScanId.packageList(name));
|
|
80
143
|
if (exists(`crates/${name}/CHANGELOG.md`)) ids.add(rustScanId.changelog(name));
|
|
81
144
|
if (defaultCheck) ids.add(rustScanId.check(name));
|
|
82
145
|
checkSets.forEach((_set, i) => ids.add(rustScanId.checkFeatures(name, i)));
|
|
83
|
-
lintSets.forEach((
|
|
146
|
+
if (clippyBatching) lintSets.forEach((set) => clippyEntries.push({ name, crate: name, ws: ".", set, count: lintSets.length, env: null }));
|
|
147
|
+
else lintSets.forEach((_set, i) => ids.add(rustScanId.clippy(name, lintSets.length, i)));
|
|
84
148
|
if (exists(`crates/${name}/src/lib.rs`)) ids.add(rustScanId.doc(name));
|
|
85
149
|
if (includeTests) {
|
|
86
150
|
lintSets.forEach((_set, i) => {
|
|
@@ -89,6 +153,8 @@ export function requiredScanIds({ units, crateFeatures = {}, exists, includeTest
|
|
|
89
153
|
});
|
|
90
154
|
}
|
|
91
155
|
}
|
|
156
|
+
// With batching on, the Clippy ids are the batches' (the same function the planner calls), never the per-crate ones.
|
|
157
|
+
if (clippyBatching) for (const b of clippyBatchPlan(clippyEntries, { solo: shardSolo, separate: clippySeparate, sidecarBound }).batches) ids.add(b.id);
|
|
92
158
|
return [...ids].sort();
|
|
93
159
|
}
|
|
94
160
|
|
package/sign-updater.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import { refuseManagedEnvSecrets } from "./managed-host-secrets.mjs";
|
|
|
7
7
|
import { execWithUpdaterCredential } from "./protected-credentials.mjs";
|
|
8
8
|
import { resolvePnpmCli } from "./development.mjs";
|
|
9
9
|
import { UPDATER_KEY_ID_RE, updaterSignatureKeyId } from "./github-updater-release.mjs";
|
|
10
|
+
import { ArtifactPathError, loadSplitArtifactContext, resolveArtifactPath } from "./release-artifact-path.mjs";
|
|
10
11
|
|
|
11
12
|
export const UPDATER_SIGNING_SECRET = "updater-signing-key";
|
|
12
13
|
|
|
@@ -14,6 +15,8 @@ export function runSignUpdater(args, {
|
|
|
14
15
|
env = process.env, platform = process.platform, cwd = process.cwd(),
|
|
15
16
|
execCredential = execWithUpdaterCredential, resolvePnpm = resolvePnpmCli,
|
|
16
17
|
signMac = signMacUpdaterFiles, exists = existsSync, remove = rmSync, read = (file) => readFileSync(file, "utf8"), log = console.log,
|
|
18
|
+
// The artifact-path context of a door split (release-artifact-path.mjs, row 7.04c): `--file` is then the bound Cargo target's, never the checkout's.
|
|
19
|
+
artifactPaths = null,
|
|
17
20
|
} = {}) {
|
|
18
21
|
const files = [];
|
|
19
22
|
let dryRun = false;
|
|
@@ -21,7 +24,7 @@ export function runSignUpdater(args, {
|
|
|
21
24
|
for (let i = 0; i < args.length; i++) {
|
|
22
25
|
if (args[i] === "--file") {
|
|
23
26
|
if (!args[i + 1] || args[i + 1].startsWith("--")) throw new Error("--file requires an artifact path");
|
|
24
|
-
files.push(path.resolve(cwd, args[++i]));
|
|
27
|
+
files.push(artifactPaths?.mode === "split" ? resolveArtifactPath(args[++i], artifactPaths) : path.resolve(cwd, args[++i]));
|
|
25
28
|
} else if (args[i] === "--key-id") {
|
|
26
29
|
if (keyId !== undefined) throw new Error("--key-id may be given only once");
|
|
27
30
|
if (!UPDATER_KEY_ID_RE.test(args[i + 1] ?? "")) throw new Error("--key-id requires the 16 upper-case hex digits of the updater key id");
|
|
@@ -77,9 +80,9 @@ export function runSignUpdater(args, {
|
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
80
|
-
try { runSignUpdater(process.argv.slice(2)); }
|
|
83
|
+
try { runSignUpdater(process.argv.slice(2), { artifactPaths: await loadSplitArtifactContext({ cwd: process.cwd() }) }); }
|
|
81
84
|
catch (error) {
|
|
82
|
-
console.error(`sign-updater: ${error.code ? `[${error.code}] ` : ""}${error.message}`);
|
|
85
|
+
console.error(`sign-updater: ${error instanceof ArtifactPathError ? "" : error.code ? `[${error.code}] ` : ""}${error.message}`);
|
|
83
86
|
process.exitCode = error.exitCode ?? 1;
|
|
84
87
|
}
|
|
85
88
|
}
|