@rightkit/release 0.2.81 → 0.2.83

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
@@ -42,7 +42,7 @@ import { cancelAndReapManagedRequest, firstManagedRequestId, releaseProgressLimi
42
42
  // These four files are the ones whose behaviour the cached target directory can
43
43
  // outlive.
44
44
 
45
- const PIPELINE_FINGERPRINT_SOURCES = ["release.mjs", "sign-windows.mjs", "tauri-bundle-marker.mjs", "nsis-payload.mjs"];
45
+ const PIPELINE_FINGERPRINT_SOURCES = ["release.mjs", "sign-windows.mjs", "sign-macos.mjs", "notarize-macos.mjs", "tauri-bundle-marker.mjs", "nsis-payload.mjs"];
46
46
  const PIPELINE_FINGERPRINT = createHash("sha256")
47
47
  .update(PIPELINE_FINGERPRINT_SOURCES.map((file) => `${file}:${createHash("sha256").update(readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), file))).digest("hex")}`).join("\n"))
48
48
  .digest("hex")
@@ -168,7 +168,26 @@ try {
168
168
  // outlived the change that was supposed to retire them.
169
169
  pipeline: PIPELINE_FINGERPRINT,
170
170
  configSha256: hashFile(configPath),
171
- receiptInputs: ["raw-exe", "installer", "embedding"].map((phase) => path.join(receiptRoot, `windows-${phase}.json`)),
171
+ // Resolve each phase receipt the same way signing does: the config's
172
+ // sign.receipt / sign.installerReceipt override wins, the default
173
+ // windows-<phase>.json name is only the fallback. Hardcoding the default
174
+ // here made the seal read a path the signer never wrote whenever a config
175
+ // (e.g. an architecture-qualified receipt) overrode it.
176
+ receiptInputs: ["raw-exe", "installer", "embedding"].map((phase) => {
177
+ const configured = phase === "raw-exe" ? target.sign?.receipt : phase === "installer" ? target.sign?.installerReceipt : undefined;
178
+ return configured ? path.resolve(appRoot, configured) : path.join(receiptRoot, `windows-${phase}.json`);
179
+ }),
180
+ } : platform === "mac" ? {
181
+ contract: target.signingContract ?? "<missing>",
182
+ pipeline: PIPELINE_FINGERPRINT,
183
+ configSha256: hashFile(configPath),
184
+ // Mac portable releases produce one Developer ID receipt before packaging
185
+ // and one Accepted notarization receipt after. Both must be part of cache
186
+ // identity and seal evidence, including configured receipt overrides.
187
+ receiptInputs: [
188
+ target.sign?.receipt ? path.resolve(appRoot, target.sign.receipt) : path.join(receiptRoot, "macos-signing.json"),
189
+ target.notarize?.receipt ? path.resolve(appRoot, target.notarize.receipt) : path.join(receiptRoot, "macos-notarization.json"),
190
+ ],
172
191
  } : null;
173
192
  if (signingIdentity) inputHashes[".right-release/signing-identity.json"] = hashFileText(JSON.stringify(signingIdentity));
174
193
  const cargoLock = nativeLayout.lockPath;
@@ -435,7 +454,15 @@ function sealRelease({ configRoot, managedCargoTarget, nativeLayout, sealedDir,
435
454
  commit,
436
455
  platform,
437
456
  cacheKey,
438
- signing: signingIdentity ? { ...signingIdentity, receipts: signingIdentity.receiptInputs.map((file) => ({ file, sha256: hashFile(file) })) } : null,
457
+ // Portable contracts sign only raw executables installer/embedding
458
+ // receipts legitimately never exist there. Seal every receipt that was
459
+ // produced, but never zero: a signed platform with no receipt at all is
460
+ // an unsound seal, not a portable release.
461
+ signing: signingIdentity ? { ...signingIdentity, receipts: (() => {
462
+ const present = signingIdentity.receiptInputs.filter((file) => existsSync(file));
463
+ if (present.length === 0) throw new Error(`no signing receipts found to seal; expected at least ${signingIdentity.receiptInputs[0]}`);
464
+ return present.map((file) => ({ file, sha256: hashFile(file) }));
465
+ })() } : null,
439
466
  files,
440
467
  routes,
441
468
  inputs: inputHashes,
@@ -0,0 +1 @@
1
+ export const MACOS_PORTABLE_SIGNING_CONTRACT = "macos-developer-id-notarized-portable-v1";
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+ import { createHash } from "node:crypto";
3
+ import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
4
+ import path from "node:path";
5
+ import { spawnSync } from "node:child_process";
6
+ import { notarytoolAuthArgs } from "./notary-auth.mjs";
7
+ import { MACOS_PORTABLE_SIGNING_CONTRACT } from "./macos-signing-contract.mjs";
8
+
9
+ const args = process.argv.slice(2);
10
+ const dryRun = args.includes("--dry-run");
11
+ const receiptIndex = args.indexOf("--receipt");
12
+ const profileIndex = args.indexOf("--profile");
13
+ const receiptPath = receiptIndex >= 0 ? args[receiptIndex + 1] : null;
14
+ const profile = profileIndex >= 0 ? args[profileIndex + 1] : undefined;
15
+ const archiveArgs = args.filter((arg, index) => arg !== "--dry-run" && arg !== "--receipt" && arg !== "--profile" && (receiptIndex < 0 || index !== receiptIndex + 1) && (profileIndex < 0 || index !== profileIndex + 1));
16
+ if (archiveArgs.length !== 1) fail("usage: node notarize-macos.mjs [--dry-run] --receipt <path> [--profile <name>] <archive>");
17
+ if (!receiptPath) fail("--receipt requires a path");
18
+ const archive = path.resolve(archiveArgs[0]);
19
+ if (dryRun) {
20
+ console.log(`dry-run: notarize ${archive}`);
21
+ process.exit(0);
22
+ }
23
+ if (process.platform !== "darwin") fail("macOS notarization must run on macOS");
24
+ if (!existsSync(archive)) fail(`missing archive: ${archive}`);
25
+
26
+ let authArgs;
27
+ try { authArgs = notarytoolAuthArgs({ profile }); } catch (error) { fail(error.message); }
28
+ const output = run("xcrun", ["notarytool", "submit", archive, "--wait", "--output-format", "json", ...authArgs]);
29
+ let result;
30
+ try { result = JSON.parse(output); } catch { fail(`notarytool did not return JSON for ${archive}`); }
31
+ if (result.status !== "Accepted") fail(`notarization was not accepted for ${archive}: ${result.status ?? "missing status"}`);
32
+
33
+ const absoluteReceipt = path.resolve(receiptPath);
34
+ mkdirSync(path.dirname(absoluteReceipt), { recursive: true });
35
+ writeFileSync(absoluteReceipt, `${JSON.stringify({
36
+ schema: 1,
37
+ signingContract: MACOS_PORTABLE_SIGNING_CONTRACT,
38
+ archive: { file: archive, ...fileEvidence(archive) },
39
+ notarization: { status: result.status, id: result.id ?? result.submissionId ?? null },
40
+ }, null, 2)}\n`);
41
+
42
+ function fileEvidence(file) {
43
+ const bytes = readFileSync(file);
44
+ return { sha256: createHash("sha256").update(bytes).digest("hex"), sizeBytes: statSync(file).size };
45
+ }
46
+
47
+ function run(cmd, runArgs) {
48
+ const result = spawnSync(cmd, runArgs, { encoding: "utf8" });
49
+ const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`.trim();
50
+ if (result.status !== 0) fail(`${cmd} ${runArgs.join(" ")} failed: ${output}`);
51
+ return output;
52
+ }
53
+
54
+ function fail(message) {
55
+ console.error(`right-notarize-macos: ${message}`);
56
+ process.exit(1);
57
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rightkit/release",
3
- "version": "0.2.81",
3
+ "version": "0.2.83",
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",
package/release.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { access, readFile, readdir } from "node:fs/promises";
3
3
  import { createHash } from "node:crypto";
4
- import { existsSync, mkdirSync, readFileSync, realpathSync, unlinkSync, writeFileSync } from "node:fs";
4
+ import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
5
5
  import path from "node:path";
6
6
  import { fileURLToPath, pathToFileURL } from "node:url";
7
7
  import { spawn, spawnSync } from "node:child_process";
@@ -22,11 +22,14 @@ import { patchTauriBundleType } from "./tauri-bundle-marker.mjs";
22
22
  import { verifyNsisEmbeddedBinary } from "./nsis-payload.mjs";
23
23
  import { terminateProcessTree } from "./heavy-command.mjs";
24
24
  import { materializeHardeningEvidence } from "./hardening-evidence.mjs";
25
+ import { MACOS_PORTABLE_SIGNING_CONTRACT } from "./macos-signing-contract.mjs";
25
26
 
26
27
  const TOOL_ROOT = path.dirname(fileURLToPath(import.meta.url));
27
28
  const HARDENING_SCAN = path.resolve(TOOL_ROOT, "hardeningscan.mjs");
28
29
  const UPLOAD_LARGE = path.resolve(TOOL_ROOT, "upload-large.mjs");
29
30
  const SIGN_WINDOWS = path.resolve(TOOL_ROOT, "sign-windows.mjs");
31
+ const SIGN_MACOS = path.resolve(TOOL_ROOT, "sign-macos.mjs");
32
+ const NOTARIZE_MACOS = path.resolve(TOOL_ROOT, "notarize-macos.mjs");
30
33
  const SIGN_UPDATER = path.resolve(TOOL_ROOT, "sign-updater.mjs");
31
34
  const RIGHTKIT_VERSIONS = JSON.parse(readFileSync(path.resolve(TOOL_ROOT, "rightkit-versions.json"), "utf8"));
32
35
  const VERSION = RIGHTKIT_VERSIONS.stagedNpm?.["@rightkit/release"] ?? RIGHTKIT_VERSIONS.npm["@rightkit/release"];
@@ -124,6 +127,12 @@ if (opts.platform === "win") {
124
127
  if (isNsis && target.sign.prePackageFiles.some((file) => target.sign.files.includes(file))) fail(`${config.app ?? "app"} win raw EXE and installer signing files must be distinct`);
125
128
  if (isPortable && target.sign?.files?.length) fail(`${config.app ?? "app"} win portable release must sign every executable through sign.prePackageFiles and omit sign.files`);
126
129
  }
130
+ if (opts.platform === "mac") {
131
+ if (target.signingContract !== MACOS_PORTABLE_SIGNING_CONTRACT) fail(`${config.app ?? "app"} mac must declare signingContract: ${MACOS_PORTABLE_SIGNING_CONTRACT}`);
132
+ if (!target.prePackage?.cmd) fail(`${config.app ?? "app"} mac must declare prePackage to materialize Developer ID signing files`);
133
+ if (!target.sign?.prePackageFiles?.length) fail(`${config.app ?? "app"} mac must declare at least one sign.prePackageFiles`);
134
+ if (!target.notarize?.file) fail(`${config.app ?? "app"} mac must declare notarize.file`);
135
+ }
127
136
  if (opts.upload && target.publishBlocked) fail(`${config.app ?? "app"} ${opts.platform} publish blocked: ${target.publishBlocked}`);
128
137
  /**
129
138
  * Assemble preflight inputs from the app's own files. Kept here (not in
@@ -240,6 +249,11 @@ if (opts.platform === "win") {
240
249
  signedFiles: rawFiles,
241
250
  });
242
251
  }
252
+ } else if (opts.platform === "mac") {
253
+ const signingFiles = target.sign.prePackageFiles.map((p) => path.resolve(root, p));
254
+ await runCommand(target.prePackage, root);
255
+ for (const file of signingFiles) await mustExist(file, `missing macOS Developer ID signing artifact: ${file}`);
256
+ await signMacos(signingFiles, root);
243
257
  } else if (nativeAssembly) {
244
258
  if (nativeAssembly.packageHook) await runCommand(nativeAssembly.packageHook, root);
245
259
  if (nativeFinalizer) {
@@ -279,6 +293,12 @@ if (target.postSign && opts.platform !== "win") {
279
293
  await runCommand(target.postSign, root);
280
294
  }
281
295
 
296
+ if (opts.platform === "mac") {
297
+ const archive = path.resolve(root, target.notarize.file);
298
+ await mustExist(archive, `missing macOS notarization archive: ${archive}`);
299
+ await notarizeMacos(archive, root);
300
+ }
301
+
282
302
  {
283
303
  const scanTargets = target.hardening ?? target.artifacts ?? [];
284
304
  if (scanTargets.length) {
@@ -378,6 +398,12 @@ async function runNativeFinalizer({ finalizer, nativeAssembly, target, root, sig
378
398
  ...finalizer,
379
399
  args: finalizer.args.map((arg) => expandFinalizerToken(arg, { provenance, outputPath, packageIdentity })),
380
400
  };
401
+ // A finalization receipt at outputPath from a PREVIOUS run must not
402
+ // survive into this one: the file is preferred over the finalizer's
403
+ // stdout below, and a stale receipt carries the prior run's provenance,
404
+ // which fails the identity check against this run's mint. Any file
405
+ // present after the finalizer returns was written by this run.
406
+ if (!opts.dryRun) rmSync(outputPath, { force: true });
381
407
  const stdout = await runCommand(finalizerCommand, root, {
382
408
  captureStdout: true,
383
409
  env: {
@@ -645,9 +671,14 @@ async function validateHostedWorkflows(root, appName, workflows, policy) {
645
671
  if (!source.startsWith("# Managed by right-git")) {
646
672
  fail(`${appName} ${workflow} is not marked as right-git managed`);
647
673
  }
674
+ const requestedSecrets = [...source.matchAll(/\bsecrets\.([A-Z0-9_]+)/gi)].map((match) => match[1]);
675
+ const allowedMacosSecrets = new Set(["APPLE_CERTIFICATE_BASE64", "APPLE_CERTIFICATE_PASSWORD", "APPLE_KEYCHAIN_PASSWORD", "APPLE_API_KEY_BASE64", "APPLE_API_KEY", "APPLE_API_ISSUER"]);
676
+ const macosSigningAllowed = workflow === "release-candidate.yml" && manifest?.candidate?.signMacos === true;
648
677
  if (/^\s*permissions:\s*write-all\s*$/mi.test(source)
649
678
  || /^\s*(?:actions|attestations|checks|contents|deployments|discussions|id-token|issues|models|packages|pages|pull-requests|security-events|statuses):\s*write\s*$/mi.test(source)
650
- || /\bsecrets\s*(?:\.|\[)/i.test(source)) {
679
+ || /pull_request_target\s*:/i.test(source)
680
+ || /\bsecrets\s*\[/i.test(source)
681
+ || requestedSecrets.some((name) => !macosSigningAllowed || !allowedMacosSecrets.has(name))) {
651
682
  fail(`${appName} right-git managed ${workflow} requests release-capable permissions or secrets`);
652
683
  }
653
684
  }
@@ -699,6 +730,58 @@ function windowsReceiptPath(root, phase) {
699
730
  return path.join(process.env.RIGHT_RELEASE_STATE_ROOT ?? path.join(root, ".right-release", "receipts"), `windows-${phase}.json`);
700
731
  }
701
732
 
733
+ async function signMacos(files, root) {
734
+ const receipt = macosReceiptPath(root, "signing");
735
+ const args = [SIGN_MACOS];
736
+ if (opts.dryRun) args.push("--dry-run");
737
+ args.push("--receipt", receipt, ...files);
738
+ if (!opts.dryRun && existsSync(receipt)) unlinkSync(receipt);
739
+ console.log("right-release: signing macOS Developer ID files");
740
+ await run("node", args, root);
741
+ if (!opts.dryRun) verifyMacosSigningReceipt(receipt, files);
742
+ }
743
+
744
+ async function notarizeMacos(archive, root) {
745
+ const receipt = macosReceiptPath(root, "notarization");
746
+ const args = [NOTARIZE_MACOS];
747
+ if (opts.dryRun) args.push("--dry-run");
748
+ args.push("--receipt", receipt);
749
+ if (target.notarize.profile) args.push("--profile", target.notarize.profile);
750
+ args.push(archive);
751
+ if (!opts.dryRun && existsSync(receipt)) unlinkSync(receipt);
752
+ console.log("right-release: notarizing macOS archive");
753
+ await run("node", args, root);
754
+ if (!opts.dryRun) verifyMacosNotarizationReceipt(receipt, archive);
755
+ }
756
+
757
+ function macosReceiptPath(root, phase) {
758
+ const configured = phase === "signing" ? target.sign?.receipt : target.notarize?.receipt;
759
+ if (configured) return path.resolve(root, configured);
760
+ return path.join(process.env.RIGHT_RELEASE_STATE_ROOT ?? path.join(root, ".right-release", "receipts"), `macos-${phase}.json`);
761
+ }
762
+
763
+ function verifyMacosSigningReceipt(receipt, files) {
764
+ if (!existsSync(receipt)) fail(`missing macOS Developer ID signing receipt: ${receipt}`);
765
+ let evidence;
766
+ try { evidence = JSON.parse(readFileSync(receipt, "utf8")); } catch { fail(`invalid macOS Developer ID signing receipt: ${receipt}`); }
767
+ const expectedIdentity = process.env.APPLE_DEVELOPER_ID?.trim();
768
+ const expected = files.map((file) => path.resolve(file)).sort();
769
+ const actual = Array.isArray(evidence.files) ? evidence.files.map((item) => path.resolve(item.file)).sort() : [];
770
+ const hashes = new Map(files.map((file) => [path.resolve(file), createHash("sha256").update(readFileSync(file)).digest("hex")]));
771
+ if (evidence.schema !== 1 || evidence.signingContract !== MACOS_PORTABLE_SIGNING_CONTRACT || !expectedIdentity || evidence.identity !== expectedIdentity
772
+ || JSON.stringify(expected) !== JSON.stringify(actual)
773
+ || evidence.files.some((item) => item.codesign !== "strict-valid" || item.identity !== expectedIdentity || item.timestampPresent !== true || item.after?.sha256 !== hashes.get(path.resolve(item.file)))) fail(`invalid macOS Developer ID signing receipt evidence: ${receipt}`);
774
+ }
775
+
776
+ function verifyMacosNotarizationReceipt(receipt, archive) {
777
+ if (!existsSync(receipt)) fail(`missing macOS notarization receipt: ${receipt}`);
778
+ let evidence;
779
+ try { evidence = JSON.parse(readFileSync(receipt, "utf8")); } catch { fail(`invalid macOS notarization receipt: ${receipt}`); }
780
+ const sha256 = createHash("sha256").update(readFileSync(archive)).digest("hex");
781
+ if (evidence.schema !== 1 || evidence.signingContract !== MACOS_PORTABLE_SIGNING_CONTRACT || path.resolve(evidence.archive?.file ?? "") !== archive
782
+ || evidence.archive?.sha256 !== sha256 || evidence.notarization?.status !== "Accepted") fail(`invalid macOS notarization receipt evidence: ${receipt}`);
783
+ }
784
+
702
785
  /**
703
786
  * Close the gap between "the raw EXE was signed" and "the installer ships that
704
787
  * EXE". Three independent facts, each able to fail on its own:
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "stagedNpm": {
16
16
  "@rightkit/ax": "0.2.1",
17
- "@rightkit/git": "0.2.5",
17
+ "@rightkit/git": "0.2.7",
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.81",
25
+ "@rightkit/release": "0.2.83",
26
26
  "@rightkit/tauri": "0.1.1",
27
27
  "@rightkit/updates": "0.2.4"
28
28
  },
@@ -34,7 +34,9 @@
34
34
  "0.2.1",
35
35
  "0.2.2",
36
36
  "0.2.3",
37
- "0.2.4"
37
+ "0.2.4",
38
+ "0.2.5",
39
+ "0.2.6"
38
40
  ],
39
41
  "@rightkit/legal-ui": [
40
42
  "0.1.0"
@@ -81,7 +83,8 @@
81
83
  "0.2.73",
82
84
  "0.2.74",
83
85
  "0.2.75",
84
- "0.2.76"
86
+ "0.2.76",
87
+ "0.2.82"
85
88
  ],
86
89
  "@rightkit/qa": [
87
90
  "0.1.0",
package/sign-macos.mjs ADDED
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+ import { createHash } from "node:crypto";
3
+ import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
4
+ import path from "node:path";
5
+ import { spawnSync } from "node:child_process";
6
+ import { MACOS_PORTABLE_SIGNING_CONTRACT } from "./macos-signing-contract.mjs";
7
+
8
+ const args = process.argv.slice(2);
9
+ const dryRun = args.includes("--dry-run");
10
+ const receiptIndex = args.indexOf("--receipt");
11
+ const receiptPath = receiptIndex >= 0 ? args[receiptIndex + 1] : null;
12
+ const files = args
13
+ .filter((arg, index) => arg !== "--dry-run" && arg !== "--receipt" && (receiptIndex < 0 || index !== receiptIndex + 1))
14
+ .map((arg) => path.resolve(arg));
15
+
16
+ if (!files.length) fail("usage: node sign-macos.mjs [--dry-run] --receipt <path> <file>...");
17
+ if (!receiptPath) fail("--receipt requires a path");
18
+ if (dryRun) {
19
+ console.log(`dry-run: Developer ID signing ${files.join(", ")}`);
20
+ process.exit(0);
21
+ }
22
+ if (process.platform !== "darwin") fail("macOS signing must run on macOS");
23
+ const identity = process.env.APPLE_DEVELOPER_ID?.trim();
24
+ if (!identity) fail("set APPLE_DEVELOPER_ID to an installed Developer ID Application signing identity");
25
+ for (const file of files) if (!existsSync(file)) fail(`missing file: ${file}`);
26
+
27
+ const evidence = [];
28
+ for (const file of files) {
29
+ const before = fileEvidence(file);
30
+ run("codesign", ["--force", "--options", "runtime", "--timestamp", "--sign", identity, file]);
31
+ const verification = run("codesign", ["--verify", "--strict", "--verbose=4", file]);
32
+ const details = run("codesign", ["-dvv", file]);
33
+ if (!/valid on disk/i.test(verification) || !/satisfies its designated requirement/i.test(verification)) {
34
+ fail(`strict codesign verification failed for ${file}`);
35
+ }
36
+ if (!new RegExp(`^Authority=${escapeRegExp(identity)}$`, "m").test(details) && !details.includes(`Authority=${identity}`)) {
37
+ fail(`codesign identity mismatch for ${file}: expected ${identity}`);
38
+ }
39
+ evidence.push({ file, before, after: fileEvidence(file), codesign: "strict-valid", identity, timestampPresent: /(?:Timestamp|Signed Time)[=:]/i.test(details) });
40
+ if (!evidence.at(-1).timestampPresent) fail(`Developer ID timestamp is missing for ${file}`);
41
+ }
42
+
43
+ const absoluteReceipt = path.resolve(receiptPath);
44
+ mkdirSync(path.dirname(absoluteReceipt), { recursive: true });
45
+ writeFileSync(absoluteReceipt, `${JSON.stringify({ schema: 1, signingContract: MACOS_PORTABLE_SIGNING_CONTRACT, identity, files: evidence }, null, 2)}\n`);
46
+
47
+ function fileEvidence(file) {
48
+ const bytes = readFileSync(file);
49
+ return { sha256: createHash("sha256").update(bytes).digest("hex"), sizeBytes: statSync(file).size };
50
+ }
51
+
52
+ function run(cmd, runArgs) {
53
+ const result = spawnSync(cmd, runArgs, { encoding: "utf8" });
54
+ const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`;
55
+ if (result.status !== 0) fail(`${cmd} ${runArgs.join(" ")} failed: ${output.trim()}`);
56
+ return output;
57
+ }
58
+
59
+ function escapeRegExp(value) {
60
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
61
+ }
62
+
63
+ function fail(message) {
64
+ console.error(`right-sign-macos: ${message}`);
65
+ process.exit(1);
66
+ }
@@ -13,7 +13,6 @@ export const RIGHTRELEASE_MANIFEST_SIGNER = Object.freeze({
13
13
 
14
14
  const EXCLUDE_CREDENTIALS = [
15
15
  "ManagedIdentityCredential",
16
- "WorkloadIdentityCredential",
17
16
  "SharedTokenCacheCredential",
18
17
  "VisualStudioCredential",
19
18
  "VisualStudioCodeCredential",
package/sign-windows.mjs CHANGED
@@ -7,7 +7,6 @@ import { spawnSync } from "node:child_process";
7
7
 
8
8
  const EXCLUDE_CREDENTIALS = [
9
9
  "ManagedIdentityCredential",
10
- "WorkloadIdentityCredential",
11
10
  "SharedTokenCacheCredential",
12
11
  "VisualStudioCredential",
13
12
  "VisualStudioCodeCredential",