@rightkit/release 0.2.97 → 0.2.99

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.
@@ -2,6 +2,7 @@
2
2
  import path from "node:path";
3
3
  import { spawn } from "node:child_process";
4
4
  import { fileURLToPath } from "node:url";
5
+ import { assertReleaseExecutionAllowed } from "../execution-policy.mjs";
5
6
 
6
7
  const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
7
8
  const commands = new Map([
@@ -25,6 +26,19 @@ const commands = new Map([
25
26
 
26
27
  const args = process.argv.slice(2);
27
28
  const first = args[0];
29
+ const githubBuildCommands = new Set(["release", "build", "package", "sign-windows", "sign-updater", "create-mac-updater", "cargo-target"]);
30
+
31
+ try {
32
+ if (githubBuildCommands.has(first)
33
+ || first?.startsWith("-")
34
+ || (first === "addon" && args[1] === "build")
35
+ || (first === "publish" && ["cargo", "swift"].includes(args[1]))) {
36
+ assertReleaseExecutionAllowed({ command: `right-release ${args.join(" ")}`.trim() });
37
+ }
38
+ } catch (error) {
39
+ console.error(`right-release: ${error.message}`);
40
+ process.exit(125);
41
+ }
28
42
 
29
43
  if (!first || first === "-h" || first === "--help") {
30
44
  printHelp();
@@ -0,0 +1,46 @@
1
+ import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
2
+ import path from "node:path";
3
+
4
+ export const GITHUB_ACTIONS_ONLY = "github-actions-only";
5
+ export const GITHUB_ACTIONS_ONLY_ERROR = "RK_GITHUB_ACTIONS_ONLY";
6
+
7
+ function directoryFrom(value) {
8
+ const selected = path.resolve(value ?? process.cwd());
9
+ try { return statSync(selected).isDirectory() ? realpathSync(selected) : path.dirname(realpathSync(selected)); }
10
+ catch { return selected; }
11
+ }
12
+
13
+ function orthicRemote(root) {
14
+ const config = path.join(root, ".git", "config");
15
+ if (!existsSync(config)) return false;
16
+ try { return /github\.com(?::|\/)Orthic-Labs\//i.test(readFileSync(config, "utf8")); }
17
+ catch { return false; }
18
+ }
19
+
20
+ export function releaseExecutionPolicy(cwd = process.cwd()) {
21
+ let cursor = directoryFrom(cwd);
22
+ const filesystemRoot = path.parse(cursor).root;
23
+ for (;;) {
24
+ const manifestPath = path.join(cursor, ".rightgit.json");
25
+ if (existsSync(manifestPath)) {
26
+ let manifest;
27
+ try { manifest = JSON.parse(readFileSync(manifestPath, "utf8")); }
28
+ catch (error) { throw Object.assign(new Error(`invalid public repository execution policy: ${manifestPath}: ${error.message}`), { code: "RK_EXECUTION_POLICY_INVALID" }); }
29
+ if (orthicRemote(cursor) && manifest.compile !== GITHUB_ACTIONS_ONLY) {
30
+ throw Object.assign(new Error(`Orthic Labs public repository requires compile=${GITHUB_ACTIONS_ONLY}: ${manifestPath}`), { code: "RK_EXECUTION_POLICY_MISSING" });
31
+ }
32
+ return Object.freeze({ root: cursor, compile: manifest.compile ?? null });
33
+ }
34
+ if (orthicRemote(cursor)) throw Object.assign(new Error(`Orthic Labs public repository requires .rightgit.json with compile=${GITHUB_ACTIONS_ONLY}: ${cursor}`), { code: "RK_EXECUTION_POLICY_MISSING" });
35
+ if (cursor === filesystemRoot) return Object.freeze({ root: null, compile: null });
36
+ cursor = path.dirname(cursor);
37
+ }
38
+ }
39
+
40
+ export function assertReleaseExecutionAllowed({ cwd = process.cwd(), environment = process.env, command = "build" } = {}) {
41
+ const policy = releaseExecutionPolicy(cwd);
42
+ if (policy.compile === GITHUB_ACTIONS_ONLY && environment.GITHUB_ACTIONS !== "true") {
43
+ throw Object.assign(new Error(`${command} is GitHub Actions only for ${policy.root}; push changes & use managed CI`), { code: GITHUB_ACTIONS_ONLY_ERROR });
44
+ }
45
+ return policy;
46
+ }
package/nsis-payload.mjs CHANGED
@@ -94,10 +94,23 @@ export function extractNsisEntry(installer, entryName, { sevenZip = resolveSeven
94
94
  const destination = path.join(tempRoot, `right-nsis-${process.pid}-${Math.random().toString(16).slice(2)}`);
95
95
  mkdirSync(destination, { recursive: true });
96
96
  try {
97
- // `e` flattens the entry to the destination root, so the extracted path is
98
- // known regardless of how deep the entry sits inside the payload.
99
- const result = run(sevenZip, ["e", "-tnsis", "-y", `-o${destination}`, "--", resolvedInstaller, base]);
100
- const extracted = path.join(destination, base);
97
+ // NSIS entries may live below `$PLUGINSDIR/release`. A basename-only 7-Zip
98
+ // filter then reports `No files to process`, so resolve the actual archive
99
+ // member first & extract that exact path.
100
+ const requested = String(entryName).replace(/\\/g, "/");
101
+ const members = listNsisPayload(resolvedInstaller, { sevenZip, run });
102
+ const exact = members.filter((member) => member.name.toLowerCase() === requested.toLowerCase());
103
+ const matches = exact.length > 0
104
+ ? exact
105
+ : members.filter((member) => path.posix.basename(member.name).toLowerCase() === base.toLowerCase());
106
+ if (matches.length === 0) {
107
+ throw new Error(`could not extract ${base} from ${resolvedInstaller}: no such payload entry`);
108
+ }
109
+ if (matches.length !== 1) {
110
+ throw new Error(`could not uniquely identify ${base} in ${resolvedInstaller}: found ${matches.length} payload entries`);
111
+ }
112
+ const result = run(sevenZip, ["e", "-tnsis", "-y", `-o${destination}`, "--", resolvedInstaller, matches[0].name]);
113
+ const extracted = path.join(destination, path.posix.basename(matches[0].name));
101
114
  if (result.status !== 0 || !existsSync(extracted)) {
102
115
  throw new Error(
103
116
  `could not extract ${base} from ${resolvedInstaller}: ${(result.stderr || result.stdout || "no such entry").trim()}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rightkit/release",
3
- "version": "0.2.97",
3
+ "version": "0.2.99",
4
4
  "description": "Portable release CLI/SDK with fail-closed public GitHub Releases and private R2 + RightApps distribution.",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "type": "module",
package/release.mjs CHANGED
@@ -660,12 +660,13 @@ async function validateHostedWorkflows(root, appName, workflows, policy) {
660
660
  const lanes = manifest?.lanes;
661
661
  const safeLanes = new Set(["ci", "release-candidate"]);
662
662
  if (manifest?.schemaVersion !== 1
663
+ || manifest?.compile !== "github-actions-only"
663
664
  || !Array.isArray(lanes)
664
665
  || lanes.length === 0
665
666
  || !lanes.includes("ci")
666
667
  || new Set(lanes).size !== lanes.length
667
668
  || lanes.some((lane) => !safeLanes.has(lane))) {
668
- fail(`${appName} right-git-ci-only policy requires unique .rightgit.json lanes drawn from ["ci", "release-candidate"] and including "ci"`);
669
+ fail(`${appName} right-git-ci-only policy requires compile=github-actions-only plus unique .rightgit.json lanes drawn from ["ci", "release-candidate"] and including "ci"`);
669
670
  }
670
671
  const expectedWorkflows = lanes.map((lane) => `${lane}.yml`).sort();
671
672
  if (JSON.stringify(workflows) !== JSON.stringify(expectedWorkflows)) {
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "stagedNpm": {
16
16
  "@rightkit/ax": "0.2.1",
17
- "@rightkit/git": "0.2.21",
17
+ "@rightkit/git": "0.2.23",
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.97",
25
+ "@rightkit/release": "0.2.99",
26
26
  "@rightkit/tauri": "0.1.1",
27
27
  "@rightkit/updates": "0.2.4"
28
28
  },
@@ -49,7 +49,9 @@
49
49
  "0.2.16",
50
50
  "0.2.18",
51
51
  "0.2.19",
52
- "0.2.20"
52
+ "0.2.20",
53
+ "0.2.21",
54
+ "0.2.22"
53
55
  ],
54
56
  "@rightkit/legal-ui": [
55
57
  "0.1.0"
@@ -103,7 +105,9 @@
103
105
  "0.2.92",
104
106
  "0.2.94",
105
107
  "0.2.95",
106
- "0.2.96"
108
+ "0.2.96",
109
+ "0.2.97",
110
+ "0.2.98"
107
111
  ],
108
112
  "@rightkit/qa": [
109
113
  "0.1.0",