@rightkit/release 0.6.31 → 0.6.33
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/bin/rightkit-gate.mjs +60 -11
- package/cargo-target-shim.mjs +2 -1
- package/deterministic-scans.mjs +5 -3
- package/package.json +1 -1
- package/rightkit-versions.json +4 -4
package/bin/rightkit-gate.mjs
CHANGED
|
@@ -25,9 +25,10 @@
|
|
|
25
25
|
//
|
|
26
26
|
// Content checks run on an export of HEAD (exactly what is pushed), never on uncommitted work in the checkout.
|
|
27
27
|
//
|
|
28
|
-
// rightkit-gate [--base <ref>] [--plan]
|
|
29
|
-
// run the gate (default base origin/main); --plan prints the scans and runs none
|
|
30
|
-
//
|
|
28
|
+
// rightkit-gate [--base <ref>] [--plan]
|
|
29
|
+
// run the gate (default base origin/main); --plan prints the scans and runs none.
|
|
30
|
+
// There is no cache bypass (GC-T14; Adrian: no no-cache option): a result is reused only under a key
|
|
31
|
+
// naming every input it read, so a changed input always reruns.
|
|
31
32
|
// rightkit-gate --to check|compile|package|qualify|dev|test --route [--platform p] [--commit <rev>]
|
|
32
33
|
// prints one JSON line (schema rightkit-gate.route/1) naming the route this host takes for the
|
|
33
34
|
// stage and the refusal it would meet, and runs nothing: no ownership, snapshot, check, run record
|
|
@@ -79,7 +80,7 @@ import path from "node:path";
|
|
|
79
80
|
import { hostTarget } from "../cross-targets.mjs";
|
|
80
81
|
import { FOREIGN_PRE_COMMIT, retireHooksIn } from "../hook-retirement.mjs";
|
|
81
82
|
import { fileURLToPath } from "node:url";
|
|
82
|
-
import { BIOME_CONFIG_FILES, ESLINT_CONFIG_FILES, LOCAL_CLASS_B_JOBS, WORKSPACE_RUST_FILE, ancestorConfigChanged, ancestorDirsOf, canonicalJson, defaultSpawn, defaultSpawnAsync, digestScanSet, fileScanCache, findRustfmt, metadataArgs, planScans, runScans, scanToolPolicyFromPipeline, scanDeferrals, scanFailures } from "../deterministic-scans.mjs";
|
|
83
|
+
import { BIOME_CONFIG_FILES, CHECKER_IDENTITY, ESLINT_CONFIG_FILES, LOCAL_CLASS_B_JOBS, WORKSPACE_RUST_FILE, ancestorConfigChanged, ancestorDirsOf, canonicalJson, defaultSpawn, defaultSpawnAsync, digestScanSet, fileScanCache, findRustfmt, metadataArgs, planScans, runScans, scanToolPolicyFromPipeline, scanDeferrals, scanFailures } from "../deterministic-scans.mjs";
|
|
83
84
|
import { changedLockNames, parseLock, reach } from "../lock-graph.mjs";
|
|
84
85
|
import { resolveExecutor } from "../gate-executor.mjs";
|
|
85
86
|
// The gate's own executor: an outer gate's cargo wrapper on PATH is never this gate's cargo (gate-executor.mjs `gateWrappers`).
|
|
@@ -111,7 +112,36 @@ export const PARTIAL_EXIT = 3;
|
|
|
111
112
|
/** The platforms a door run can package: desktop (signed, sealed, installed QA, publisher upload) and mobile (signed, sealed, store test track). */
|
|
112
113
|
export const PLATFORMS = Object.freeze(["mac", "win", "ios", "android"]);
|
|
113
114
|
export const MOBILE_PLATFORMS = Object.freeze(new Set(["ios", "android"]));
|
|
114
|
-
|
|
115
|
+
// The gate's code identity for result keys: the checker (deterministic-scans and scan-digest, CHECKER_IDENTITY) and this file, where
|
|
116
|
+
// the keys are built. An unidentifiable checker gets a per-process value, so nothing is reused across runs.
|
|
117
|
+
let gateCodeIdentityMemo = null;
|
|
118
|
+
function gateCodeIdentity() {
|
|
119
|
+
if (gateCodeIdentityMemo === null) {
|
|
120
|
+
const h = createHash("sha256");
|
|
121
|
+
h.update(CHECKER_IDENTITY ?? `unidentified-${process.pid}-${Date.now()}`);
|
|
122
|
+
h.update("\0");
|
|
123
|
+
h.update(fs.readFileSync(fileURLToPath(import.meta.url)));
|
|
124
|
+
// The runtime cargo wrapper and the broker carrier it runs: their code decides what a carried compile did.
|
|
125
|
+
for (const f of ["cargo-target-shim.mjs", "snapshot-broker.mjs", "snapshot-request.mjs", "snapshot-metadata.mjs", "provenance-verify.mjs", "cargo-ledger.mjs"]) { h.update(`\0${f}\0`); h.update(fs.readFileSync(new URL(`../${f}`, import.meta.url))); }
|
|
126
|
+
gateCodeIdentityMemo = h.digest("hex").slice(0, 24);
|
|
127
|
+
}
|
|
128
|
+
return gateCodeIdentityMemo;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The real cargo a broker host's runtime wrapper runs non-compiling calls with (GATE-CONTRACT GC-A11: metadata, fmt --check, deny,
|
|
133
|
+
* audit, package --list never go to the broker, which refuses them since rustright a2972f0): the broker's registered toolchain first
|
|
134
|
+
* (managed-cargo.mjs directCargoPath), else PATH without the RustRight shims; null when none exists.
|
|
135
|
+
*/
|
|
136
|
+
function directCargoBinOf(o) {
|
|
137
|
+
const pk = o.platform === "win32" ? (Object.keys(o.env).find((k) => k.toUpperCase() === "PATH") ?? "Path") : "PATH";
|
|
138
|
+
const d = directCargoPath({ env: { ...o.env, PATH: o.env[pk] }, exists: o.exists, platform: o.platform, gateWrappers: true });
|
|
139
|
+
const names = o.platform === "win32" ? ["cargo.exe"] : ["cargo"];
|
|
140
|
+
for (const dir of String(d.path ?? "").split(o.platform === "win32" ? ";" : ":").filter(Boolean)) for (const n of names) { const c = path.join(dir, n); if (o.exists(c)) return c; }
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const USAGE = `usage: rightkit-gate --to check|compile|package|qualify|release [--platform mac|win|ios|android] [--tier patch|update] [--receipt-in <file>] [--receipt-out <file>] | rightkit-gate --to check|compile|package|qualify|release --unit npm:@rightkit/<name>|cargo:rightkit-<name> [--receipt-out <file>] | rightkit-gate --to tool --unit cargo:rightkit-qa|cargo:rightkit-credentials [--no-broker <exception-id>] [--receipt-out <file>] [--commit <rev>] (builds the unit's release binary from the commit and enrols it: cargo:rightkit-qa as the managed rightkit-qa runner, cargo:rightkit-credentials as the managed OS credential provider updater signing runs; Mac and Windows) | rightkit-gate --to check|compile|package|qualify --units-file <json {"units":[<selector>,...]} written for this run> | rightkit-gate --to check|compile|package|qualify --all-units-exception <id> (RightKit only: its unit is named on every run, or every unit by Adrian's entry in ci/all-units-exceptions.json of the commit) | rightkit-gate --to check|compile|package|qualify [--unit <selector>] --no-broker <exception-id> (Mac and Dell only; Adrian's recorded exception in .rightkit/broker-exceptions.json of the commit) | rightkit-gate --to dev|test [--commit <rev>] [-- <right-release args>] | rightkit-gate --to check|compile|package|qualify|dev|test --route [--platform mac|win|ios|android] [--commit <rev>] | rightkit-gate stage --platform mac|win [--tier patch|update] | rightkit-gate [--base <ref>] [--plan] | rightkit-gate install-hook | rightkit-gate env-digest | rightkit-gate snapshot [--commit <rev>] [--verify [--env <sha256>]] [--json] | rightkit-gate live-scans --repo <root> | rightkit-gate clippy [<cargo clippy args>] | rightkit-gate env-digest [--snapshot <dir> --commit <sha>] | rightkit-gate check [--repo <dir>] [--commit <rev> | --worktree] [--rule-tier compile|release] [--only <rule,...>] [--list] [--print-baseline] [--baseline <file>] | rightkit-gate check --commit <sha> --full-a --snapshot <dir> | --version`;
|
|
115
145
|
/** The host platform (process.platform) that constructs each platform's artifact; a platform missing here (android) builds on any host. */
|
|
116
146
|
const STAGE_NATIVE_HOST = Object.freeze({ mac: "darwin", ios: "darwin", win: "win32" });
|
|
117
147
|
|
|
@@ -2316,6 +2346,10 @@ async function bindUnitCargo({ o, git, root, ds, executor, which, scopeDirs, ext
|
|
|
2316
2346
|
// Installing the carrier map sends nothing: the ownership records each carried request's sub-handle just before it is sent (snapshot-broker.mjs).
|
|
2317
2347
|
const { brokerSection } = await import("../snapshot-broker.mjs");
|
|
2318
2348
|
broker = { checkoutDirs: Object.fromEntries(workspaces.map((w) => [w, path.join(checkoutReal, ...(w === "." ? [] : w.split("/")))])), section: (o.brokerSection ?? brokerSection)(sb) };
|
|
2349
|
+
// The unit stages' non-compiling cargo (the `cargo fmt --check` step, metadata) runs directly with the broker's real cargo, as class A
|
|
2350
|
+
// does (GC-A11). Without it the wrapper sent `cargo fmt -p <crate> --check` to the broker, which refuses non-compiling requests: every
|
|
2351
|
+
// unit compile on the Mac and Dell stopped there (rightkit-document-workspace on the Dell, 2026-11-03, exit 125).
|
|
2352
|
+
realCargo = directCargoBinOf(o);
|
|
2319
2353
|
} else {
|
|
2320
2354
|
realCargo = realCargoOf(which("cargo"));
|
|
2321
2355
|
if (!realCargo) return { refusal: "no cargo on PATH to wrap for the unit stages" };
|
|
@@ -3039,6 +3073,11 @@ export async function main(argv, io = {}) {
|
|
|
3039
3073
|
gateFile: fileURLToPath(import.meta.url), ...io,
|
|
3040
3074
|
};
|
|
3041
3075
|
const args = [...argv];
|
|
3076
|
+
// The cache bypass is retired (GC-T14; workspace rule: never write or run a no-cache option). Refused by name so an old caller learns why.
|
|
3077
|
+
if (args.includes("--no-cache") || (io.env ?? process.env).RK_GATE_CACHE === "0") {
|
|
3078
|
+
(io.err ?? console.error)("rightkit-gate: --no-cache and RK_GATE_CACHE=0 are retired: results are reused only under a key naming every input they read, so a changed input always reruns (GC-T14)");
|
|
3079
|
+
return 2;
|
|
3080
|
+
}
|
|
3042
3081
|
const option = (name) => { const i = args.indexOf(name); return i < 0 ? undefined : args[i + 1]; };
|
|
3043
3082
|
// `clippy`: the Clippy route (../clippy-route.mjs; docs/GATE-CONTRACT.md §1 "Clippy route & batching"). Dispatched before the global
|
|
3044
3083
|
// flags below because everything after `clippy` is cargo's own argv, verbatim (`-v`, `-h` and `--version` are cargo's).
|
|
@@ -3675,7 +3714,7 @@ export async function main(argv, io = {}) {
|
|
|
3675
3714
|
// broker host never reaches here; a direct Windows host keeps the fail-closed static walk). Removed when the gate ends (cleanup).
|
|
3676
3715
|
if (o.platform !== "win32" && rust.workspaces.length) {
|
|
3677
3716
|
// GC-A11: the wrapper runs non-compiling calls directly, so a broker-mode wrapper also needs the real toolchain cargo (shims off PATH).
|
|
3678
|
-
const directCargoBin = () =>
|
|
3717
|
+
const directCargoBin = () => directCargoBinOf(o);
|
|
3679
3718
|
const realCargo = wrapBroker ? (directCargoBin() ?? undefined) : realCargoOf(which("cargo"));
|
|
3680
3719
|
if (!realCargo && !wrapBroker) { o.err(`${tag} BLOCKED: no cargo on PATH to wrap for the snapshot compile; nothing compiled`); return 1; }
|
|
3681
3720
|
try {
|
|
@@ -3969,7 +4008,7 @@ export async function main(argv, io = {}) {
|
|
|
3969
4008
|
try { envAtStart = classAEnvironmentDigest({ root: liveBase, gatePackage: o.gatePackage, files: live.files, spawn: o.spawn, includeCaches: false }); envStartWithCaches = classAEnvironmentDigest({ root: liveBase, gatePackage: o.gatePackage, files: live.files, spawn: o.spawn }); cachesAtStart = toolCacheManifest({ root: liveBase, files: live.files }); }
|
|
3970
4009
|
catch (error) { o.err(`${tag} BLOCKED: ${error.message}`); return 1; }
|
|
3971
4010
|
}
|
|
3972
|
-
if (boundFullA
|
|
4011
|
+
if (boundFullA) {
|
|
3973
4012
|
try {
|
|
3974
4013
|
const common = git("rev-parse", "--git-common-dir");
|
|
3975
4014
|
if (failed(common)) throw new Error("no git directory");
|
|
@@ -3981,12 +4020,19 @@ export async function main(argv, io = {}) {
|
|
|
3981
4020
|
const readBlob = (p) => fs.readFileSync(path.join(liveBase, p), "utf8");
|
|
3982
4021
|
// The verdict also depends on what is not in the tree: the gate's own code and advisory data, the node and pnpm that run
|
|
3983
4022
|
// the checks, the installed dependencies (pnpm's install state) and the platform. Any change there is a cache miss.
|
|
3984
|
-
|
|
4023
|
+
// Tool caches (vitest, tsc build info, ...) are left out: the scans write them themselves, so keying on them made every rerun miss.
|
|
4024
|
+
const environment = classAEnvironmentDigest({ root: liveBase, gatePackage: o.gatePackage, files, spawn: o.spawn, includeCaches: false });
|
|
3985
4025
|
const digest = buildCacheDigest({ objectId, headTree: digestOf(files), rustUnits: rust.units, npmUnits: npm, cargoDir: ".", rustLocks, crateFeatures, listFiles, readBlob });
|
|
3986
|
-
|
|
4026
|
+
// A row's key is its own inputs plus the environment; the run's scope and scan set are not inputs of one row, and keying on them
|
|
4027
|
+
// missed every row whenever one file joined or left the plan. build-helpers is never reused: it reads the host's trace list,
|
|
4028
|
+
// which is outside every key (and takes seconds).
|
|
4029
|
+
// A row field that shapes what the scan checks without changing its id or command is part of its key: a tsc row's tscWorkspace
|
|
4030
|
+
// (the sibling packages its check project maps; scopeScans narrows it per scope) changes the verdict on the same tree.
|
|
4031
|
+
const rowShape = (scan) => (scan.tscWorkspace ? `:tscws=${createHash("sha256").update(canonicalJson([...scan.tscWorkspace].sort())).digest("hex")}` : "");
|
|
4032
|
+
cache = { ...store, digest: (scan) => { if (/^build-helpers(:|$)/.test(scan.id)) return null; const key = digest(scan); return key === null ? null : `${key}:${environment}${rowShape(scan)}`; } };
|
|
3987
4033
|
} catch { cache = null; }
|
|
3988
4034
|
}
|
|
3989
|
-
if (!classAOnly
|
|
4035
|
+
if (!classAOnly) {
|
|
3990
4036
|
try {
|
|
3991
4037
|
const headSha = snapshotBCommit?.commit ?? text(git("rev-parse", "HEAD")).trim();
|
|
3992
4038
|
const treeId = text(git("rev-parse", `${headSha}^{tree}`)).trim();
|
|
@@ -4009,7 +4055,10 @@ export async function main(argv, io = {}) {
|
|
|
4009
4055
|
if (failed(r)) throw new Error(`git show failed: ${why(r)}`);
|
|
4010
4056
|
return text(r);
|
|
4011
4057
|
};
|
|
4012
|
-
|
|
4058
|
+
// The gate's identity is part of every class B key: a changed check or key logic never reuses an older verdict.
|
|
4059
|
+
const rowDigest = buildCacheDigest({ objectId, headTree: treeId, rustUnits: rust.units, npmUnits: npm, cargoDir: ".", rustLocks, crateFeatures, listFiles, readBlob });
|
|
4060
|
+
const gateIdentity = gateCodeIdentity();
|
|
4061
|
+
cache = { ...store, digest: (scan) => { const key = rowDigest(scan); return key === null ? null : `${key}:${gateIdentity}`; } };
|
|
4013
4062
|
}
|
|
4014
4063
|
} catch { cache = null; }
|
|
4015
4064
|
}
|
package/cargo-target-shim.mjs
CHANGED
|
@@ -175,7 +175,8 @@ export function decideCargoInvocation({ args, cwd, env, map, locate, realpath =
|
|
|
175
175
|
*
|
|
176
176
|
* Broker mode (`broker: { checkoutDirs, section }`, the Mac): `checkoutDirs` is the gate's { [cargoDir]: absolute path of that
|
|
177
177
|
* workspace in the primary checkout } (the snapshot-to-checkout map, the only source of a request's primaryCwd) and `section` the
|
|
178
|
-
* public part of the gate's snapshot broker (brokerSection). `realCargo` then
|
|
178
|
+
* public part of the gate's snapshot broker (brokerSection). `realCargo` then runs `version`, `help` and the non-compiling calls
|
|
179
|
+
* (GC-A11: metadata, fmt --check, deny, audit, package --list), which the broker refuses; null leaves those to fail at the broker.
|
|
179
180
|
*
|
|
180
181
|
* Windows, broker mode only (rightkit#1350, rustright#215): a child started without a shell finds only an .exe, so `bin/cargo.exe` is a
|
|
181
182
|
* byte copy of the live RustRight client (`broker.section.client`) and `bin/gate-trampoline.json` beside it pins node, this module and the
|
package/deterministic-scans.mjs
CHANGED
|
@@ -160,9 +160,11 @@ const BUILD_ENV_PREFIXES = ["CARGO_", "RUST", "SCCACHE_", "RK_", "RIGHTKIT_", "R
|
|
|
160
160
|
// 3,809 entries and hit none across identical runs): the run's ownership handle, the attest nonce, the request-id file, the carried call's
|
|
161
161
|
// snapshot request and cargo map, the direct receipt path.
|
|
162
162
|
const BUILD_ENV_EXCLUDED = /^(RK_GATE_|RUSTRIGHT_QUIET_LEASE$|RIGHTKIT_BUILD_OWNERSHIP$|RIGHTKIT_CARRIED_CARGO_MAP$|RUSTRIGHT_ATTEST_NONCE$|RUSTRIGHT_REQUEST_ID_FILE$|RUSTRIGHT_SNAPSHOT_REQUEST$|RK_DIRECT_RECEIPT$)/;
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
|
|
163
|
+
// Per-run parts of a value are normalised: the runtime cargo wrapper's fresh parent (`rk-gate-shim-XXXXXX`) and its folder name
|
|
164
|
+
// (`rk-cargo-shim-<identity>`), whose identity hashes the run's broker section and so differs on every run (measured 2026-11-03: two identical
|
|
165
|
+
// Class A runs of rightkit-asr shared no key, only CARGO differed). The wrapper's CODE keys the result through the gate identity instead
|
|
166
|
+
// (the gate package files in the Class A environment digest; gateCodeIdentity for class B), so a changed wrapper still misses.
|
|
167
|
+
const normalizeRunTemp = (value) => String(value).replace(/rk-gate-shim-[A-Za-z0-9]+/g, "rk-gate-shim-*").replace(/rk-cargo-shim-[0-9a-f]+/g, "rk-cargo-shim-*");
|
|
166
168
|
export const buildEnvName = (name) => {
|
|
167
169
|
const upper = String(name).toUpperCase();
|
|
168
170
|
if (BUILD_ENV_EXCLUDED.test(upper)) return false;
|
package/package.json
CHANGED
package/rightkit-versions.json
CHANGED
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@rightkit/qa": "0.6.2",
|
|
50
50
|
"@rightkit/qa-chrome": "0.1.12",
|
|
51
51
|
"@rightkit/react-shell": "0.7.2",
|
|
52
|
-
"@rightkit/release": "0.6.
|
|
52
|
+
"@rightkit/release": "0.6.33",
|
|
53
53
|
"@rightkit/settings-ui": "0.7.0",
|
|
54
54
|
"@rightkit/social-ui": "0.1.0",
|
|
55
55
|
"@rightkit/system-ui": "0.1.0",
|
|
@@ -527,7 +527,7 @@
|
|
|
527
527
|
"rightkit-code-audit-provider-sdk": "0.1.0",
|
|
528
528
|
"rightkit-color": "0.1.0",
|
|
529
529
|
"rightkit-compose": "0.2.2",
|
|
530
|
-
"rightkit-compositor": "0.
|
|
530
|
+
"rightkit-compositor": "0.2.0",
|
|
531
531
|
"rightkit-content-plan": "0.1.1",
|
|
532
532
|
"rightkit-content-proof": "0.1.0",
|
|
533
533
|
"rightkit-context": "0.1.0",
|
|
@@ -557,7 +557,7 @@
|
|
|
557
557
|
"rightkit-disk-cleanup": "0.1.0",
|
|
558
558
|
"rightkit-docs": "0.1.3",
|
|
559
559
|
"rightkit-doctor": "0.1.0",
|
|
560
|
-
"rightkit-document-workspace": "0.1.
|
|
560
|
+
"rightkit-document-workspace": "0.1.3",
|
|
561
561
|
"rightkit-embed": "0.6.2",
|
|
562
562
|
"rightkit-engine-host": "0.1.1",
|
|
563
563
|
"rightkit-evidence": "0.1.0",
|
|
@@ -630,7 +630,7 @@
|
|
|
630
630
|
"rightkit-spend": "0.2.0",
|
|
631
631
|
"rightkit-sync": "0.2.2",
|
|
632
632
|
"rightkit-system-monitor": "0.1.0",
|
|
633
|
-
"rightkit-tauri-shell": "0.7.
|
|
633
|
+
"rightkit-tauri-shell": "0.7.1",
|
|
634
634
|
"rightkit-terminal-ui": "0.1.0",
|
|
635
635
|
"rightkit-text-polish": "0.1.0",
|
|
636
636
|
"rightkit-time": "0.1.1",
|