- Outputs are now written in fixed order so partial writes are reproducible.
- artifact-path output and S3 upload source are resolved to absolute paths,
matching the README's "absolute path" promise.
- New TestRun_FailureStillRunsCleanup integration test injects a notarization
failure and asserts the temporary keychain is still deleted, proving the
cleanup stack runs on every error path.
- go.mod pinned to go 1.22 (matches sample fixture; works on standard macOS
runner images) instead of the local-development 1.25.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same artefact go get/test sometimes leaves in fixture directories.
modfile.Parse is text-only and the test path never resolves modules;
the file is unnecessary and matches the cleanup we did after Task 5.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Exercises the full run() pipeline using fake shell scripts on PATH that
record their argv to a temp RECORD_DIR. Verifies all external commands
were invoked, outputs contain the expected version/app/artifact values,
ditto was called twice (pre- and post-staple), and security delete-keychain
ran during cleanup.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DeveloperIDCertBase64 is the .p12 contents and equally sensitive as
the password — register it with the log scrubber so a future code
path that accidentally wraps cfg in a debug log can't leak it. Also
documents why maskSecrets writes to stdout rather than stderr.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>