fix(release): check macOS signing inputs before compilation

This commit is contained in:
2026-10-17 05:52:26 -04:00
parent 998684c1a7
commit d9cd8e328e
3 changed files with 23 additions and 2 deletions
+3
View File
@@ -45,6 +45,9 @@ jobs:
- name: Verify exact reviewed source
run: python3 -B contrib/release/check_dispatch.py
- name: Check signing inputs before compiling
run: python3 -B contrib/release/sign_macos.py --check-inputs
- name: Verify Fleet-managed build dependencies
run: |
set -e
+14 -2
View File
@@ -10,6 +10,7 @@ import os
from pathlib import Path
import secrets
import subprocess
import sys
import tempfile
@@ -77,13 +78,18 @@ def private_file(path, content):
stream.write(content)
def main():
def signing_inputs():
credentials = {name: os.environ.get(name, "") for name in FIELDS}
missing = [name for name, value in credentials.items() if not value]
if missing:
raise ValueError("Signing input is missing: " + ", ".join(missing))
if "Such Software" not in credentials["APPLE_SIGNING_IDENTITY"]:
raise ValueError("Developer ID identity does not name the expected publisher")
return credentials
def main():
credentials = signing_inputs()
app = Path("build/dist/Wowlet.app").resolve()
if not app.is_dir():
raise ValueError("Packaged Wowlet.app is missing")
@@ -143,7 +149,13 @@ def main():
if __name__ == "__main__":
try:
main()
if sys.argv[1:] == ["--check-inputs"]:
signing_inputs()
print("Required signing inputs are present")
elif sys.argv[1:]:
raise ValueError("Use no arguments to sign or --check-inputs for the cheap input guard")
else:
main()
except (OSError, ValueError, RuntimeError, subprocess.TimeoutExpired) as error:
# These exceptions contain logical fields, native result classes or
# public file paths. Captured child output is never included.
+6
View File
@@ -29,6 +29,12 @@ class MacSigningTests(unittest.TestCase):
self.assertTrue(options["capture_output"])
self.assertNotIn("APPLE_CERTIFICATE_PASSWORD", options["env"])
def test_missing_inputs_refuse_without_native_operations(self):
with patch.dict(signing.os.environ, {}, clear=True), patch.object(signing.subprocess, "run") as execute:
with self.assertRaises(ValueError):
signing.signing_inputs()
execute.assert_not_called()
def test_control_characters_and_unrelated_keychain_operations_refuse(self):
with patch.object(signing.subprocess, "run") as execute:
for value in ("line\nbreak", "nul\x00byte", "carriage\rreturn"):