@rightkit/release 0.2.68 → 0.2.70

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.
Files changed (46) hide show
  1. package/cli/right-release.mjs +0 -0
  2. package/package.json +13 -9
  3. package/release.mjs +47 -14
  4. package/rightkit-versions.json +4 -2
  5. package/addon-command.test.mjs +0 -54
  6. package/addon-contract.test.mjs +0 -48
  7. package/asr-artifact-adoption.test.mjs +0 -122
  8. package/build-invocation-contract.test.mjs +0 -124
  9. package/build-release.test.mjs +0 -242
  10. package/cache-command.test.mjs +0 -118
  11. package/cache-policy.test.mjs +0 -346
  12. package/cargo-guard.test.mjs +0 -195
  13. package/cargo-target.test.mjs +0 -82
  14. package/create-mac-updater.test.mjs +0 -14
  15. package/github-release.test.mjs +0 -103
  16. package/heavy-command.test.mjs +0 -221
  17. package/legal-contract.test.mjs +0 -151
  18. package/mirror-root-artifact.test.mjs +0 -58
  19. package/model-promote.test.mjs +0 -284
  20. package/notary-auth.test.mjs +0 -31
  21. package/nsis-payload.test.mjs +0 -139
  22. package/nsis-upgrade-contract.test.mjs +0 -57
  23. package/preflight.test.mjs +0 -123
  24. package/progress-control.test.mjs +0 -56
  25. package/prune-r2.test.mjs +0 -12
  26. package/publish-cargo.test.mjs +0 -43
  27. package/publish-swift.test.mjs +0 -44
  28. package/publish-update.test.mjs +0 -207
  29. package/qa-contract.test.mjs +0 -47
  30. package/registry-parity.test.mjs +0 -30
  31. package/release-cli-contract.test.mjs +0 -119
  32. package/release-invocation.test.mjs +0 -22
  33. package/release-state.test.mjs +0 -395
  34. package/release-token.test.mjs +0 -21
  35. package/release.test.mjs +0 -477
  36. package/right-suite-contract.test.mjs +0 -1007
  37. package/rightapps-register.test.mjs +0 -28
  38. package/runtime-artifact-manifest.test.mjs +0 -128
  39. package/sign-updater.test.mjs +0 -12
  40. package/source-gate.test.mjs +0 -25
  41. package/standalone-clone-evidence.json +0 -32
  42. package/standalone-clone-verify.test.mjs +0 -76
  43. package/suite-doctor.test.mjs +0 -19
  44. package/target-bridge.test.mjs +0 -269
  45. package/tauri-bundle-marker.test.mjs +0 -81
  46. package/upload-large.test.mjs +0 -70
