@rightkit/release 0.2.104 → 0.2.106
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/addon-command.mjs +1 -1
- package/background-process.mjs +33 -0
- package/build-release.mjs +47 -6
- package/cache-command.mjs +2 -2
- package/cache-policy.mjs +1 -1
- package/cargo-contract.mjs +230 -230
- package/cargo-guard.mjs +4 -4
- package/cargo-target.mjs +53 -48
- package/cli/right-release.mjs +3 -2
- package/create-mac-updater.mjs +1 -1
- package/deps.mjs +1 -1
- package/direct-bootstrap.mjs +84 -12
- package/github-release.mjs +1 -1
- package/heavy-command.mjs +1 -1
- package/macos-signing-identity.mjs +13 -0
- package/managed-cargo.mjs +29 -0
- package/mirror-root-artifact.mjs +1 -1
- package/model-promote.mjs +1 -1
- package/notarize-macos.mjs +1 -1
- package/nsis-payload.mjs +1 -1
- package/package.json +1 -1
- package/preflight.mjs +1 -1
- package/process-liveness.mjs +1 -1
- package/progress-control.mjs +1 -1
- package/pub-upload.mjs +1 -1
- package/publish-cargo.mjs +1 -1
- package/publish-swift.mjs +1 -1
- package/publish-update.mjs +1 -1
- package/registry-parity.mjs +1 -1
- package/release-invocation.mjs +1 -1
- package/release-state.mjs +2 -1
- package/release-token.mjs +1 -1
- package/release.mjs +18 -11
- package/rightkit-versions.json +141 -136
- package/sign-macos.mjs +4 -3
- package/sign-release-manifest.mjs +7 -5
- package/sign-updater.mjs +1 -1
- package/sign-windows.mjs +3 -15
- package/signing-env.mjs +29 -0
- package/standalone-clone-verify.mjs +1 -1
- package/upload-large.mjs +1 -1
- package/upload-release.mjs +1 -1
package/addon-command.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import { spawnSync } from "
|
|
6
|
+
import { spawnSync } from "./background-process.mjs";
|
|
7
7
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
8
8
|
import { addonManifestSha256, addonRoutes, canonicalAddonManifest, createAddonManifest, downloadImmutableAddOn, immutableAddonManifestUrl, validateAddonConfig, validateAddonManifest } from "./addon-contract.mjs";
|
|
9
9
|
import { assertPrimaryReleaseCheckout } from "./release-invocation.mjs";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import childProcess from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
|
|
4
|
+
// Release tooling has no interactive console children. Keep this policy at
|
|
5
|
+
// every Node launch boundary, including fixtures & nested release commands.
|
|
6
|
+
function hiddenArguments(args, options) {
|
|
7
|
+
return Array.isArray(args)
|
|
8
|
+
? [args, { ...options, windowsHide: true }]
|
|
9
|
+
: [[], { ...(args ?? options), windowsHide: true }];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function spawn(command, args, options) {
|
|
13
|
+
return childProcess.spawn(command, ...hiddenArguments(args, options));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function spawnSync(command, args, options) {
|
|
17
|
+
return childProcess.spawnSync(command, ...hiddenArguments(args, options));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function execFileSync(file, args, options) {
|
|
21
|
+
return childProcess.execFileSync(file, ...hiddenArguments(args, options));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function execFile(file, args, options, callback) {
|
|
25
|
+
if (typeof args === "function") { callback = args; args = undefined; }
|
|
26
|
+
if (typeof options === "function") { callback = options; options = undefined; }
|
|
27
|
+
return childProcess.execFile(file, ...hiddenArguments(args, options), callback);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Node's custom promisifier returns { stdout, stderr } & exposes promise.child.
|
|
31
|
+
// Preserve that contract for release-token's existing promisify(execFile).
|
|
32
|
+
execFile[promisify.custom] = (file, args, options) =>
|
|
33
|
+
childProcess.execFile[promisify.custom](file, ...hiddenArguments(args, options));
|
package/build-release.mjs
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
} from "node:fs";
|
|
21
21
|
import { tmpdir } from "node:os";
|
|
22
22
|
import path from "node:path";
|
|
23
|
-
import { spawn, spawnSync } from "
|
|
23
|
+
import { spawn, spawnSync } from "./background-process.mjs";
|
|
24
24
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
25
25
|
import { assertPrimaryReleaseCheckout, dirtyBuildInputs, resolveReleaseBuildInputs } from "./release-invocation.mjs";
|
|
26
26
|
import { resolveNativeCargoLayout } from "./native-cargo-layout.mjs";
|
|
@@ -78,6 +78,7 @@ let configName = "right-release.config.mjs";
|
|
|
78
78
|
let platform = process.platform === "win32" ? "win" : process.platform === "darwin" ? "mac" : process.platform;
|
|
79
79
|
let dryRun = false;
|
|
80
80
|
let skipChecks = false;
|
|
81
|
+
let resumeFrom = null;
|
|
81
82
|
|
|
82
83
|
for (let i = 0; i < args.length; i += 1) {
|
|
83
84
|
const arg = args[i];
|
|
@@ -85,11 +86,13 @@ for (let i = 0; i < args.length; i += 1) {
|
|
|
85
86
|
else if (arg === "--platform") platform = args[++i];
|
|
86
87
|
else if (arg === "--dry-run") dryRun = true;
|
|
87
88
|
else if (arg === "--skip-checks") skipChecks = true;
|
|
89
|
+
else if (arg === "--resume-from") resumeFrom = args[++i];
|
|
88
90
|
else if (arg === "--tier" || arg.startsWith("--tier=")) fail("build is tier-neutral; select patch or update only during upload");
|
|
89
91
|
else if (arg === "-h" || arg === "--help") usage(0);
|
|
90
92
|
else fail(`unknown argument: ${arg}`);
|
|
91
93
|
}
|
|
92
94
|
if (platform !== "win" && platform !== "mac") fail("--platform must be win or mac");
|
|
95
|
+
if (resumeFrom && !["prepackage", "sign", "package", "post-sign", "harden"].includes(resumeFrom)) fail("--resume-from must be prepackage, sign, package, post-sign, or harden");
|
|
93
96
|
|
|
94
97
|
const configPath = path.resolve(configName);
|
|
95
98
|
const invocationRoot = path.dirname(configPath);
|
|
@@ -137,10 +140,15 @@ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
|
|
|
137
140
|
try {
|
|
138
141
|
throwIfInterrupted();
|
|
139
142
|
const commit = git(repoRoot, ["rev-parse", "HEAD"]);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
143
|
+
// A phase-resume never reads unrelated source. Its later build-input gate
|
|
144
|
+
// remains strict, but requiring a globally clean mono-workspace here would
|
|
145
|
+
// turn an already-built, signed installer into a needless full rebuild.
|
|
146
|
+
if (!resumeFrom) {
|
|
147
|
+
assertCleanSource({
|
|
148
|
+
status: git(repoRoot, ["status", "--porcelain=v1", "-z", "--untracked-files=all"]),
|
|
149
|
+
commandId: "right-release build",
|
|
150
|
+
});
|
|
151
|
+
}
|
|
144
152
|
mkdirSync(path.join(vaultRoot, "locks"), { recursive: true });
|
|
145
153
|
lock = acquireLock(path.join(vaultRoot, "locks", `${platform}.lock.json`));
|
|
146
154
|
const shortCommit = commit.slice(0, 8);
|
|
@@ -265,6 +273,7 @@ try {
|
|
|
265
273
|
const platformDir = platform === "win" ? "windows" : "mac";
|
|
266
274
|
const buildRoot = managedCargoTarget ? null : path.join(vaultRoot, "build", config.app, config.version, shortCommit, platformDir);
|
|
267
275
|
const stateRoot = path.join(vaultRoot, "state", releaseId, platformDir);
|
|
276
|
+
env.RIGHT_RELEASE_STATE_ROOT = stateRoot;
|
|
268
277
|
const lockPayload = {
|
|
269
278
|
schema: 1,
|
|
270
279
|
releaseId,
|
|
@@ -339,7 +348,7 @@ try {
|
|
|
339
348
|
throwIfInterrupted();
|
|
340
349
|
await runProgress(
|
|
341
350
|
process.execPath,
|
|
342
|
-
[WORKER, "--config", configPath, "--platform", platform, "--no-upload", ...(skipChecks ? ["--skip-checks"] : [])],
|
|
351
|
+
[WORKER, "--config", configPath, "--platform", platform, "--no-upload", "--resume", ...(resumeFrom ? ["--resume-from", resumeFrom] : []), ...(skipChecks ? ["--skip-checks"] : [])],
|
|
343
352
|
appRoot,
|
|
344
353
|
env,
|
|
345
354
|
[managedCargoTarget ?? env.CARGO_TARGET_DIR, path.join(appRoot, ".cache")],
|
|
@@ -350,6 +359,21 @@ try {
|
|
|
350
359
|
checkpoint(stateRoot, "signed");
|
|
351
360
|
checkpoint(stateRoot, "hardened");
|
|
352
361
|
},
|
|
362
|
+
// Product-specific checks that must run after the signed/hardened bytes
|
|
363
|
+
// exist but before they become immutable. This is intentionally a small
|
|
364
|
+
// hook: Right Release still owns signing, hardening, and sealing; apps
|
|
365
|
+
// may only inspect their candidate and emit a pass/fail result.
|
|
366
|
+
preSeal: async ({ sealedDir }) => {
|
|
367
|
+
if (!target.preSeal) return;
|
|
368
|
+
await runConfiguredReleaseCheck(target.preSeal, {
|
|
369
|
+
root: appRoot,
|
|
370
|
+
env: {
|
|
371
|
+
RIGHT_RELEASE_SEALED_DIR: sealedDir,
|
|
372
|
+
RIGHT_RELEASE_RELEASE_ID: releaseId,
|
|
373
|
+
RIGHT_RELEASE_PLATFORM: platform,
|
|
374
|
+
},
|
|
375
|
+
});
|
|
376
|
+
},
|
|
353
377
|
seal: async ({ sealedDir }) => {
|
|
354
378
|
sealRelease({ configRoot: appRoot, managedCargoTarget, nativeLayout, sealedDir, releaseId, config, target, platform, commit, inputHashes, toolVersions, cacheKey, signingIdentity });
|
|
355
379
|
verifySealedRelease(sealedDir);
|
|
@@ -671,6 +695,23 @@ function runChecked(cmd, runArgs, cwd, env = process.env) {
|
|
|
671
695
|
if (result.status !== 0) fail(`${cmd} exited ${result.status}`);
|
|
672
696
|
}
|
|
673
697
|
|
|
698
|
+
function runConfiguredReleaseCheck(command, { root, env }) {
|
|
699
|
+
if (!command) return;
|
|
700
|
+
if (typeof command.cmd !== "string" || !command.cmd.trim()) {
|
|
701
|
+
fail("release preSeal check must declare a command");
|
|
702
|
+
}
|
|
703
|
+
const args = Array.isArray(command.args) ? command.args.map(String) : [];
|
|
704
|
+
const cwd = path.resolve(root, command.cwd ?? ".");
|
|
705
|
+
const result = spawnSync(command.cmd, args, {
|
|
706
|
+
cwd,
|
|
707
|
+
env: { ...process.env, ...env },
|
|
708
|
+
stdio: "inherit",
|
|
709
|
+
windowsHide: true,
|
|
710
|
+
shell: false,
|
|
711
|
+
});
|
|
712
|
+
if (result.status !== 0) fail(`release preSeal check failed: ${command.cmd} ${args.join(" ")}`);
|
|
713
|
+
}
|
|
714
|
+
|
|
674
715
|
function killTree(pid) {
|
|
675
716
|
terminateProcessTree(pid);
|
|
676
717
|
}
|
package/cache-command.mjs
CHANGED
|
@@ -25,12 +25,12 @@ import { brokerManagedHost } from "./cargo-contract.mjs";
|
|
|
25
25
|
const BROKER_MANAGED_MESSAGE = "broker-managed host: the build broker owns CARGO_TARGET_DIR; Cache V2 target checks skipped";
|
|
26
26
|
const BROKER_GATED_COMMANDS = new Set(["status", "prune", "migrate"]);
|
|
27
27
|
|
|
28
|
-
export async function runCacheCommand(args = process.argv.slice(2), { env = process.env, stdout = console.log, stderr = console.error } = {}) {
|
|
28
|
+
export async function runCacheCommand(args = process.argv.slice(2), { env = process.env, stdout = console.log, stderr = console.error, isBrokerHost = brokerManagedHost } = {}) {
|
|
29
29
|
const [command, ...rest] = args;
|
|
30
30
|
const json = rest.includes("--json");
|
|
31
31
|
const platform = platformFrom(env);
|
|
32
32
|
const cacheRoot = resolveSharedCacheRoot({ platform, env });
|
|
33
|
-
if (BROKER_GATED_COMMANDS.has(command) &&
|
|
33
|
+
if (BROKER_GATED_COMMANDS.has(command) && isBrokerHost(env)) {
|
|
34
34
|
const result = { schema: 1, command, cacheRoot, brokerManaged: true, skipped: true, message: BROKER_MANAGED_MESSAGE };
|
|
35
35
|
if (json) stdout(JSON.stringify(result));
|
|
36
36
|
else stdout(BROKER_MANAGED_MESSAGE);
|
package/cache-policy.mjs
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import os from "node:os";
|
|
18
18
|
import path from "node:path";
|
|
19
19
|
import { createHash } from "node:crypto";
|
|
20
|
-
import { spawnSync } from "
|
|
20
|
+
import { spawnSync } from "./background-process.mjs";
|
|
21
21
|
|
|
22
22
|
export const CACHE_SCHEMA = 1;
|
|
23
23
|
export const DEFAULT_TARGET_MAX_BYTES = 12 * 1024 ** 3;
|