@rightkit/release 0.2.69 → 0.2.71
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/build-release.mjs +19 -14
- package/cache-command.mjs +7 -4
- package/cli/right-release.mjs +0 -0
- package/native-cargo-layout.mjs +239 -0
- package/native-release-finalization.mjs +259 -0
- package/package.json +11 -11
- package/preflight.mjs +6 -3
- package/registry-parity.mjs +2 -2
- package/release-invocation.mjs +10 -2
- package/release-state.mjs +5 -2
- package/release.mjs +220 -12
- package/rightkit-versions.json +4 -2
- package/addon-command.test.mjs +0 -54
- package/addon-contract.test.mjs +0 -48
- package/asr-artifact-adoption.test.mjs +0 -122
- package/build-invocation-contract.test.mjs +0 -124
- package/build-release.test.mjs +0 -242
- package/cache-command.test.mjs +0 -118
- package/cache-policy.test.mjs +0 -346
- package/cargo-guard.test.mjs +0 -195
- package/cargo-target.test.mjs +0 -82
- package/create-mac-updater.test.mjs +0 -14
- package/github-release.test.mjs +0 -103
- package/heavy-command.test.mjs +0 -221
- package/legal-contract.test.mjs +0 -151
- package/mirror-root-artifact.test.mjs +0 -58
- package/model-promote.test.mjs +0 -284
- package/notary-auth.test.mjs +0 -31
- package/nsis-payload.test.mjs +0 -139
- package/nsis-upgrade-contract.test.mjs +0 -57
- package/pipeline-normalization-contract.test.mjs +0 -140
- package/preflight.test.mjs +0 -123
- package/progress-control.test.mjs +0 -56
- package/prune-r2.test.mjs +0 -12
- package/publish-cargo.test.mjs +0 -43
- package/publish-swift.test.mjs +0 -44
- package/publish-update.test.mjs +0 -207
- package/qa-contract.test.mjs +0 -47
- package/registry-parity.test.mjs +0 -30
- package/release-cli-contract.test.mjs +0 -119
- package/release-invocation.test.mjs +0 -22
- package/release-state.test.mjs +0 -395
- package/release-token.test.mjs +0 -21
- package/release.test.mjs +0 -533
- package/right-suite-contract.test.mjs +0 -1011
- package/rightapps-register.test.mjs +0 -28
- package/runtime-artifact-manifest.test.mjs +0 -128
- package/sign-updater.test.mjs +0 -12
- package/source-gate.test.mjs +0 -25
- package/standalone-clone-evidence.json +0 -32
- package/standalone-clone-verify.test.mjs +0 -76
- package/suite-doctor.test.mjs +0 -19
- package/target-bridge.test.mjs +0 -269
- package/tauri-bundle-marker.test.mjs +0 -81
- package/upload-large.test.mjs +0 -70
|
@@ -1,1011 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { spawnSync } from "node:child_process";
|
|
6
|
-
import { pathToFileURL } from "node:url";
|
|
7
|
-
import test, { after } from "node:test";
|
|
8
|
-
import {
|
|
9
|
-
assertNoRightKitCargoOverrides,
|
|
10
|
-
assertPublishedRightKitCargoDependencies,
|
|
11
|
-
cargoArguments,
|
|
12
|
-
cargoExecutable,
|
|
13
|
-
isolatedCargoMetadataEnv,
|
|
14
|
-
managedCargoShimOnPath,
|
|
15
|
-
validateRightKitCargoContract,
|
|
16
|
-
} from "./cargo-contract.mjs";
|
|
17
|
-
import { assertAsrAdapterPair } from "./asr-artifact-adoption.mjs";
|
|
18
|
-
import { resolveConfiguredBuildInputs } from "./release-invocation.mjs";
|
|
19
|
-
|
|
20
|
-
const workspace = path.resolve(
|
|
21
|
-
process.env.RIGHT_SUITE_CONTRACT_WORKSPACE
|
|
22
|
-
?? new URL("../../../..", import.meta.url).pathname.replace(/^\/(\w:)/, "$1"),
|
|
23
|
-
);
|
|
24
|
-
// The Right Suite web layer's repo + filesystem path is `rightsites` post the 2026-07-15 naming lock;
|
|
25
|
-
// a not-yet-renamed checkout may still have `rightapps`. Resolve whichever exists so the contract
|
|
26
|
-
// passes on both. (The runtime service namespace stays `rightapps` — that is deliberately untouched.)
|
|
27
|
-
const siteRepoDir = existsSync(path.join(workspace, "rightsites")) ? "rightsites" : "rightapps";
|
|
28
|
-
const versionsPath = path.join(path.dirname(new URL(import.meta.url).pathname.replace(/^\/(\w:)/, "$1")), "rightkit-versions.json");
|
|
29
|
-
const versions = JSON.parse(readFileSync(versionsPath, "utf8"));
|
|
30
|
-
const isolatedCargoHome = mkdtempSync(path.join(tmpdir(), "rightkit-cargo-home-"));
|
|
31
|
-
after(() => rmSync(isolatedCargoHome, { recursive: true, force: true }));
|
|
32
|
-
const pubkey = "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDI5Mzk1RjlGRjQ2NjI2MUQKUldRZEptYjBuMTg1S1VSUXlBdFM4WmtzaHArYko0U2hRMDVlSDJmSExVZG82Q0hoQ2srUlhqanAK";
|
|
33
|
-
const apps = [
|
|
34
|
-
{ key: "viewright", root: "viewright", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["scripts/build-mac-notarized.sh"] },
|
|
35
|
-
{ key: "scraperight", root: "scraperight", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["package.sh"] },
|
|
36
|
-
{ key: "heardright", root: "heardright/tauri-app-next", repoRoot: "heardright", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["scripts/mac-dmg.mjs", "scripts/publish-release.mjs"] },
|
|
37
|
-
// mac-dmg.mjs is the release file, as in HeardRight/CodeRight. build-mac.sh only delegates to it,
|
|
38
|
-
// so asserting the mirror call against the wrapper failed a pipeline that does mirror.
|
|
39
|
-
{ key: "mailright", root: "mailright", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["scripts/mac-dmg.mjs"] },
|
|
40
|
-
{ key: "coderight", root: "coderight/apps/coderight-tauri", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["scripts/mac-dmg.mjs"] },
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
// ScreenRight is intentionally a macOS-only AppKit consumer. It has no Tauri
|
|
44
|
-
// manifest or Windows target, so keep it in an explicit registry lane rather
|
|
45
|
-
// than manufacturing unsupported platform entries.
|
|
46
|
-
const macOnlyApps = [
|
|
47
|
-
{ key: "screenright", root: "tools/screenright", releaseFiles: ["scripts/release-package.mjs"] },
|
|
48
|
-
];
|
|
49
|
-
|
|
50
|
-
// Consuming suite apps whose packaging/build scripts must resolve Cargo build
|
|
51
|
-
// output from `cargo metadata`'s `target_directory`, never by reading
|
|
52
|
-
// CARGO_TARGET_DIR (or a shell/PowerShell equivalent) directly to locate it.
|
|
53
|
-
// This defect recurred three times across the suite (broker-managed hosts own
|
|
54
|
-
// CARGO_TARGET_DIR, so a stale/wrong value silently reads the wrong tree).
|
|
55
|
-
// rightsites and tools/screenright are intentionally out of scope here.
|
|
56
|
-
const cargoTargetDirGuardApps = [
|
|
57
|
-
"coderight/apps/coderight-tauri",
|
|
58
|
-
"cutright/apps/studio",
|
|
59
|
-
"genright",
|
|
60
|
-
"heardright/tauri-app-next",
|
|
61
|
-
"mailright",
|
|
62
|
-
"membrane/apps/membrane-hub",
|
|
63
|
-
"orthic",
|
|
64
|
-
"scraperight",
|
|
65
|
-
"viewright",
|
|
66
|
-
];
|
|
67
|
-
|
|
68
|
-
function assertReleasePackageScripts(scripts, label) {
|
|
69
|
-
for (const platform of ["mac", "win"]) {
|
|
70
|
-
assert.equal(scripts[`release:build:${platform}`], `right-release build --platform ${platform}`, `${label} must use the tier-neutral ${platform} build entry point`);
|
|
71
|
-
for (const tier of ["patch", "update"]) {
|
|
72
|
-
assert.equal(scripts[`release:upload:${tier}:${platform}`], `right-release upload --platform ${platform} --tier ${tier}`, `${label} must select ${tier} only during ${platform} upload`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const genericTauri = scripts.tauri;
|
|
77
|
-
if (typeof genericTauri === "string") {
|
|
78
|
-
assert.doesNotMatch(
|
|
79
|
-
genericTauri.trim(),
|
|
80
|
-
/^(?:(?:pnpm|npm)\s+(?:(?:exec|dlx)\s+)?|npx\s+)?(?:(?:\.\/)?node_modules\/\.bin\/)?(?:@tauri-apps\/cli\s+)?tauri(?:\s|$)/,
|
|
81
|
-
`${label} generic \"tauri\" package script bypasses the RightKit release entry points; use an explicitly named dev, debug, unsigned, or local command instead`,
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function assertMacPackageEntry(packageCommand, scripts, label) {
|
|
87
|
-
assert.equal(packageCommand.cmd, "pnpm", `${label} must use the shared pnpm package entry point`);
|
|
88
|
-
assert.ok(
|
|
89
|
-
[
|
|
90
|
-
["run", "rightkit:package:mac"],
|
|
91
|
-
["run", "rightkit:package:mac", "--", "--notarize"],
|
|
92
|
-
].some((allowed) => JSON.stringify(packageCommand.args) === JSON.stringify(allowed)),
|
|
93
|
-
`${label} R2 release must use the dedicated signed and notarized macOS package entry point`,
|
|
94
|
-
);
|
|
95
|
-
const implementation = scripts["rightkit:package:mac"];
|
|
96
|
-
assert.equal(typeof implementation, "string", `${label} must define rightkit:package:mac`);
|
|
97
|
-
assert.doesNotMatch(implementation, /\bright-release\b/, `${label} rightkit:package:mac must package directly instead of recursing into the release build`);
|
|
98
|
-
assert.doesNotMatch(implementation, /\bpnpm(?:\s+run)?\s+rightkit:package:mac\b/, `${label} rightkit:package:mac must not recurse into itself`);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function assertBuildInputs(config, target, label) {
|
|
102
|
-
resolveConfiguredBuildInputs(config, target, label);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function resolveCargoVersionContract(versionManifest, canonicalVersions) {
|
|
106
|
-
const consumer = new Map(Object.entries(versionManifest.cargo ?? {}));
|
|
107
|
-
const staged = new Map(Object.entries(versionManifest.stagedCargo ?? {}));
|
|
108
|
-
const canonical = new Map();
|
|
109
|
-
|
|
110
|
-
for (const [crate, version] of staged) {
|
|
111
|
-
if (!canonicalVersions.has(crate)) throw new Error(`unknown staged Cargo crate: ${crate}`);
|
|
112
|
-
const actual = canonicalVersions.get(crate);
|
|
113
|
-
if (actual !== version) {
|
|
114
|
-
throw new Error(`${crate} canonical manifest is ${actual}, expected staged version ${version}`);
|
|
115
|
-
}
|
|
116
|
-
canonical.set(crate, version);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
for (const [crate, version] of consumer) {
|
|
120
|
-
if (!canonicalVersions.has(crate)) throw new Error(`unknown published Cargo crate: ${crate}`);
|
|
121
|
-
const expected = staged.get(crate) ?? version;
|
|
122
|
-
const actual = canonicalVersions.get(crate);
|
|
123
|
-
if (actual !== expected) {
|
|
124
|
-
const source = staged.has(crate) ? "staged" : "published";
|
|
125
|
-
throw new Error(`${crate} canonical manifest is ${actual}, expected ${source} version ${expected}`);
|
|
126
|
-
}
|
|
127
|
-
canonical.set(crate, expected);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return { canonical, consumer };
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
let currentCargoVersionContract;
|
|
134
|
-
function getCurrentCargoVersionContract() {
|
|
135
|
-
currentCargoVersionContract ??= resolveCargoVersionContract(versions, readCanonicalCrateVersions());
|
|
136
|
-
return currentCargoVersionContract;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const cargoContractCache = new Map();
|
|
140
|
-
function readCargoManifestContract(manifestPath, label) {
|
|
141
|
-
const cacheKey = path.resolve(manifestPath).toLowerCase();
|
|
142
|
-
if (cargoContractCache.has(cacheKey)) return cargoContractCache.get(cacheKey);
|
|
143
|
-
const result = spawnSync(
|
|
144
|
-
"cargo",
|
|
145
|
-
["metadata", "--no-deps", "--offline", "--format-version", "1", "--manifest-path", manifestPath],
|
|
146
|
-
{
|
|
147
|
-
cwd: path.dirname(manifestPath),
|
|
148
|
-
encoding: "utf8",
|
|
149
|
-
env: isolatedCargoMetadataEnv(isolatedCargoHome),
|
|
150
|
-
windowsHide: true,
|
|
151
|
-
},
|
|
152
|
-
);
|
|
153
|
-
assert.equal(
|
|
154
|
-
result.status,
|
|
155
|
-
0,
|
|
156
|
-
`${label} Cargo metadata rejected manifest; RightKit dependencies must use exact crates.io versions: ${String(result.stderr ?? "").trim()}`,
|
|
157
|
-
);
|
|
158
|
-
const metadata = JSON.parse(result.stdout);
|
|
159
|
-
const expectedPath = path.resolve(manifestPath).toLowerCase();
|
|
160
|
-
const pkg = metadata.packages.find(({ manifest_path: candidate }) => path.resolve(candidate).toLowerCase() === expectedPath);
|
|
161
|
-
if (!pkg && path.resolve(metadata.workspace_root, "Cargo.toml").toLowerCase() === expectedPath) {
|
|
162
|
-
const contract = { dependencies: [], workspaceRoot: path.resolve(metadata.workspace_root) };
|
|
163
|
-
cargoContractCache.set(cacheKey, contract);
|
|
164
|
-
return contract;
|
|
165
|
-
}
|
|
166
|
-
assert.ok(pkg, `${label} was not returned by Cargo metadata`);
|
|
167
|
-
const contract = { dependencies: pkg.dependencies, workspaceRoot: path.resolve(metadata.workspace_root) };
|
|
168
|
-
cargoContractCache.set(cacheKey, contract);
|
|
169
|
-
return contract;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function assertCargoFixture(manifest, published, label) {
|
|
173
|
-
const fixtureRoot = mkdtempSync(path.join(tmpdir(), "rightkit-cargo-contract-"));
|
|
174
|
-
const manifestPath = path.join(fixtureRoot, "Cargo.toml");
|
|
175
|
-
const packageMetadata = /^\s*\[\s*package\s*\]/m.test(manifest)
|
|
176
|
-
? ""
|
|
177
|
-
: '\n[package]\nname = "rightkit-contract-fixture"\nversion = "0.0.0"\nedition = "2021"\n';
|
|
178
|
-
writeFileSync(manifestPath, `${manifest}${packageMetadata}\n[lib]\npath = "fixture.rs"\n`, "utf8");
|
|
179
|
-
writeFileSync(path.join(fixtureRoot, "fixture.rs"), "", "utf8");
|
|
180
|
-
try {
|
|
181
|
-
return assertPublishedRightKitCargoDependencies(
|
|
182
|
-
readCargoManifestContract(manifestPath, label).dependencies,
|
|
183
|
-
published,
|
|
184
|
-
label,
|
|
185
|
-
);
|
|
186
|
-
} finally {
|
|
187
|
-
rmSync(fixtureRoot, { recursive: true, force: true });
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function assertCargoOverrideFixture({ manifest, workspaceManifest, localConfig, ancestorConfig, outsideConfig }) {
|
|
192
|
-
const fixtureRoot = mkdtempSync(path.join(tmpdir(), "rightkit-cargo-override-"));
|
|
193
|
-
const repoRoot = path.join(fixtureRoot, "repo");
|
|
194
|
-
const appRoot = path.join(repoRoot, "app");
|
|
195
|
-
mkdirSync(appRoot, { recursive: true });
|
|
196
|
-
const manifestPath = path.join(appRoot, "Cargo.toml");
|
|
197
|
-
writeFileSync(manifestPath, manifest, "utf8");
|
|
198
|
-
if (workspaceManifest) writeFileSync(path.join(repoRoot, "Cargo.toml"), workspaceManifest, "utf8");
|
|
199
|
-
for (const [root, filename, source] of [
|
|
200
|
-
[appRoot, "config", localConfig],
|
|
201
|
-
[repoRoot, "config.toml", ancestorConfig],
|
|
202
|
-
[fixtureRoot, "config.toml", outsideConfig],
|
|
203
|
-
]) {
|
|
204
|
-
if (!source) continue;
|
|
205
|
-
const cargoDir = path.join(root, ".cargo");
|
|
206
|
-
mkdirSync(cargoDir, { recursive: true });
|
|
207
|
-
writeFileSync(path.join(cargoDir, filename), source, "utf8");
|
|
208
|
-
}
|
|
209
|
-
try {
|
|
210
|
-
assertNoRightKitCargoOverrides(manifestPath, repoRoot, "fixture/Cargo.toml");
|
|
211
|
-
if (workspaceManifest) {
|
|
212
|
-
assertNoRightKitCargoOverrides(path.join(repoRoot, "Cargo.toml"), repoRoot, "fixture/workspace Cargo.toml");
|
|
213
|
-
}
|
|
214
|
-
return 0;
|
|
215
|
-
} finally {
|
|
216
|
-
rmSync(fixtureRoot, { recursive: true, force: true });
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
test("Cargo override contract accepts exact registry pins without repo-local overrides", () => {
|
|
221
|
-
assert.equal(assertCargoOverrideFixture({
|
|
222
|
-
manifest: `[package]\nname = "fixture"\nversion = "0.0.0"\n[dependencies]\nrightkit-license = "=0.1.1"`,
|
|
223
|
-
localConfig: `[net]\nretry = 2\n[registries.private]\nindex = "https://example.test/index"`,
|
|
224
|
-
outsideConfig: `[source.crates-io]\nreplace-with = "user-global-vendor"`,
|
|
225
|
-
}), 0);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
test("Cargo contract ignores release caches and build outputs", () => {
|
|
229
|
-
const fixtureRoot = mkdtempSync(path.join(tmpdir(), "rightkit-cargo-scan-"));
|
|
230
|
-
const appRoot = path.join(fixtureRoot, "app");
|
|
231
|
-
mkdirSync(path.join(appRoot, ".right-release", "cache", "cargo-home", "registry", "cached"), { recursive: true });
|
|
232
|
-
writeFileSync(
|
|
233
|
-
path.join(appRoot, "Cargo.toml"),
|
|
234
|
-
'[package]\nname = "fixture"\nversion = "0.0.0"\nedition = "2021"\n[lib]\npath = "fixture.rs"\n',
|
|
235
|
-
"utf8",
|
|
236
|
-
);
|
|
237
|
-
writeFileSync(path.join(appRoot, "fixture.rs"), "", "utf8");
|
|
238
|
-
writeFileSync(
|
|
239
|
-
path.join(appRoot, ".right-release", "cache", "cargo-home", "registry", "cached", "Cargo.toml"),
|
|
240
|
-
"this is deliberately invalid cached TOML",
|
|
241
|
-
"utf8",
|
|
242
|
-
);
|
|
243
|
-
try {
|
|
244
|
-
assert.equal(validateRightKitCargoContract(appRoot, new Map(), "fixture"), 1);
|
|
245
|
-
} finally {
|
|
246
|
-
rmSync(fixtureRoot, { recursive: true, force: true });
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
test("Cargo override contract rejects RightKit patches and replacements in repo-local Cargo config", () => {
|
|
251
|
-
for (const config of [
|
|
252
|
-
{ localConfig: `[patch.crates-io]\nrightkit-license = { path = "../rightkit-license" }` },
|
|
253
|
-
{ localConfig: `patch . "https://github.com/rust-lang/crates.io-index" . "rightkit-logs" = { git = "https://example.test/rightkit-logs.git" }` },
|
|
254
|
-
{ localConfig: `[ replace ]\n"rightkit-license:0.1.1" = { path = "../rightkit-license" }` },
|
|
255
|
-
{ ancestorConfig: `[patch.private-source]\nadapter = { package = "rightkit-license", registry = "private" }` },
|
|
256
|
-
]) {
|
|
257
|
-
assert.throws(
|
|
258
|
-
() => assertCargoOverrideFixture({
|
|
259
|
-
manifest: `[package]\nname = "fixture"\nversion = "0.0.0"\n[dependencies]\nrightkit-license = "=0.1.1"`,
|
|
260
|
-
...config,
|
|
261
|
-
}),
|
|
262
|
-
/forbidden RightKit Cargo override/,
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
test("Cargo override contract rejects path patches, Git patches, and replace entries", () => {
|
|
268
|
-
for (const manifest of [
|
|
269
|
-
`patch . "crates-io" . "rightkit-license" = { path = "../rightkit-license" } # dotted path patch`,
|
|
270
|
-
`[ patch . "https://github.com/rust-lang/crates.io-index" ]\n"rightkit-logs" = { git = "https://example.test/rightkit-logs.git" }`,
|
|
271
|
-
`[ replace ]\n"rightkit-license:0.1.1" = { path = "../rightkit-license" }`,
|
|
272
|
-
]) {
|
|
273
|
-
assert.throws(
|
|
274
|
-
() => assertCargoOverrideFixture({ manifest }),
|
|
275
|
-
/forbidden RightKit Cargo override/,
|
|
276
|
-
);
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
test("Cargo override contract rejects workspace-root patches inherited by a member", () => {
|
|
281
|
-
assert.throws(
|
|
282
|
-
() => assertCargoOverrideFixture({
|
|
283
|
-
manifest: `[package]\nname = "fixture"\nversion = "0.0.0"`,
|
|
284
|
-
workspaceManifest: `[workspace]\nmembers = ["app"]\n[patch.crates-io]\nrightkit-license = { path = "patched/rightkit-license" }`,
|
|
285
|
-
}),
|
|
286
|
-
/forbidden RightKit Cargo override/,
|
|
287
|
-
);
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
test("Cargo override contract rejects local and repo-ancestor crates.io source replacement", () => {
|
|
291
|
-
for (const fixture of [
|
|
292
|
-
{
|
|
293
|
-
localConfig: `source . crates-io . replace-with = "vendored-sources"\n[source.vendored-sources]\ndirectory = "vendor"`,
|
|
294
|
-
},
|
|
295
|
-
{
|
|
296
|
-
ancestorConfig: `[source."crates-io"]\nreplace-with = "rightkit-git"\n[source.rightkit-git]\ngit = "https://example.test/rightkit-index.git"`,
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
ancestorConfig: `[source.crates-io]\nreplace-with = "private-registry"\n[source.private-registry]\nregistry = "https://example.test/index"`,
|
|
300
|
-
},
|
|
301
|
-
]) {
|
|
302
|
-
assert.throws(
|
|
303
|
-
() => assertCargoOverrideFixture({
|
|
304
|
-
manifest: `[package]\nname = "fixture"\nversion = "0.0.0"\n[dependencies]\nrightkit-license = "=0.1.1"`,
|
|
305
|
-
...fixture,
|
|
306
|
-
}),
|
|
307
|
-
/forbidden crates\.io source replacement/,
|
|
308
|
-
);
|
|
309
|
-
}
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
test("direct Cargo dependency contract accepts only published exact RightKit pins", () => {
|
|
313
|
-
const published = new Map([
|
|
314
|
-
["rightkit-license", "0.1.2"],
|
|
315
|
-
["rightkit-logs", "0.1.0"],
|
|
316
|
-
["rightkit-tauri", "0.1.0"],
|
|
317
|
-
]);
|
|
318
|
-
const manifest = `
|
|
319
|
-
[ package ]
|
|
320
|
-
name = "rightkit-tauri"
|
|
321
|
-
# rightkit-tauri = "=0.1.0"
|
|
322
|
-
|
|
323
|
-
[ dependencies ]
|
|
324
|
-
"rightkit-license" = "=0.1.2" # published exact pin
|
|
325
|
-
"rightkit-tauri" = "=0.1.0"
|
|
326
|
-
|
|
327
|
-
[ target . 'cfg(windows)' . dependencies . "rightkit-logs" ]
|
|
328
|
-
version = "=0.1.0"
|
|
329
|
-
|
|
330
|
-
[ target . 'cfg(unix)' . dev-dependencies ]
|
|
331
|
-
license-adapter = { package = "rightkit-license", version = "=0.1.2" }
|
|
332
|
-
`;
|
|
333
|
-
|
|
334
|
-
assert.equal(assertCargoFixture(manifest, published, "fixture/Cargo.toml"), 4);
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
test("direct Cargo dependency contract rejects staged-only RightKit crates", () => {
|
|
338
|
-
const { consumer } = resolveCargoVersionContract(
|
|
339
|
-
{
|
|
340
|
-
cargo: { "rightkit-license": "0.1.2" },
|
|
341
|
-
stagedCargo: { "rightkit-tauri": "0.1.0" },
|
|
342
|
-
},
|
|
343
|
-
new Map([
|
|
344
|
-
["rightkit-license", "0.1.2"],
|
|
345
|
-
["rightkit-tauri", "0.1.0"],
|
|
346
|
-
]),
|
|
347
|
-
);
|
|
348
|
-
assert.equal(consumer.has("rightkit-tauri"), false);
|
|
349
|
-
assert.throws(
|
|
350
|
-
() => assertCargoFixture(
|
|
351
|
-
`dependencies . "rightkit-tauri" = "=0.1.0" # staged only`,
|
|
352
|
-
consumer,
|
|
353
|
-
"fixture/Cargo.toml",
|
|
354
|
-
),
|
|
355
|
-
/fixture\/Cargo\.toml rightkit-tauri is not a published RightKit crate/,
|
|
356
|
-
);
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
test("direct Cargo dependency contract still rejects path, Git, and custom registry sources", () => {
|
|
360
|
-
const published = new Map([
|
|
361
|
-
["rightkit-license", "0.1.1"],
|
|
362
|
-
["rightkit-logs", "0.1.0"],
|
|
363
|
-
]);
|
|
364
|
-
for (const manifest of [
|
|
365
|
-
`dependencies . rightkit-license = { path = "../rightkit-license" }`,
|
|
366
|
-
`target . 'cfg(windows)' . dependencies . "rightkit-logs" = { git = "https://example.test/rightkit.git" }`,
|
|
367
|
-
`dependencies . rightkit-license = { version = "=0.1.1", registry = "private" }`,
|
|
368
|
-
]) {
|
|
369
|
-
assert.throws(
|
|
370
|
-
() => assertCargoFixture(manifest, published, "fixture/Cargo.toml"),
|
|
371
|
-
/must use exact crates\.io versions|must use the exact crates\.io version/,
|
|
372
|
-
);
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
test("Cargo version contract keeps staged versions out of consumer pins", () => {
|
|
377
|
-
const resolved = resolveCargoVersionContract(
|
|
378
|
-
{
|
|
379
|
-
cargo: { "rightkit-license": "0.1.1" },
|
|
380
|
-
stagedCargo: { "rightkit-license": "0.1.2" },
|
|
381
|
-
},
|
|
382
|
-
new Map([["rightkit-license", "0.1.2"]]),
|
|
383
|
-
);
|
|
384
|
-
|
|
385
|
-
assert.equal(resolved.consumer.get("rightkit-license"), "0.1.1");
|
|
386
|
-
assert.equal(resolved.canonical.get("rightkit-license"), "0.1.2");
|
|
387
|
-
});
|
|
388
|
-
|
|
389
|
-
test("Cargo version contract rejects unknown staged crates", () => {
|
|
390
|
-
assert.throws(
|
|
391
|
-
() => resolveCargoVersionContract(
|
|
392
|
-
{ cargo: {}, stagedCargo: { "rightkit-unknown": "0.1.0" } },
|
|
393
|
-
new Map(),
|
|
394
|
-
),
|
|
395
|
-
/unknown staged Cargo crate: rightkit-unknown/,
|
|
396
|
-
);
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
test("Cargo version contract rejects staged versions that mismatch canonical manifests", () => {
|
|
400
|
-
assert.throws(
|
|
401
|
-
() => resolveCargoVersionContract(
|
|
402
|
-
{ cargo: { "rightkit-license": "0.1.1" }, stagedCargo: { "rightkit-license": "0.1.3" } },
|
|
403
|
-
new Map([["rightkit-license", "0.1.2"]]),
|
|
404
|
-
),
|
|
405
|
-
/rightkit-license canonical manifest is 0\.1\.2, expected staged version 0\.1\.3/,
|
|
406
|
-
);
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
test("release package scripts use tier-neutral builds and tiered uploads", () => {
|
|
410
|
-
const scripts = {
|
|
411
|
-
"release:build:mac": "right-release build --platform mac",
|
|
412
|
-
"release:build:win": "right-release build --platform win",
|
|
413
|
-
"release:upload:patch:mac": "right-release upload --platform mac --tier patch",
|
|
414
|
-
"release:upload:patch:win": "right-release upload --platform win --tier patch",
|
|
415
|
-
"release:upload:update:mac": "right-release upload --platform mac --tier update",
|
|
416
|
-
"release:upload:update:win": "right-release upload --platform win --tier update",
|
|
417
|
-
};
|
|
418
|
-
assert.doesNotThrow(() => assertReleasePackageScripts(scripts, "fixture"));
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
test("release package scripts reject a generic direct Tauri alias but allow named local commands", () => {
|
|
422
|
-
const scripts = {
|
|
423
|
-
"release:build:mac": "right-release build --platform mac",
|
|
424
|
-
"release:build:win": "right-release build --platform win",
|
|
425
|
-
"release:upload:patch:mac": "right-release upload --platform mac --tier patch",
|
|
426
|
-
"release:upload:patch:win": "right-release upload --platform win --tier patch",
|
|
427
|
-
"release:upload:update:mac": "right-release upload --platform mac --tier update",
|
|
428
|
-
"release:upload:update:win": "right-release upload --platform win --tier update",
|
|
429
|
-
"tauri:dev": "tauri dev",
|
|
430
|
-
"mac:build:debug": "tauri build --debug",
|
|
431
|
-
"build:win:unsigned": "tauri build --bundles nsis --no-sign",
|
|
432
|
-
"cargo:check": "cargo check --locked",
|
|
433
|
-
};
|
|
434
|
-
assert.doesNotThrow(() => assertReleasePackageScripts(scripts, "fixture"));
|
|
435
|
-
for (const genericTauri of ["tauri", "pnpm exec tauri", "pnpm dlx tauri", "./node_modules/.bin/tauri"]) {
|
|
436
|
-
assert.throws(
|
|
437
|
-
() => assertReleasePackageScripts({ ...scripts, tauri: genericTauri }, "fixture"),
|
|
438
|
-
/generic \"tauri\" package script bypasses/i,
|
|
439
|
-
genericTauri,
|
|
440
|
-
);
|
|
441
|
-
}
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
test("mac release config uses a dedicated non-recursive package entry point", () => {
|
|
445
|
-
const command = { cmd: "pnpm", args: ["run", "rightkit:package:mac"] };
|
|
446
|
-
assert.doesNotThrow(() => assertMacPackageEntry(command, { "rightkit:package:mac": "node scripts/mac-dmg.mjs --notarize" }, "fixture"));
|
|
447
|
-
assert.doesNotThrow(() => assertMacPackageEntry(
|
|
448
|
-
{ cmd: "pnpm", args: ["run", "rightkit:package:mac", "--", "--notarize"] },
|
|
449
|
-
{ "rightkit:package:mac": "node scripts/mac-dmg.mjs" },
|
|
450
|
-
"fixture",
|
|
451
|
-
));
|
|
452
|
-
assert.throws(
|
|
453
|
-
() => assertMacPackageEntry(command, { "rightkit:package:mac": "right-release build --platform mac" }, "fixture"),
|
|
454
|
-
/instead of recursing into the release build/i,
|
|
455
|
-
);
|
|
456
|
-
assert.throws(
|
|
457
|
-
() => assertMacPackageEntry(command, { "rightkit:package:mac": "pnpm run rightkit:package:mac" }, "fixture"),
|
|
458
|
-
/must not recurse into itself/i,
|
|
459
|
-
);
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
test("every app platform requires effective non-empty build inputs", () => {
|
|
463
|
-
assert.doesNotThrow(() => assertBuildInputs(
|
|
464
|
-
{ buildInputs: { include: ["src/**"] } },
|
|
465
|
-
{},
|
|
466
|
-
"fixture mac",
|
|
467
|
-
));
|
|
468
|
-
assert.throws(() => assertBuildInputs({}, {}, "fixture win"), /fixture win must declare non-empty buildInputs\.include paths/);
|
|
469
|
-
assert.throws(() => assertBuildInputs({}, { buildInputs: { include: [] } }, "fixture mac"), /fixture mac must declare non-empty buildInputs\.include paths/);
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
test("RightKit exposes one current version manifest", () => {
|
|
473
|
-
assert.equal(existsSync(versionsPath), true, "rightkit-versions.json must be the single current-version source");
|
|
474
|
-
assert.equal(versions.schema, 2);
|
|
475
|
-
assert.match(versions.packageManager, /^pnpm@\d+\.\d+\.\d+$/);
|
|
476
|
-
assert.equal(versions.npm["@rightkit/release"], "0.2.47");
|
|
477
|
-
assert.equal(versions.npm["@rightkit/legal"], "0.2.0");
|
|
478
|
-
assert.equal(versions.npm["@rightkit/license"], "0.1.5");
|
|
479
|
-
assert.equal(versions.npm["@rightkit/logs"], "0.1.3");
|
|
480
|
-
assert.equal(versions.npm["@rightkit/tauri"], "0.1.0");
|
|
481
|
-
assert.equal(versions.npm["@rightkit/updates"], "0.2.3");
|
|
482
|
-
assert.deepEqual(versions.stagedNpm, {
|
|
483
|
-
"@rightkit/ax": "0.2.0",
|
|
484
|
-
"@rightkit/git": "0.2.1",
|
|
485
|
-
"@rightkit/hooks": "0.1.1",
|
|
486
|
-
"@rightkit/legal": "0.3.1",
|
|
487
|
-
"@rightkit/legal-ui": "0.1.1",
|
|
488
|
-
"@rightkit/license": "0.1.7",
|
|
489
|
-
"@rightkit/logs": "0.1.4",
|
|
490
|
-
"@rightkit/platform-ui": "0.1.1",
|
|
491
|
-
"@rightkit/qa": "0.2.1",
|
|
492
|
-
"@rightkit/release": "0.2.69",
|
|
493
|
-
"@rightkit/tauri": "0.1.1",
|
|
494
|
-
"@rightkit/updates": "0.2.4",
|
|
495
|
-
});
|
|
496
|
-
assert.deepEqual(versions.legacyNpm, {
|
|
497
|
-
"@rightkit/legal-ui": ["0.1.0"],
|
|
498
|
-
"@rightkit/hooks": ["0.1.0"],
|
|
499
|
-
"@rightkit/legal": ["0.3.0"],
|
|
500
|
-
"@rightkit/license": ["0.1.6"],
|
|
501
|
-
"@rightkit/release": ["0.2.22", "0.2.29", "0.2.30", "0.2.31", "0.2.41", "0.2.42", "0.2.43", "0.2.44", "0.2.45", "0.2.46", "0.2.49", "0.2.50", "0.2.51", "0.2.53", "0.2.54", "0.2.55", "0.2.56", "0.2.61", "0.2.62", "0.2.63", "0.2.64", "0.2.65", "0.2.66", "0.2.67", "0.2.68"],
|
|
502
|
-
"@rightkit/qa": ["0.1.0", "0.2.0"],
|
|
503
|
-
});
|
|
504
|
-
assert.ok(
|
|
505
|
-
new Set([versions.npm["@rightkit/release"], ...versions.legacyNpm["@rightkit/release"]]).has("0.2.42"),
|
|
506
|
-
"previously published @rightkit/release versions must remain accepted during the 0.2.46 rollout",
|
|
507
|
-
);
|
|
508
|
-
for (const [name, version] of Object.entries(versions.stagedNpm)) {
|
|
509
|
-
const packageName = name.slice("@rightkit/".length);
|
|
510
|
-
const manifest = JSON.parse(readFileSync(
|
|
511
|
-
path.join(workspace, "tools/rightkit/packages", packageName, "package.json"),
|
|
512
|
-
"utf8",
|
|
513
|
-
));
|
|
514
|
-
assert.equal(manifest.name, name);
|
|
515
|
-
assert.equal(manifest.version, version, `${name} package version must equal stagedNpm`);
|
|
516
|
-
}
|
|
517
|
-
assert.equal(versions.cargo["rightkit-license"], "0.1.2");
|
|
518
|
-
assert.equal(versions.cargo["rightkit-logs"], "0.1.0");
|
|
519
|
-
assert.equal(versions.cargo["rightkit-tauri"], "0.1.0");
|
|
520
|
-
assert.deepEqual(versions.stagedCargo, {
|
|
521
|
-
"rightkit-license": "0.1.3",
|
|
522
|
-
"rightkit-tauri": "0.1.1",
|
|
523
|
-
});
|
|
524
|
-
getCurrentCargoVersionContract();
|
|
525
|
-
});
|
|
526
|
-
|
|
527
|
-
test("Cargo metadata uses managed Cargo directly on Windows", () => {
|
|
528
|
-
assert.equal(cargoExecutable("win32"), "cargo");
|
|
529
|
-
assert.deepEqual(cargoArguments(["metadata"], "win32"), ["metadata"]);
|
|
530
|
-
assert.equal(cargoExecutable("darwin"), "cargo");
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
test("Cargo metadata delegates controlled storage to managed RightKit", () => {
|
|
534
|
-
const ambient = {
|
|
535
|
-
CARGO_HOME: "/ambient/cargo",
|
|
536
|
-
CARGO_TARGET_DIR: "/ambient/target",
|
|
537
|
-
RIGHTKIT_BUILD_BROKER_SOCKET: "/managed/broker.sock",
|
|
538
|
-
};
|
|
539
|
-
assert.deepEqual(isolatedCargoMetadataEnv("/isolated/cargo", ambient), {
|
|
540
|
-
RIGHTKIT_BUILD_BROKER_SOCKET: "/managed/broker.sock",
|
|
541
|
-
});
|
|
542
|
-
assert.deepEqual(isolatedCargoMetadataEnv("/isolated/cargo", { CARGO_HOME: "/ambient/cargo" }), {
|
|
543
|
-
CARGO_HOME: "/isolated/cargo",
|
|
544
|
-
});
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
test("Cargo metadata recognizes managed Cargo from PATH without inherited broker environment", () => {
|
|
548
|
-
const macShim = "/Volumes/D/.rightkit-managed/agent-bin/cargo";
|
|
549
|
-
const macEnv = { PATH: `/usr/bin:${path.dirname(macShim)}`, CARGO_HOME: "" };
|
|
550
|
-
assert.equal(managedCargoShimOnPath(macEnv, "darwin", (candidate) => candidate === macShim), true);
|
|
551
|
-
assert.deepEqual(isolatedCargoMetadataEnv("/isolated/cargo", macEnv, "darwin", (candidate) => candidate === macShim), {
|
|
552
|
-
PATH: macEnv.PATH,
|
|
553
|
-
});
|
|
554
|
-
|
|
555
|
-
const windowsShim = "D:\\RightKitManagedAgent\\agent-bin\\cargo.cmd";
|
|
556
|
-
const windowsEnv = {
|
|
557
|
-
PATH: "C:\\Windows\\System32;D:\\RightKitManagedAgent\\agent-bin",
|
|
558
|
-
PATHEXT: ".EXE;.CMD",
|
|
559
|
-
};
|
|
560
|
-
assert.equal(managedCargoShimOnPath(windowsEnv, "win32", (candidate) => candidate.toLowerCase() === windowsShim.toLowerCase()), true);
|
|
561
|
-
assert.deepEqual(isolatedCargoMetadataEnv("D:\\isolated\\cargo", windowsEnv, "win32", (candidate) => candidate.toLowerCase() === windowsShim.toLowerCase()), windowsEnv);
|
|
562
|
-
});
|
|
563
|
-
|
|
564
|
-
test("Cargo metadata respects PATH precedence when unmanaged Cargo resolves first", () => {
|
|
565
|
-
const env = { PATH: "/usr/local/bin:/Volumes/D/.rightkit-managed/agent-bin" };
|
|
566
|
-
const existing = new Set([
|
|
567
|
-
"/usr/local/bin/cargo",
|
|
568
|
-
"/Volumes/D/.rightkit-managed/agent-bin/cargo",
|
|
569
|
-
]);
|
|
570
|
-
assert.equal(managedCargoShimOnPath(env, "darwin", (candidate) => existing.has(candidate)), false);
|
|
571
|
-
assert.deepEqual(isolatedCargoMetadataEnv("/isolated/cargo", env, "darwin", (candidate) => existing.has(candidate)), {
|
|
572
|
-
PATH: env.PATH,
|
|
573
|
-
CARGO_HOME: "/isolated/cargo",
|
|
574
|
-
});
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
test("license v2 public vector is identical at every portable consumer boundary", () => {
|
|
578
|
-
const canonical = readFileSync(
|
|
579
|
-
path.join(workspace, "tools/rightkit/crates/rightkit-license/test-vectors/license-v2.json"),
|
|
580
|
-
"utf8",
|
|
581
|
-
);
|
|
582
|
-
for (const relativePath of [
|
|
583
|
-
"tools/rightkit/packages/license/test-vectors/license-v2.json",
|
|
584
|
-
`${siteRepoDir}/packages/api/src/licensing/test-vectors/license-v2.json`,
|
|
585
|
-
"scraperight/tests/fixtures/license-v2.json",
|
|
586
|
-
]) {
|
|
587
|
-
assert.equal(
|
|
588
|
-
readFileSync(path.join(workspace, relativePath), "utf8"),
|
|
589
|
-
canonical,
|
|
590
|
-
`${relativePath} must be the canonical public license vector byte-for-byte`,
|
|
591
|
-
);
|
|
592
|
-
}
|
|
593
|
-
});
|
|
594
|
-
|
|
595
|
-
for (const app of apps) {
|
|
596
|
-
test(`${app.key} follows the signed tiered Right Release contract`, async () => {
|
|
597
|
-
const root = path.join(workspace, app.root);
|
|
598
|
-
const pkg = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8"));
|
|
599
|
-
const rightKitDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
600
|
-
for (const [name, specifier] of Object.entries(rightKitDeps).filter(([name]) => name.startsWith("@rightkit/"))) {
|
|
601
|
-
assert.doesNotMatch(specifier, /^(?:git|file|link|workspace):|github/i, `${app.key} ${name} must come from the published npm package`);
|
|
602
|
-
const allowed = new Set(
|
|
603
|
-
[
|
|
604
|
-
versions.npm[name],
|
|
605
|
-
versions.stagedNpm?.[name],
|
|
606
|
-
...(versions.legacyNpm?.[name] ?? []),
|
|
607
|
-
].filter(Boolean),
|
|
608
|
-
);
|
|
609
|
-
if (allowed.size) assert.ok(allowed.has(specifier), `${app.key} ${name} must match a published rollout version`);
|
|
610
|
-
}
|
|
611
|
-
const releaseVersion = pkg.devDependencies?.["@rightkit/release"];
|
|
612
|
-
const acceptedPackageManagers = releaseVersion === versions.stagedNpm?.["@rightkit/release"]
|
|
613
|
-
? [versions.packageManager]
|
|
614
|
-
: [versions.packageManager, "pnpm@11.12.0"];
|
|
615
|
-
assert.ok(
|
|
616
|
-
acceptedPackageManagers.includes(pkg.packageManager),
|
|
617
|
-
`${app.key} packageManager must match its @rightkit/release rollout lane`,
|
|
618
|
-
);
|
|
619
|
-
assert.ok(
|
|
620
|
-
new Set([
|
|
621
|
-
versions.npm["@rightkit/release"],
|
|
622
|
-
versions.stagedNpm?.["@rightkit/release"],
|
|
623
|
-
...(versions.legacyNpm?.["@rightkit/release"] ?? []),
|
|
624
|
-
]).has(pkg.devDependencies?.["@rightkit/release"]),
|
|
625
|
-
);
|
|
626
|
-
assert.equal(
|
|
627
|
-
pkg.dependencies?.["@rightkit/updates"],
|
|
628
|
-
versions.npm["@rightkit/updates"],
|
|
629
|
-
`${app.key} must consume the exact published shared updater runtime`,
|
|
630
|
-
);
|
|
631
|
-
assert(!JSON.stringify(pkg).includes("github:adrdsouza/claude#main&path:/tools/right-release"));
|
|
632
|
-
assert(!JSON.stringify(pkg).includes("github:adrdsouza/claude#main&path:/tools/rightkit/packages/release"));
|
|
633
|
-
assert(!JSON.stringify(pkg).includes("git+https://github.com/adrdsouza/rightkit.git"));
|
|
634
|
-
assert.equal(pkg.scripts["release:doctor"], "right-release doctor");
|
|
635
|
-
assert.equal(pkg.scripts["release:mac"], undefined, "tierless release entry points are forbidden");
|
|
636
|
-
assert.equal(pkg.scripts["release:win"], undefined, "tierless release entry points are forbidden");
|
|
637
|
-
assertReleasePackageScripts(pkg.scripts, app.key);
|
|
638
|
-
assert.equal(pkg.scripts["deps:check"], "right-release deps --check");
|
|
639
|
-
assert.equal(pkg.scripts["deps:update"], "right-release deps --update");
|
|
640
|
-
assert.ok(!Object.entries(pkg.scripts).some(([name, command]) => /^(?:release|publish):/i.test(name) && /unsigned|--no-sign/i.test(command)), `${app.key} release/publish commands must not expose an unsigned macOS DMG mode`);
|
|
641
|
-
assert.ok(!JSON.stringify(pkg.scripts).includes("../tools/right-release"), `${app.key} scripts must not depend on the parent Claude workspace`);
|
|
642
|
-
assert.ok(!JSON.stringify(pkg.scripts).includes("../tools/rightkit/packages/release"), `${app.key} scripts must not depend on the parent Claude workspace`);
|
|
643
|
-
|
|
644
|
-
const config = (await import(`${pathToFileURL(path.join(root, "right-release.config.mjs"))}?contract=${Date.now()}`)).default;
|
|
645
|
-
assert.equal(config.app, app.key);
|
|
646
|
-
assert.ok(config.version);
|
|
647
|
-
for (const platform of ["mac", "win"]) {
|
|
648
|
-
const target = config.targets[platform];
|
|
649
|
-
assertBuildInputs(config, target, `${app.key} ${platform}`);
|
|
650
|
-
assert.equal(target.signed, true);
|
|
651
|
-
assert.equal(target.upload, undefined, "generic uploads bypass tier manifest routing");
|
|
652
|
-
assert.equal(target.publish.cmd, "right-release");
|
|
653
|
-
assert.match(target.publish.args.join(" "), /^publish-update\b/);
|
|
654
|
-
assert.ok(new Set(target.updater.artifacts.map((artifact) => artifact.key)).size <= 1, `${app.key} ${platform} must expose at most one current updater R2 object key`);
|
|
655
|
-
assert.ok(new Set(target.installer.artifacts.map((artifact) => artifact.key)).size <= 1, `${app.key} ${platform} must expose at most one current installer R2 object key`);
|
|
656
|
-
for (const installer of target.installer.artifacts) {
|
|
657
|
-
assert.match(installer.key, /\/installers\/(mac|windows)\/current\//, `${app.key} ${platform} installers must replace the stable current R2 object`);
|
|
658
|
-
}
|
|
659
|
-
for (const updater of target.updater.artifacts) {
|
|
660
|
-
assert.match(updater.key, /\/updates\/(mac|windows)\/current\//, `${app.key} ${platform} updaters must replace the stable current R2 object`);
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
assertMacPackageEntry(config.targets.mac.package, pkg.scripts, app.key);
|
|
664
|
-
for (const installer of config.targets.mac.installer.artifacts) {
|
|
665
|
-
assert.equal(path.dirname(installer.file), ".", `${app.key} macOS installer must be copied to the app package root before upload`);
|
|
666
|
-
}
|
|
667
|
-
assert.ok(config.targets.win.sign.files.length);
|
|
668
|
-
const winUpdaterFiles = new Set(config.targets.win.updater.artifacts.map((artifact) => artifact.file));
|
|
669
|
-
for (const signed of config.targets.win.sign.files) assert.ok(winUpdaterFiles.has(signed), `${signed} must be both Azure-signed and updater-signed`);
|
|
670
|
-
|
|
671
|
-
const tauri = JSON.parse(readFileSync(path.join(root, app.tauri), "utf8"));
|
|
672
|
-
assert.equal(tauri.plugins.updater.pubkey, pubkey);
|
|
673
|
-
assert.deepEqual(tauri.plugins.updater.endpoints, [
|
|
674
|
-
`https://api.spoares.com/v1/apps/${app.key}/releases/latest.json?platform={{target}}`,
|
|
675
|
-
]);
|
|
676
|
-
assert.equal(tauri.bundle.createUpdaterArtifacts, true);
|
|
677
|
-
|
|
678
|
-
const { consumer, canonical } = getCurrentCargoVersionContract();
|
|
679
|
-
const rollout = new Map([...consumer].map(([name, version]) => [name, new Set([version, canonical.get(name)].filter(Boolean))]));
|
|
680
|
-
validateRightKitCargoContract(root, rollout, app.key);
|
|
681
|
-
|
|
682
|
-
for (const localCopy of [
|
|
683
|
-
"src-tauri/vendor/rightkit-license",
|
|
684
|
-
"src-tauri/vendor/rightkit-logs",
|
|
685
|
-
"crates/rightkit-license",
|
|
686
|
-
]) {
|
|
687
|
-
assert.equal(
|
|
688
|
-
existsSync(path.join(root, localCopy)),
|
|
689
|
-
false,
|
|
690
|
-
`${app.key} must not carry an app-local ${localCopy} copy`,
|
|
691
|
-
);
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
const repoRoot = path.join(workspace, app.repoRoot ?? app.root);
|
|
695
|
-
for (const packagePath of findFiles(repoRoot, "package.json")) {
|
|
696
|
-
const candidate = JSON.parse(readFileSync(packagePath, "utf8"));
|
|
697
|
-
assert.equal(candidate.scripts?.["release:win"], undefined, `${path.relative(workspace, packagePath)} has a forbidden tierless Windows release script`);
|
|
698
|
-
assert.equal(candidate.scripts?.["release:mac"], undefined, `${path.relative(workspace, packagePath)} has a forbidden tierless macOS release script`);
|
|
699
|
-
for (const command of Object.values(candidate.scripts ?? {})) {
|
|
700
|
-
assert.doesNotMatch(command, /\brelease:(?:win|mac)\b/, `${path.relative(workspace, packagePath)} delegates to a forbidden tierless release command`);
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
for (const instructionName of ["AGENTS.md", "CLAUDE.md"]) {
|
|
704
|
-
const instructionPath = path.join(repoRoot, instructionName);
|
|
705
|
-
if (!existsSync(instructionPath)) continue;
|
|
706
|
-
const instruction = readFileSync(instructionPath, "utf8");
|
|
707
|
-
assert.doesNotMatch(instruction, /pnpm(?: run)? release:(?:win|mac)\b/, `${app.key} ${instructionName} documents a forbidden tierless release`);
|
|
708
|
-
assert.doesNotMatch(instruction, /shared tooling at [`']?\.\.\/tools\/right-release/i, `${app.key} ${instructionName} documents a sibling source dependency`);
|
|
709
|
-
assert.doesNotMatch(instruction, /\$env:RIGHTAPPS_ADMIN_TOKEN|pnpm publish:r2/, `${app.key} ${instructionName} documents obsolete release credentials or publishers`);
|
|
710
|
-
}
|
|
711
|
-
for (const releaseFile of app.releaseFiles) {
|
|
712
|
-
const source = readFileSync(path.join(root, releaseFile), "utf8");
|
|
713
|
-
assert.doesNotMatch(source, /(?:\.\.\/)+tools\/right-release|tools\/right-release\//, `${app.key} ${releaseFile} must consume the installed package`);
|
|
714
|
-
assert.match(source, /right-release["']?,?\s*["']mirror-root-artifact|right-release mirror-root-artifact/, `${app.key} ${releaseFile} must mirror the final DMG to the canonical package root`);
|
|
715
|
-
}
|
|
716
|
-
});
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
for (const app of macOnlyApps) {
|
|
720
|
-
test(`${app.key} follows the macOS-only AppKit Right Release contract`, async (context) => {
|
|
721
|
-
const root = path.join(workspace, app.root);
|
|
722
|
-
if (!existsSync(path.join(root, "package.json"))) {
|
|
723
|
-
context.skip(`${app.key} is not present in this checkout`);
|
|
724
|
-
return;
|
|
725
|
-
}
|
|
726
|
-
const pkg = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8"));
|
|
727
|
-
assert.equal(pkg.scripts["release:doctor"], "right-release doctor");
|
|
728
|
-
assert.equal(pkg.scripts["release:build:mac"], "right-release build --platform mac");
|
|
729
|
-
assert.equal(pkg.scripts["release:upload:patch:mac"], "right-release upload --platform mac --tier patch");
|
|
730
|
-
assert.equal(pkg.scripts["release:build:win"], undefined, `${app.key} must not fake a Windows target`);
|
|
731
|
-
assert.equal(pkg.scripts["release:upload:patch:win"], undefined, `${app.key} must not fake a Windows target`);
|
|
732
|
-
assert.equal(pkg.scripts["release:upload:update:mac"], undefined, `${app.key} must not expose ungated feature-update upload`);
|
|
733
|
-
assert.equal(pkg.scripts["release:upload:update:win"], undefined);
|
|
734
|
-
|
|
735
|
-
const config = (await import(`${pathToFileURL(path.join(root, "right-release.config.mjs"))}?mac-only=${Date.now()}`)).default;
|
|
736
|
-
assert.equal(config.app, app.key);
|
|
737
|
-
assert.deepEqual(Object.keys(config.targets), ["mac"]);
|
|
738
|
-
assert.equal(config.targets.mac.signed, true);
|
|
739
|
-
assert.deepEqual(config.targets.mac.publish, {
|
|
740
|
-
cmd: "right-release",
|
|
741
|
-
args: ["publish-update", "--config", "right-release.config.mjs", "--platform", "mac"],
|
|
742
|
-
});
|
|
743
|
-
const updaters = config.targets.mac.updater.artifacts;
|
|
744
|
-
assert.equal(updaters.length, 2);
|
|
745
|
-
assert.deepEqual(updaters.map((updater) => updater.platform).sort(), ["darwin-aarch64", "darwin-x86_64"]);
|
|
746
|
-
assert.equal(new Set(updaters.map((updater) => updater.file)).size, 1, `${app.key} universal updater must share one DMG`);
|
|
747
|
-
assert.equal(new Set(updaters.map((updater) => updater.signature)).size, 1, `${app.key} universal updater must share one signature`);
|
|
748
|
-
assert.equal(new Set(updaters.map((updater) => updater.key)).size, 1, `${app.key} universal updater must share one current R2 object`);
|
|
749
|
-
for (const updater of updaters) {
|
|
750
|
-
assert.match(updater.file, /\.dmg$/);
|
|
751
|
-
assert.equal(updater.signature, `${updater.file}.sig`);
|
|
752
|
-
assert.equal(updater.key, `${app.key}/updates/mac/current/ScreenRight.dmg`);
|
|
753
|
-
}
|
|
754
|
-
assertBuildInputs(config, config.targets.mac, `${app.key} mac`);
|
|
755
|
-
assertMacPackageEntry(config.targets.mac.package, pkg.scripts, app.key);
|
|
756
|
-
assert.ok(config.targets.mac.installer.artifacts.length >= 1);
|
|
757
|
-
assert.ok(config.checks.includes("legal:check"), `${app.key} must gate generated legal notices`);
|
|
758
|
-
assert.deepEqual(config.deps, { workdirs: ["."] });
|
|
759
|
-
assert.equal(existsSync(path.join(root, "src-tauri", "tauri.conf.json")), false, `${app.key} must not invent a Tauri manifest`);
|
|
760
|
-
for (const releaseFile of app.releaseFiles) {
|
|
761
|
-
const source = readFileSync(path.join(root, releaseFile), "utf8");
|
|
762
|
-
assert.match(source, /mirror-root-artifact/);
|
|
763
|
-
}
|
|
764
|
-
});
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
test("HeardRight and ScrapeRight expose one locked ASR promotion adapter contract", async () => {
|
|
768
|
-
const heard = (await import(`${pathToFileURL(path.join(workspace, "heardright/tauri-app-next/right-release.config.mjs"))}?asr=${Date.now()}`)).default;
|
|
769
|
-
const scrape = (await import(`${pathToFileURL(path.join(workspace, "scraperight/right-release.config.mjs"))}?asr=${Date.now()}`)).default;
|
|
770
|
-
assert.equal(assertAsrAdapterPair(heard.runtimeArtifacts?.asr, scrape.runtimeArtifacts?.asr), true);
|
|
771
|
-
});
|
|
772
|
-
|
|
773
|
-
function findFiles(root, filename) {
|
|
774
|
-
const found = [];
|
|
775
|
-
const visit = (dir) => {
|
|
776
|
-
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
777
|
-
if (entry.isDirectory() && [".audit", ".cache", ".git", ".claude", ".worktrees", "node_modules", "target", "vendor"].includes(entry.name)) continue;
|
|
778
|
-
const full = path.join(dir, entry.name);
|
|
779
|
-
if (entry.isDirectory()) visit(full);
|
|
780
|
-
else if (entry.isFile() && entry.name === filename) found.push(full);
|
|
781
|
-
}
|
|
782
|
-
};
|
|
783
|
-
visit(root);
|
|
784
|
-
return found;
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
function readCanonicalCrateVersions() {
|
|
788
|
-
const crateRoot = path.join(workspace, "tools/rightkit/crates");
|
|
789
|
-
return new Map(
|
|
790
|
-
readdirSync(crateRoot, { withFileTypes: true })
|
|
791
|
-
.filter((entry) => entry.isDirectory() && existsSync(path.join(crateRoot, entry.name, "Cargo.toml")))
|
|
792
|
-
.map((entry) => {
|
|
793
|
-
const manifest = readFileSync(path.join(crateRoot, entry.name, "Cargo.toml"), "utf8");
|
|
794
|
-
const version = manifest.match(/^version\s*=\s*"([^"]+)"$/m)?.[1];
|
|
795
|
-
assert.ok(version, `${entry.name} canonical manifest must declare a package version`);
|
|
796
|
-
return [entry.name, version];
|
|
797
|
-
}),
|
|
798
|
-
);
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
const CARGO_TARGET_DIR_GUARD_EXTENSIONS = new Set([".mjs", ".js", ".ts", ".sh", ".ps1"]);
|
|
802
|
-
const CARGO_TARGET_DIR_GUARD_ALLOW_MARKER = /rightkit-allow-cargo-target-dir:\s*\S/;
|
|
803
|
-
// Test/contract files assert *about* the CARGO_TARGET_DIR pattern (e.g. inside
|
|
804
|
-
// a regex literal passed to assert.match/assert.doesNotMatch) rather than
|
|
805
|
-
// locating build output with it; they are not packaging/build scripts.
|
|
806
|
-
const CARGO_TARGET_DIR_GUARD_SKIP_BASENAME = /(?:^test-.*|\.test)\.(?:mjs|js|ts)$/;
|
|
807
|
-
|
|
808
|
-
function cargoTargetDirGuardPatternFor(extension) {
|
|
809
|
-
if (extension === ".ps1") return /\$env:CARGO_TARGET_DIR\b/;
|
|
810
|
-
if (extension === ".sh") return /\$\{?CARGO_TARGET_DIR\b/;
|
|
811
|
-
return /process\.env(?:\.CARGO_TARGET_DIR\b|\[["']CARGO_TARGET_DIR["']\])/;
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
function findCargoTargetDirGuardFiles(root) {
|
|
815
|
-
const found = [];
|
|
816
|
-
const visit = (dir) => {
|
|
817
|
-
if (!existsSync(dir)) return;
|
|
818
|
-
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
819
|
-
if (entry.isDirectory() && ["node_modules", "target", "vendor", ".git", ".cache", ".right-release"].includes(entry.name)) continue;
|
|
820
|
-
const full = path.join(dir, entry.name);
|
|
821
|
-
if (entry.isDirectory()) visit(full);
|
|
822
|
-
else if (entry.isFile() && CARGO_TARGET_DIR_GUARD_EXTENSIONS.has(path.extname(entry.name))) found.push(full);
|
|
823
|
-
}
|
|
824
|
-
};
|
|
825
|
-
const scriptsDir = path.join(root, "scripts");
|
|
826
|
-
if (existsSync(scriptsDir)) visit(scriptsDir);
|
|
827
|
-
for (const topLevel of ["package.sh", "package.ps1"]) {
|
|
828
|
-
const candidate = path.join(root, topLevel);
|
|
829
|
-
if (existsSync(candidate)) found.push(candidate);
|
|
830
|
-
}
|
|
831
|
-
return found;
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
test("consuming suite apps resolve Cargo build output from cargo metadata, never CARGO_TARGET_DIR directly", () => {
|
|
835
|
-
for (const appRoot of cargoTargetDirGuardApps) {
|
|
836
|
-
const root = path.join(workspace, appRoot);
|
|
837
|
-
if (!existsSync(root)) continue;
|
|
838
|
-
for (const filePath of findCargoTargetDirGuardFiles(root)) {
|
|
839
|
-
const basename = path.basename(filePath);
|
|
840
|
-
if (CARGO_TARGET_DIR_GUARD_SKIP_BASENAME.test(basename)) continue;
|
|
841
|
-
const extension = path.extname(filePath);
|
|
842
|
-
const pattern = cargoTargetDirGuardPatternFor(extension);
|
|
843
|
-
const lines = readFileSync(filePath, "utf8").split("\n");
|
|
844
|
-
const relativePath = path.relative(workspace, filePath);
|
|
845
|
-
lines.forEach((line, index) => {
|
|
846
|
-
if (!pattern.test(line)) return;
|
|
847
|
-
if (/^\s*(?:\/\/|#)/.test(line)) return; // prose describing the pattern, not code reading it
|
|
848
|
-
const previousLine = index > 0 ? lines[index - 1] : "";
|
|
849
|
-
const allowed = CARGO_TARGET_DIR_GUARD_ALLOW_MARKER.test(line) || CARGO_TARGET_DIR_GUARD_ALLOW_MARKER.test(previousLine);
|
|
850
|
-
assert.ok(
|
|
851
|
-
allowed,
|
|
852
|
-
`${relativePath}:${index + 1} reads CARGO_TARGET_DIR directly to locate Cargo build output: \`${line.trim()}\`\n`
|
|
853
|
-
+ "resolve build output from `cargo metadata`'s `target_directory`; the environment is never authoritative for locating output.\n"
|
|
854
|
-
+ "add a `rightkit-allow-cargo-target-dir: <reason>` marker on this line (or the line above) only if this use is not locating output.",
|
|
855
|
-
);
|
|
856
|
-
});
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
});
|
|
860
|
-
|
|
861
|
-
// The shared resolver helpers themselves must keep asking cargo metadata for
|
|
862
|
-
// target_directory. Guarding only the wrong pattern's reintroduction is not
|
|
863
|
-
// enough — gutting/deleting the correct implementation must also fail here.
|
|
864
|
-
const cargoTargetRootHelpers = [
|
|
865
|
-
"coderight/apps/coderight-tauri/scripts/lib/target-root.mjs",
|
|
866
|
-
"heardright/tauri-app-next/scripts/lib/target-root.mjs",
|
|
867
|
-
"genright/scripts/lib/target-root.mjs",
|
|
868
|
-
"mailright/scripts/lib/target-root.mjs",
|
|
869
|
-
"orthic/scripts/lib/target-root.mjs",
|
|
870
|
-
"viewright/scripts/lib/target-root.mjs",
|
|
871
|
-
"membrane/apps/membrane-hub/scripts/lib/target-root.mjs",
|
|
872
|
-
];
|
|
873
|
-
|
|
874
|
-
test("consumer target-root helpers delegate to RightKit's canonical resolver", () => {
|
|
875
|
-
for (const helperPath of cargoTargetRootHelpers) {
|
|
876
|
-
const appRoot = path.join(workspace, helperPath.split("/scripts/lib/target-root.mjs")[0]);
|
|
877
|
-
if (!existsSync(path.join(appRoot, "package.json"))) continue;
|
|
878
|
-
const fullPath = path.join(workspace, helperPath);
|
|
879
|
-
assert.ok(existsSync(fullPath), `${helperPath} is missing; the app must keep its shared cargo-metadata target resolver`);
|
|
880
|
-
const source = readFileSync(fullPath, "utf8");
|
|
881
|
-
assert.match(source, /@rightkit\/release\/cargo-target\.mjs/, `${helperPath} must import RightKit's resolver`);
|
|
882
|
-
assert.match(source, /resolveTargetRoot/, `${helperPath} must delegate target resolution to RightKit`);
|
|
883
|
-
}
|
|
884
|
-
});
|
|
885
|
-
|
|
886
|
-
test("consuming app target-root helpers do not reimplement Cargo metadata", () => {
|
|
887
|
-
const LOCAL_RESOLVER_PATTERN = /function\s+(?:cargoTargetRoot|resolveManagedCargoTarget)\s*\([^)]*\)\s*\{[^}]*cargo[^}]*metadata/s;
|
|
888
|
-
for (const helperPath of cargoTargetRootHelpers) {
|
|
889
|
-
const appRoot = path.join(workspace, helperPath.split("/scripts/lib/target-root.mjs")[0]);
|
|
890
|
-
if (!existsSync(appRoot)) continue;
|
|
891
|
-
const fullPath = path.join(workspace, helperPath);
|
|
892
|
-
if (!existsSync(fullPath)) continue;
|
|
893
|
-
const source = readFileSync(fullPath, "utf8");
|
|
894
|
-
assert.doesNotMatch(
|
|
895
|
-
source,
|
|
896
|
-
LOCAL_RESOLVER_PATTERN,
|
|
897
|
-
`${helperPath} must re-export @rightkit/release's resolveTargetRoot instead of reimplementing the cargo metadata call locally`,
|
|
898
|
-
);
|
|
899
|
-
}
|
|
900
|
-
});
|
|
901
|
-
|
|
902
|
-
const cargoAuthorityRoots = [
|
|
903
|
-
...cargoTargetDirGuardApps,
|
|
904
|
-
"citadel",
|
|
905
|
-
"heardright",
|
|
906
|
-
"legion",
|
|
907
|
-
"rightsites",
|
|
908
|
-
"rightsuite",
|
|
909
|
-
"sellright",
|
|
910
|
-
"tools/screenright",
|
|
911
|
-
"voiceright",
|
|
912
|
-
"workright",
|
|
913
|
-
];
|
|
914
|
-
const cargoAuthorityNames = [
|
|
915
|
-
"CARGO_HOME",
|
|
916
|
-
"CARGO_TARGET_DIR",
|
|
917
|
-
"CARGO_BUILD_TARGET_DIR",
|
|
918
|
-
"CARGO_BUILD_BUILD_DIR",
|
|
919
|
-
"CARGO_BUILD_JOBS",
|
|
920
|
-
"CARGO_ENCODED_RUSTFLAGS",
|
|
921
|
-
"RUSTFLAGS",
|
|
922
|
-
"RUSTC_WRAPPER",
|
|
923
|
-
"RUSTC_WORKSPACE_WRAPPER",
|
|
924
|
-
"SCCACHE_DIR",
|
|
925
|
-
"SCCACHE_BASEDIRS",
|
|
926
|
-
"SCCACHE_CACHE_SIZE",
|
|
927
|
-
];
|
|
928
|
-
const cargoAuthorityExtensions = new Set([".mjs", ".js", ".cjs", ".ts", ".sh", ".ps1", ".py", ".json"]);
|
|
929
|
-
|
|
930
|
-
function findFirstPartyBuildScripts(root) {
|
|
931
|
-
const found = [];
|
|
932
|
-
const visit = (dir) => {
|
|
933
|
-
if (!existsSync(dir)) return;
|
|
934
|
-
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
935
|
-
if (entry.isDirectory() && [
|
|
936
|
-
".agent", ".audit", ".cache", ".git", ".right-release", "bakeoff", "dist", "docs",
|
|
937
|
-
"node_modules", "reference", "target", "tests", "vendor",
|
|
938
|
-
].includes(entry.name)) continue;
|
|
939
|
-
const full = path.join(dir, entry.name);
|
|
940
|
-
if (entry.isDirectory()) {
|
|
941
|
-
visit(full);
|
|
942
|
-
continue;
|
|
943
|
-
}
|
|
944
|
-
if (!entry.isFile() || !cargoAuthorityExtensions.has(path.extname(entry.name))) continue;
|
|
945
|
-
const relative = path.relative(root, full).replaceAll(path.sep, "/");
|
|
946
|
-
if (/(?:^|\/)(?:test-|[^/]+\.test\.)/.test(relative)) continue;
|
|
947
|
-
if (
|
|
948
|
-
relative.includes("/scripts/")
|
|
949
|
-
|| relative.startsWith("scripts/")
|
|
950
|
-
|| /(?:^|\/)(?:package\.json|package\.(?:sh|ps1)|right-release\.config\.mjs)$/.test(relative)
|
|
951
|
-
|| (!relative.includes("/") && /\.(?:sh|ps1)$/.test(relative))
|
|
952
|
-
) found.push(full);
|
|
953
|
-
}
|
|
954
|
-
};
|
|
955
|
-
visit(root);
|
|
956
|
-
return found;
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
function executableScriptSource(source) {
|
|
960
|
-
return source
|
|
961
|
-
.replace(/\/\*[\s\S]*?\*\//g, "")
|
|
962
|
-
.split("\n")
|
|
963
|
-
.filter((line) => !/^\s*(?:\/\/|#)/.test(line))
|
|
964
|
-
.join("\n");
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
test("product scripts never override or destroy RightKit-owned Cargo cache state", () => {
|
|
968
|
-
const authorityName = cargoAuthorityNames.join("|");
|
|
969
|
-
const jsMutation = new RegExp(`(?:delete\\s+process\\.env\\.(?:${authorityName})|process\\.env\\.(?:${authorityName})\\s*=|\\b(?:${authorityName})\\s*:)`);
|
|
970
|
-
const shellMutation = new RegExp(`(?:^|\\n)\\s*(?:export\\s+|unset\\s+|env\\s+(?:-[^\\n ]+\\s+)*-u\\s+)?(?:${authorityName})(?:\\s*=|\\b)`);
|
|
971
|
-
const powershellMutation = new RegExp(`\\$env:(?:${authorityName})\\s*=`, "i");
|
|
972
|
-
const cargoClean = /\bcargo\s+clean\b|["']cargo["'][\s\S]{0,400}?["']clean["']/;
|
|
973
|
-
|
|
974
|
-
for (const appRoot of cargoAuthorityRoots) {
|
|
975
|
-
const root = path.join(workspace, appRoot);
|
|
976
|
-
if (!existsSync(root)) continue;
|
|
977
|
-
for (const filePath of findFirstPartyBuildScripts(root)) {
|
|
978
|
-
const source = executableScriptSource(readFileSync(filePath, "utf8"));
|
|
979
|
-
const relative = path.relative(workspace, filePath);
|
|
980
|
-
assert.doesNotMatch(source, jsMutation, `${relative} mutates RightKit-owned Cargo/cache environment`);
|
|
981
|
-
assert.doesNotMatch(source, shellMutation, `${relative} mutates RightKit-owned Cargo/cache environment`);
|
|
982
|
-
assert.doesNotMatch(source, powershellMutation, `${relative} mutates RightKit-owned Cargo/cache environment`);
|
|
983
|
-
assert.doesNotMatch(source, cargoClean, `${relative} destroys reusable Cargo output with cargo clean`);
|
|
984
|
-
assert.doesNotMatch(source, /--target-dir\b/, `${relative} bypasses RightKit target ownership`);
|
|
985
|
-
assert.doesNotMatch(source, /(?:^|[\\/])\.cargo[\\/]bin(?:[\\/]|\b)/i, `${relative} bypasses managed Cargo by injecting a toolchain directory`);
|
|
986
|
-
assert.doesNotMatch(source, /build-guard\.mjs/, `${relative} depends on obsolete product-local build/cache control`);
|
|
987
|
-
}
|
|
988
|
-
assert.equal(existsSync(path.join(root, "scripts", "build-guard.mjs")), false, `${appRoot} must not carry a product-local build guard`);
|
|
989
|
-
}
|
|
990
|
-
});
|
|
991
|
-
|
|
992
|
-
test("Right Suite has no hosted workflow files", () => {
|
|
993
|
-
for (const root of ["viewright", "scraperight", "heardright", "mailright", "coderight", "genright", "voiceright", "tools/rightkit"]) {
|
|
994
|
-
const workflowDir = path.join(workspace, root, ".github", "workflows");
|
|
995
|
-
const workflows = existsSync(workflowDir) ? readdirSync(workflowDir) : [];
|
|
996
|
-
assert.deepEqual(workflows, [], `${root} must not contain hosted workflow files`);
|
|
997
|
-
}
|
|
998
|
-
});
|
|
999
|
-
|
|
1000
|
-
test("RightApps brand hosts expose app-keyed update manifest proxies", () => {
|
|
1001
|
-
for (const app of apps) {
|
|
1002
|
-
const siteRoot = path.join(workspace, siteRepoDir, app.key);
|
|
1003
|
-
for (const route of ["patches", "latest"]) {
|
|
1004
|
-
const routeFile = path.join(siteRoot, "src", "routes", "releases", `${route}.json`, "index.ts");
|
|
1005
|
-
const source = readFileSync(routeFile, "utf8");
|
|
1006
|
-
assert.match(source, new RegExp(`APP_KEY\\s*=\\s*["']${app.key}["']`), `${app.key} ${route}.json proxy must set the app key`);
|
|
1007
|
-
assert.match(source, /RIGHTAPPS_API_URL/, `${app.key} ${route}.json proxy must use the configurable RightApps API base`);
|
|
1008
|
-
assert.match(source, /x-app-key/i, `${app.key} ${route}.json proxy must forward the app key header`);
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
});
|