package/release.test.mjs DELETED
@@ -1,477 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
3
- import os from "node:os";
4
- import path from "node:path";
5
- import { execFileSync, spawnSync } from "node:child_process";
6
- import { fileURLToPath } from "node:url";
7
- import test from "node:test";
8
-
9
- const release = fileURLToPath(new URL("./release.mjs", import.meta.url));
10
- const cli = fileURLToPath(new URL("./cli/right-release.mjs", import.meta.url));
11
- const versions = JSON.parse(readFileSync(new URL("./rightkit-versions.json", import.meta.url), "utf8"));
12
- const defaultBuildInputs = { include: ["package.json", "pnpm-lock.yaml", "src-tauri/**"] };
13
- const hostPlatform = process.platform === "darwin" ? "mac" : process.platform === "win32" ? "win" : process.platform;
14
-
15
- function git(cwd, ...args) {
16
- return execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
17
- }
18
-
19
- function fixture({ signed = true, publish = false, signingContract = "windows-raw-exe-authenticode-before-nsis-v1", prePackageFiles = ["raw.exe"], packageJson, packageCommand, cargoManifest, cargoConfig, repoCargoConfig, siblingCargoManifest, buildInputs = defaultBuildInputs, platform = "win" } = {}) {
20
- const fixtureRoot = mkdtempSync(path.join(os.tmpdir(), "right-release-test-"));
21
- const dir = repoCargoConfig ? path.join(fixtureRoot, "apps", "fixture") : fixtureRoot;
22
- mkdirSync(dir, { recursive: true });
23
- const config = path.join(dir, "right-release.config.mjs");
24
- writeFileSync(
25
- path.join(dir, "package.json"),
26
- JSON.stringify(
27
- packageJson ?? {
28
- name: "fixture",
29
- scripts: { [`release:patch:${platform}`]: `right-release --platform ${platform} --tier patch` },
30
- packageManager: versions.packageManager,
31
- dependencies: {
32
- "@rightkit/license": versions.npm["@rightkit/license"],
33
- "@rightkit/logs": versions.npm["@rightkit/logs"],
34
- },
35
- devDependencies: { "@rightkit/release": versions.npm["@rightkit/release"] },
36
- },
37
- null,
38
- 2,
39
- ),
40
- );
41
- writeFileSync(
42
- config,
43
- `export default ${JSON.stringify({
44
- schema: 1,
45
- app: "fixture",
46
- packageManager: "pnpm",
47
- checks: [],
48
- targets: {
49
- [platform]: {
50
- ...(buildInputs ? { buildInputs } : {}),
51
- signed,
52
- package: packageCommand ?? { cmd: "node", args: ["-e", "process.exit(0)"] },
53
- ...(publish ? { publish: { cmd: "node", args: ["publish-update.mjs"] } } : {}),
54
- artifacts: [],
55
- ...(platform === "win" ? { signingContract, prePackage: { cmd: "node", args: ["-e", "process.exit(0)"] }, sign: { prePackageFiles, files: ["fixture.exe"] } } : {}),
56
- updater: { artifacts: [{ file: "fixture.exe", signature: "fixture.exe.sig", platform: "windows-x86_64", key: "fixture/fixture.exe" }] },
57
- hardening: [],
58
- },
59
- },
60
- })};\n`,
61
- );
62
- writeFileSync(path.join(dir, "pnpm-lock.yaml"), "lockfileVersion: '9.0'\n", "utf8");
63
- const tauriDir = path.join(dir, "src-tauri");
64
- mkdirSync(tauriDir, { recursive: true });
65
- writeFileSync(path.join(tauriDir, "Cargo.toml"), `[package]\nname = "fixture-tauri"\nversion = "0.0.0"\nedition = "2021"\n[lib]\npath = "lib.rs"\n`, "utf8");
66
- writeFileSync(path.join(tauriDir, "Cargo.lock"), "# fixture lock\n", "utf8");
67
- writeFileSync(path.join(tauriDir, "lib.rs"), "pub fn fixture() {}\n", "utf8");
68
- if (cargoManifest) {
69
- writeFileSync(path.join(dir, "Cargo.toml"), `${cargoManifest}\n[lib]\npath = "fixture.rs"\n`, "utf8");
70
- writeFileSync(path.join(dir, "fixture.rs"), "", "utf8");
71
- }
72
- if (cargoConfig) {
73
- const cargoDir = path.join(dir, ".cargo");
74
- mkdirSync(cargoDir, { recursive: true });
75
- writeFileSync(path.join(cargoDir, "config.toml"), cargoConfig, "utf8");
76
- }
77
- if (repoCargoConfig) {
78
- const cargoDir = path.join(fixtureRoot, ".cargo");
79
- mkdirSync(cargoDir, { recursive: true });
80
- writeFileSync(path.join(cargoDir, "config.toml"), repoCargoConfig, "utf8");
81
- }
82
- if (siblingCargoManifest) {
83
- const sibling = path.join(fixtureRoot, "docs", "archived-workspace");
84
- mkdirSync(sibling, { recursive: true });
85
- writeFileSync(path.join(sibling, "Cargo.toml"), siblingCargoManifest, "utf8");
86
- }
87
- git(fixtureRoot, "init", "--initial-branch", "main");
88
- git(fixtureRoot, "config", "user.email", "release-test@example.com");
89
- git(fixtureRoot, "config", "user.name", "Release Test");
90
- git(fixtureRoot, "add", ".");
91
- git(fixtureRoot, "commit", "-m", "initial");
92
- return config;
93
- }
94
-
95
- function lockFixture() {
96
- const dir = mkdtempSync(path.join(os.tmpdir(), "right-release-lock-test-"));
97
- const config = path.join(dir, "right-release.config.mjs");
98
- writeFileSync(
99
- path.join(dir, "package.json"),
100
- JSON.stringify(
101
- {
102
- name: "fixture-lock",
103
- scripts: { "release:patch:mac": "right-release --platform mac --tier patch" },
104
- packageManager: versions.packageManager,
105
- dependencies: {
106
- "@rightkit/license": versions.npm["@rightkit/license"],
107
- "@rightkit/logs": versions.npm["@rightkit/logs"],
108
- },
109
- devDependencies: { "@rightkit/release": versions.npm["@rightkit/release"] },
110
- },
111
- null,
112
- 2,
113
- ),
114
- );
115
- writeFileSync(
116
- config,
117
- `export default ${JSON.stringify({
118
- schema: 1,
119
- app: "fixture-lock",
120
- packageManager: "pnpm",
121
- checks: [],
122
- targets: {
123
- mac: {
124
- signed: true,
125
- package: { cmd: "node", args: ["-e", "process.exit(0)"] },
126
- artifacts: [],
127
- hardening: [],
128
- installer: { artifacts: [] },
129
- updater: { artifacts: [] },
130
- },
131
- },
132
- })};\n`,
133
- );
134
- return { dir, config };
135
- }
136
-
137
- // This suite must exercise the non-broker path deterministically regardless of
138
- // whether the machine running the tests is itself broker-managed (this
139
- // workspace's own agent shells are: the managed cargo shim sits on PATH).
140
- // Strip both broker signals from the inherited environment before spawning.
141
- function unmanagedEnv() {
142
- const sanitized = { ...process.env };
143
- delete sanitized.RIGHTKIT_BUILD_BROKER_SOCKET;
144
- const delimiter = process.platform === "win32" ? ";" : ":";
145
- sanitized.PATH = String(process.env.PATH ?? "")
146
- .split(delimiter)
147
- .filter((entry) => !/(?:^|[/\\])(?:\.rightkit-managed|rightkitmanagedagent)[/\\]agent-bin$/i.test(entry))
148
- .join(delimiter);
149
- return sanitized;
150
- }
151
-
152
- function run(config, ...args) {
153
- return spawnSync(process.execPath, [release, "--config", config, "--platform", "win", "--dry-run", ...args], {
154
- encoding: "utf8",
155
- env: unmanagedEnv(),
156
- });
157
- }
158
-
159
- function runRaw(config, ...args) {
160
- return spawnSync(process.execPath, [release, "--config", config, ...args], {
161
- encoding: "utf8",
162
- env: unmanagedEnv(),
163
- });
164
- }
165
-
166
- function runDoctor(config, ...args) {
167
- return spawnSync(process.execPath, [cli, "doctor", "--config", config, "--platform", hostPlatform, ...args], {
168
- encoding: "utf8",
169
- env: unmanagedEnv(),
170
- });
171
- }
172
-
173
- test("accepts a tier-neutral internal build", () => {
174
- const result = run(fixture());
175
- assert.equal(result.status, 0, result.stderr);
176
- assert.match(result.stdout, /tier=neutral/);
177
- assert.doesNotMatch(result.stdout, /RIGHT_RELEASE_TIER=/);
178
- });
179
-
180
- test("notarization commands default to a bounded 30-minute timeout without changing explicit overrides", () => {
181
- const defaultResult = runRaw(fixture({
182
- platform: "mac",
183
- packageCommand: { cmd: "node", args: ["-e", "process.exit(0)", "--notarize"] },
184
- }), "--platform", "mac", "--dry-run");
185
- assert.equal(defaultResult.status, 0, defaultResult.stderr);
186
- assert.match(defaultResult.stdout, /timeout=1800000ms/);
187
-
188
- const explicitResult = runRaw(fixture({
189
- platform: "mac",
190
- packageCommand: { cmd: "node", args: ["-e", "process.exit(0)", "--notarize"], timeoutMs: 1234 },
191
- }), "--platform", "mac", "--dry-run");
192
- assert.equal(explicitResult.status, 0, explicitResult.stderr);
193
- assert.match(explicitResult.stdout, /timeout=1234ms/);
194
- });
195
-
196
- test("release worker reuses owned process-tree termination for Windows and remote command descendants", () => {
197
- const source = readFileSync(release, "utf8");
198
- assert.match(source, /import \{ terminateProcessTree \} from "\.\/heavy-command\.mjs"/);
199
- assert.match(source, /function killProcessTree\(pid\) \{\s*terminateProcessTree\(pid\);\s*\}/s);
200
- });
201
-
202
- test("Windows native release tools preserve artifact arguments containing spaces", () => {
203
- const source = readFileSync(release, "utf8");
204
- assert.match(source, /const useShell = process\.platform === "win32" && !\/\\\.\(\?:exe\|com\)\$\/i\.test\(cmd\);/);
205
- assert.match(source, /shell: useShell/);
206
- assert.doesNotMatch(source, /shell: process\.platform === "win32"/);
207
- });
208
-
209
- test("accepts patch and exposes it to the signed package command", () => {
210
- const result = run(fixture(), "--tier=patch");
211
- assert.equal(result.status, 0, result.stderr);
212
- assert.match(result.stdout, /tier=patch/);
213
- assert.match(result.stdout, /RIGHT_RELEASE_TIER=patch/);
214
- });
215
-
216
- test("accepts update as the Pro-gated feature tier", () => {
217
- const result = run(fixture(), "--tier", "update");
218
- assert.equal(result.status, 0, result.stderr);
219
- assert.match(result.stdout, /tier=update/);
220
- assert.match(result.stdout, /RIGHT_RELEASE_TIER=update/);
221
- });
222
-
223
- test("rejects an invalid entitlement tier", () => {
224
- const result = run(fixture(), "--tier=minor");
225
- assert.notEqual(result.status, 0);
226
- assert.match(result.stderr, /invalid --tier.*patch\|update/i);
227
- });
228
-
229
- test("rejects targets that do not explicitly declare signed release output", () => {
230
- const result = run(fixture({ signed: false }), "--tier=patch");
231
- assert.notEqual(result.status, 0);
232
- assert.match(result.stderr, /signed: true/);
233
- });
234
-
235
- test("rejects Windows targets with missing or ambiguous signing configuration", () => {
236
- for (const options of [{ signingContract: null }, { prePackageFiles: [] }, { prePackageFiles: ["raw.exe", "other.exe"] }]) {
237
- const result = run(fixture(options), "--tier=patch");
238
- assert.notEqual(result.status, 0);
239
- assert.match(result.stderr, /signingContract|prePackageFiles/i);
240
- }
241
- });
242
-
243
- test("rejects Git, path, or link RightKit app dependencies before release work starts", () => {
244
- const result = run(
245
- fixture({
246
- packageJson: {
247
- name: "fixture",
248
- packageManager: versions.packageManager,
249
- scripts: { "release:patch:win": "node ../tools/right-release/release.mjs --tier patch" },
250
- dependencies: {
251
- "@rightkit/license": "git+https://github.com/adrdsouza/rightkit.git#main",
252
- "@rightkit/logs": "link:../../../rightkit/packages/logs",
253
- },
254
- devDependencies: {
255
- "@rightkit/release": "github:adrdsouza/claude#main&path:/tools/right-release",
256
- },
257
- },
258
- }),
259
- "--tier=patch",
260
- );
261
- assert.notEqual(result.status, 0);
262
- assert.match(result.stderr, /right-release bin|published npm package/i);
263
- });
264
-
265
- test("rejects hosted workflow files before release work starts", () => {
266
- const config = fixture();
267
- const workflowDir = path.join(path.dirname(config), ".github", "workflows");
268
- mkdirSync(workflowDir, { recursive: true });
269
- writeFileSync(path.join(workflowDir, "ci.yml"), "name: forbidden\n");
270
-
271
- const result = run(config, "--tier=patch");
272
- assert.notEqual(result.status, 0);
273
- assert.match(result.stderr, /hosted workflow.*forbidden/i);
274
- });
275
-
276
- test("doctor accepts an exact crates.io RightKit pin with benign Cargo config", () => {
277
- const config = fixture({
278
- platform: hostPlatform,
279
- cargoManifest: `[package]\nname = "fixture"\nversion = "0.0.0"\nedition = "2021"\n[dependencies]\nrightkit-license = "=0.1.2"`,
280
- cargoConfig: `[net]\nretry = 2\n[registries.private]\nindex = "https://example.test/index"`,
281
- });
282
- const result = runDoctor(config);
283
- assert.equal(result.status, 0, result.stderr);
284
- assert.match(result.stdout, /right-release/);
285
- });
286
-
287
- test("doctor rejects a selected target with missing or empty buildInputs.include", () => {
288
- for (const buildInputs of [null, { include: [] }]) {
289
- const result = run(fixture({ buildInputs }), "--doctor");
290
- assert.notEqual(result.status, 0);
291
- assert.match(result.stderr, /non-empty buildInputs\.include paths/i);
292
- }
293
- });
294
-
295
- test("doctor passes a clean selected target", () => {
296
- const result = runDoctor(fixture({ platform: hostPlatform }));
297
- assert.equal(result.status, 0, result.stderr);
298
- // Derived from the version manifest, not hardcoded: a literal here has to be
299
- // hand-edited on every bump and fails the suite when someone forgets.
300
- const expected = versions.stagedNpm?.["@rightkit/release"] ?? versions.npm["@rightkit/release"];
301
- assert.match(result.stdout, new RegExp(`right-release ${expected.replace(/\./g, "\\.")}`));
302
- });
303
-
304
- test("doctor rejects a real src-tauri target before release work", () => {
305
- const config = fixture({ platform: hostPlatform });
306
- mkdirSync(path.join(path.dirname(config), "src-tauri", "target"));
307
- const result = runDoctor(config);
308
- assert.notEqual(result.status, 0);
309
- assert.match(`${result.stdout}\n${result.stderr}`, /target-bridge[\s\S]*real directory[\s\S]*cache migrate/i);
310
- });
311
-
312
- test("doctor accepts a real src-tauri target on a broker-managed host instead of proposing cache migrate", () => {
313
- const config = fixture({ platform: hostPlatform });
314
- mkdirSync(path.join(path.dirname(config), "src-tauri", "target"));
315
- const result = spawnSync(process.execPath, [cli, "doctor", "--config", config, "--platform", hostPlatform], {
316
- encoding: "utf8",
317
- env: { ...unmanagedEnv(), RIGHTKIT_BUILD_BROKER_SOCKET: "/managed/broker.sock" },
318
- });
319
- assert.equal(result.status, 0, result.stderr);
320
- assert.doesNotMatch(`${result.stdout}\n${result.stderr}`, /cache migrate/i);
321
- assert.match(result.stdout, /target-bridge[\s\S]*broker-managed host, left untouched/i);
322
- });
323
-
324
- test("doctor permits unrelated dirt", () => {
325
- const config = fixture({ platform: hostPlatform });
326
- const root = path.dirname(config);
327
- mkdirSync(path.join(root, "notes"));
328
- writeFileSync(path.join(root, "notes", "scratch.md"), "unrelated\n");
329
- const result = runDoctor(config);
330
- assert.equal(result.status, 0, result.stderr);
331
- });
332
-
333
- test("doctor rejects tracked dirt inside declared buildInputs with the exact path", () => {
334
- const config = fixture();
335
- writeFileSync(path.join(path.dirname(config), "src-tauri", "lib.rs"), "pub fn changed() {}\n");
336
- const result = run(config, "--doctor");
337
- assert.notEqual(result.status, 0);
338
- assert.match(result.stderr, /dirty files can change the packaged app[\s\S]*- src-tauri\/lib\.rs/i);
339
- });
340
-
341
- test("doctor rejects untracked dirt inside declared buildInputs with the exact path", () => {
342
- const config = fixture();
343
- writeFileSync(path.join(path.dirname(config), "src-tauri", "new-runtime.rs"), "pub fn new_runtime() {}\n");
344
- const result = run(config, "--doctor");
345
- assert.notEqual(result.status, 0);
346
- assert.match(result.stderr, /dirty files can change the packaged app[\s\S]*- src-tauri\/new-runtime\.rs/i);
347
- });
348
-
349
- test("doctor rejects dirty required release metadata even when it is not declared", () => {
350
- const config = fixture({ buildInputs: { include: ["src-tauri/lib.rs"] } });
351
- writeFileSync(path.join(path.dirname(config), "pnpm-lock.yaml"), "lockfileVersion: '9.1'\n");
352
- const result = run(config, "--doctor");
353
- assert.notEqual(result.status, 0);
354
- assert.match(result.stderr, /dirty files can change the packaged app[\s\S]*- pnpm-lock\.yaml/i);
355
- });
356
-
357
- test("doctor rejects a dirty release config before importing it", () => {
358
- const config = fixture();
359
- writeFileSync(config, `${readFileSync(config, "utf8")}\n// dirty config\n`);
360
- const result = run(config, "--doctor");
361
- assert.notEqual(result.status, 0);
362
- assert.match(result.stderr, /dirty release config cannot be executed[\s\S]*- right-release\.config\.mjs/i);
363
- });
364
-
365
- test("doctor rejects linked and detached checkouts like build runtime", () => {
366
- const primaryConfig = fixture();
367
- const primary = path.dirname(primaryConfig);
368
- const linked = `${primary}-linked`;
369
- git(primary, "worktree", "add", "--detach", linked);
370
- const linkedResult = run(path.join(linked, "right-release.config.mjs"), "--doctor");
371
- assert.notEqual(linkedResult.status, 0);
372
- assert.match(linkedResult.stderr, /must be invoked from the primary Git worktree/i);
373
-
374
- git(primary, "checkout", "--detach");
375
- const detachedResult = run(primaryConfig, "--doctor");
376
- assert.notEqual(detachedResult.status, 0);
377
- assert.match(detachedResult.stderr, /detached HEAD is forbidden/i);
378
- });
379
-
380
- test("doctor scopes Cargo inspection to the configured app inside a monorepo", () => {
381
- const config = fixture({
382
- platform: hostPlatform,
383
- cargoManifest: `[package]\nname = "fixture"\nversion = "0.0.0"\nedition = "2021"\n[dependencies]\nrightkit-license = "=0.1.2"`,
384
- repoCargoConfig: `[net]\nretry = 2`,
385
- siblingCargoManifest: `[package]\nname = "archived-copy"\nversion = "0.0.0"\n[dependencies]\nrightkit-license = { path = "../../rightkit-license" }`,
386
- });
387
- const result = runDoctor(config);
388
- assert.equal(result.status, 0, result.stderr);
389
- });
390
-
391
- test("doctor rejects a repo-local RightKit Cargo override", () => {
392
- const config = fixture({
393
- cargoManifest: `[package]\nname = "fixture"\nversion = "0.0.0"\nedition = "2021"\n[dependencies]\nrightkit-license = "=0.1.1"`,
394
- cargoConfig: `[patch.crates-io]\nrightkit-license = { path = "../rightkit-license" }`,
395
- });
396
- const result = run(config, "--doctor");
397
- assert.notEqual(result.status, 0);
398
- assert.match(result.stderr, /forbidden RightKit Cargo override/i);
399
- });
400
-
401
- test("doctor rejects a RightKit override at an ancestor repository root", () => {
402
- const config = fixture({
403
- cargoManifest: `[package]\nname = "fixture"\nversion = "0.0.0"\nedition = "2021"\n[dependencies]\nrightkit-license = "=0.1.1"`,
404
- repoCargoConfig: `[patch.crates-io]\nrightkit-license = { git = "https://example.test/rightkit-license.git" }`,
405
- });
406
- const result = run(config, "--doctor");
407
- assert.notEqual(result.status, 0);
408
- assert.match(result.stderr, /forbidden RightKit Cargo override/i);
409
- });
410
-
411
- test("combined build and upload is rejected before the package step", () => {
412
- const result = run(fixture({ publish: true }), "--tier=update", "--upload");
413
- assert.notEqual(result.status, 0);
414
- assert.match(result.stderr, /combined build\+upload was removed/i);
415
- assert.doesNotMatch(result.stdout, /node -e process\.exit\(0\)/);
416
- });
417
-
418
- test("Windows tier-neutral build builds raw EXE, signs it, bundles, signs installer, then minisigns updater payload", () => {
419
- const result = run(fixture({ publish: true }));
420
- assert.equal(result.status, 0, result.stderr);
421
- const rawBuildAt = result.stdout.indexOf("node -e");
422
- const rawSignAt = result.stdout.indexOf("signing windows raw-exe");
423
- const bundleAt = result.stdout.indexOf("node -e", rawSignAt);
424
- const installerSignAt = result.stdout.indexOf("signing windows installer");
425
- const updaterAt = result.stdout.indexOf("sign-updater.mjs");
426
- assert.ok(rawBuildAt >= 0, result.stdout);
427
- assert.ok(rawSignAt > rawBuildAt, result.stdout);
428
- assert.ok(bundleAt > rawSignAt, result.stdout);
429
- assert.ok(installerSignAt > bundleAt, result.stdout);
430
- assert.ok(updaterAt > installerSignAt, result.stdout);
431
- assert.doesNotMatch(result.stdout, /publish-update\.mjs/);
432
- });
433
-
434
- test("Windows verifies the installer embeds the signed EXE after bundling and before the installer is signed", () => {
435
- const result = run(fixture({ publish: true }));
436
- assert.equal(result.status, 0, result.stderr);
437
- const rawSignAt = result.stdout.indexOf("signing windows raw-exe");
438
- const bundleAt = result.stdout.indexOf("node -e", rawSignAt);
439
- const embeddingAt = result.stdout.indexOf("verify installer embeds the signed raw EXE");
440
- const installerSignAt = result.stdout.indexOf("signing windows installer");
441
- assert.ok(embeddingAt > bundleAt, `embedding check must follow bundling:\n${result.stdout}`);
442
- assert.ok(installerSignAt > embeddingAt, `a mutated payload must never reach the installer signature:\n${result.stdout}`);
443
- });
444
-
445
- test("legacy internal tier does not make the build worker upload", () => {
446
- const result = run(fixture({ publish: true }), "--tier=update");
447
- assert.equal(result.status, 0, result.stderr);
448
- const azureAt = result.stdout.indexOf("sign-windows.mjs");
449
- const updaterAt = result.stdout.indexOf("sign-updater.mjs");
450
- assert.ok(azureAt >= 0, result.stdout);
451
- assert.ok(updaterAt > azureAt, result.stdout);
452
- assert.doesNotMatch(result.stdout, /publish-update\.mjs/);
453
- });
454
-
455
- test("release sweeps stale rust artifacts when a target dir exists", () => {
456
- const config = fixture();
457
- const dir = path.dirname(config);
458
- mkdirSync(path.join(dir, "src-tauri", "target"), { recursive: true });
459
- const result = run(config, "--tier=patch");
460
- assert.equal(result.status, 0, result.stderr);
461
- assert.match(result.stdout, /dry-run: cargo sweep --installed .*src-tauri/);
462
- });
463
-
464
- test("release skips the sweep when no target dir exists", () => {
465
- const result = run(fixture(), "--tier=patch");
466
- assert.equal(result.status, 0, result.stderr);
467
- assert.doesNotMatch(result.stdout, /cargo sweep/);
468
- });
469
-
470
- test("release lock is single-flight and is cleaned after success", () => {
471
- const { dir, config } = lockFixture();
472
- const lockPath = path.join(dir, ".cache", "right-release", "mac.lock.json");
473
- const result = runRaw(config, "--platform", "mac", "--tier=patch");
474
- assert.equal(result.status, 0, result.stderr);
475
- assert.match(result.stdout, /right-release: done/);
476
- assert.equal(existsSync(lockPath), false);
477
- });