@rightkit/release 0.2.84 → 0.2.86

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 CHANGED
@@ -76,12 +76,14 @@ const args = process.argv.slice(2);
76
76
  let configName = "right-release.config.mjs";
77
77
  let platform = process.platform === "win32" ? "win" : process.platform === "darwin" ? "mac" : process.platform;
78
78
  let dryRun = false;
79
+ let skipChecks = false;
79
80
 
80
81
  for (let i = 0; i < args.length; i += 1) {
81
82
  const arg = args[i];
82
83
  if (arg === "--config") configName = args[++i];
83
84
  else if (arg === "--platform") platform = args[++i];
84
85
  else if (arg === "--dry-run") dryRun = true;
86
+ else if (arg === "--skip-checks") skipChecks = true;
85
87
  else if (arg === "--tier" || arg.startsWith("--tier=")) fail("build is tier-neutral; select patch or update only during upload");
86
88
  else if (arg === "-h" || arg === "--help") usage(0);
87
89
  else fail(`unknown argument: ${arg}`);
@@ -337,7 +339,7 @@ try {
337
339
  throwIfInterrupted();
338
340
  await runProgress(
339
341
  process.execPath,
340
- [WORKER, "--config", configPath, "--platform", platform, "--no-upload"],
342
+ [WORKER, "--config", configPath, "--platform", platform, "--no-upload", ...(skipChecks ? ["--skip-checks"] : [])],
341
343
  appRoot,
342
344
  env,
343
345
  [managedCargoTarget ?? env.CARGO_TARGET_DIR, path.join(appRoot, ".cache")],
@@ -127,7 +127,7 @@ function printHelp() {
127
127
  console.log(`right-release <command> [options]
128
128
 
129
129
  Commands:
130
- build [--platform mac|win] Build, sign/notarize, harden, and seal; never uploads
130
+ build [--platform mac|win] [--skip-checks] Build, sign/notarize, harden, and seal; never uploads
131
131
  upload --release <id> --platform mac|win --tier patch|update
132
132
  Upload one sealed release; never builds
133
133
  release Compatibility alias for build
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rightkit/release",
3
- "version": "0.2.84",
3
+ "version": "0.2.86",
4
4
  "description": "Portable Right Suite release CLI/SDK: signed native archives, direct bootstrap transactions, immutable GitHub Release upload, R2 bootstrap publication, and add-on adoption.",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "type": "module",
@@ -17,6 +17,14 @@
17
17
  "!standalone-clone-evidence.json"
18
18
  ],
19
19
  "sideEffects": false,
20
+ "scripts": {
21
+ "test": "node --test --test-concurrency=1 --test-force-exit *.test.mjs",
22
+ "test:registry-parity": "node registry-parity.mjs --allow-unpublished",
23
+ "test:signer:windows": "node sign-release-manifest.integration.mjs",
24
+ "prepublishOnly": "pnpm test && pnpm test:signer:windows && pnpm test:registry-parity",
25
+ "doctor:all": "node --test right-suite-contract.test.mjs",
26
+ "verify:standalone": "node standalone-clone-verify.mjs"
27
+ },
20
28
  "publishConfig": {
21
29
  "registry": "https://registry.npmjs.org/",
22
30
  "access": "public"
@@ -26,11 +34,5 @@
26
34
  "url": "git+https://github.com/bogusyogi/claude.git",
27
35
  "directory": "tools/rightkit/packages/release"
28
36
  },
29
- "scripts": {
30
- "test": "node --test --test-concurrency=1 --test-force-exit *.test.mjs",
31
- "test:registry-parity": "node registry-parity.mjs --allow-unpublished",
32
- "test:signer:windows": "node sign-release-manifest.integration.mjs",
33
- "doctor:all": "node --test right-suite-contract.test.mjs",
34
- "verify:standalone": "node standalone-clone-verify.mjs"
35
- }
36
- }
37
+ "packageManager": "pnpm@11.24.0"
38
+ }
@@ -0,0 +1,5 @@
1
+ /** Run only app-configured pre-build checks; release safeguards never route here. */
2
+ export async function runConfiguredChecks({ packageManager, checks = [], workdir, skipChecks = false, run }) {
3
+ if (skipChecks) return;
4
+ for (const script of checks) await run(packageManager, script, workdir);
5
+ }
@@ -15,7 +15,7 @@ function canonical(file) {
15
15
  return path.normalize(realpathSync(file)).toLowerCase();
16
16
  }
17
17
 
18
- export function assertPrimaryReleaseCheckout(repoRoot) {
18
+ export function assertPrimaryReleaseCheckout(repoRoot, env = process.env) {
19
19
  const worktrees = git(repoRoot, ["worktree", "list", "--porcelain"]);
20
20
  const gitDir = git(repoRoot, ["rev-parse", "--git-dir"]).trim();
21
21
  const configured = spawnSync("git", ["config", "--path", "--get", "core.worktree"], {
@@ -32,7 +32,35 @@ export function assertPrimaryReleaseCheckout(repoRoot) {
32
32
  throw new Error(`right-release must be invoked from the primary Git worktree: ${primary}`);
33
33
  }
34
34
  const branch = spawnSync("git", ["symbolic-ref", "--quiet", "HEAD"], { cwd: repoRoot, encoding: "utf8", windowsHide: true });
35
- if (branch.status !== 0) throw new Error("right-release requires a branch-attached primary Git checkout; detached HEAD is forbidden");
35
+ if (branch.status !== 0 && !isVerifiedGithubActionsTagCheckout(repoRoot, env)) {
36
+ throw new Error("right-release requires a branch-attached primary Git checkout; detached HEAD is forbidden");
37
+ }
38
+ }
39
+
40
+ function isVerifiedGithubActionsTagCheckout(repoRoot, env) {
41
+ const ref = env.GITHUB_REF;
42
+ const sha = env.GITHUB_SHA;
43
+ if (
44
+ env.GITHUB_ACTIONS !== "true"
45
+ || env.GITHUB_EVENT_NAME !== "push"
46
+ || env.GITHUB_REF_TYPE !== "tag"
47
+ || !/^refs\/tags\/v.+$/.test(ref ?? "")
48
+ || !/^[a-f0-9]{40}$/.test(sha ?? "")
49
+ || !/^[A-Za-z0-9][A-Za-z0-9-]{0,38}\/[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/.test(env.GITHUB_REPOSITORY ?? "")
50
+ ) return false;
51
+ const head = git(repoRoot, ["rev-parse", "HEAD"]).trim();
52
+ if (head !== sha) return false;
53
+ let tagCommit;
54
+ let origin;
55
+ try {
56
+ tagCommit = git(repoRoot, ["rev-parse", `${ref}^{commit}`]).trim();
57
+ origin = git(repoRoot, ["remote", "get-url", "origin"]).trim();
58
+ } catch {
59
+ return false;
60
+ }
61
+ if (tagCommit !== head) return false;
62
+ const repository = origin.match(/(?:github\.com[/:])([^/\s]+\/[^/\s]+?)(?:\.git)?\/?$/i)?.[1];
63
+ return repository?.toLowerCase() === env.GITHUB_REPOSITORY.toLowerCase();
36
64
  }
37
65
 
38
66
  export function resolvePrimaryWorktree({ repoRoot, worktrees, gitDir, coreWorktree }) {
package/release.mjs CHANGED
@@ -23,6 +23,7 @@ import { verifyNsisEmbeddedBinary } from "./nsis-payload.mjs";
23
23
  import { terminateProcessTree } from "./heavy-command.mjs";
24
24
  import { materializeHardeningEvidence } from "./hardening-evidence.mjs";
25
25
  import { MACOS_PORTABLE_SIGNING_CONTRACT } from "./macos-signing-contract.mjs";
26
+ import { runConfiguredChecks } from "./release-checks.mjs";
26
27
 
27
28
  const TOOL_ROOT = path.dirname(fileURLToPath(import.meta.url));
28
29
  const HARDENING_SCAN = path.resolve(TOOL_ROOT, "hardeningscan.mjs");
@@ -217,9 +218,13 @@ const started = Date.now();
217
218
  console.log(`right-release ${VERSION}: ${config.app ?? path.basename(root)} ${opts.platform} ${mode} tier=${opts.tier ?? "neutral"}`);
218
219
 
219
220
  if (opts.install) await runInstall(config.packageManager, workdir);
220
- if (!opts.skipChecks) {
221
- for (const script of config.checks ?? []) await runPackageScript(config.packageManager, script, workdir);
222
- }
221
+ await runConfiguredChecks({
222
+ packageManager: config.packageManager,
223
+ checks: config.checks,
224
+ workdir,
225
+ skipChecks: opts.skipChecks,
226
+ run: runPackageScript,
227
+ });
223
228
 
224
229
  let nativeFinalization = null;
225
230
  let bundleMarkerReceipts = [];
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "stagedNpm": {
16
16
  "@rightkit/ax": "0.2.1",
17
- "@rightkit/git": "0.2.8",
17
+ "@rightkit/git": "0.2.14",
18
18
  "@rightkit/hooks": "0.1.1",
19
19
  "@rightkit/legal": "0.3.1",
20
20
  "@rightkit/legal-ui": "0.1.1",
@@ -22,7 +22,7 @@
22
22
  "@rightkit/logs": "0.1.4",
23
23
  "@rightkit/platform-ui": "0.1.1",
24
24
  "@rightkit/qa": "0.2.1",
25
- "@rightkit/release": "0.2.84",
25
+ "@rightkit/release": "0.2.86",
26
26
  "@rightkit/tauri": "0.1.1",
27
27
  "@rightkit/updates": "0.2.4"
28
28
  },
@@ -122,8 +122,9 @@ export function materializeInTotoSlsaProvenance({
122
122
  sourceCommit,
123
123
  sourceRepository,
124
124
  subjects,
125
- startedAt,
126
- finishedAt = new Date().toISOString(),
125
+ now = () => new Date().toISOString(),
126
+ startedAt = now(),
127
+ finishedAt = now(),
127
128
  }) {
128
129
  assertIdentity({ product, version, target, sourceCommit });
129
130
  if (!outputPath.endsWith(".intoto.jsonl")) throw new Error("in-toto output must end in .intoto.jsonl");