Skip to content

ci: import the signing certificate as a named .p12 - #21043

Merged
lawrencecchen merged 2 commits into
mainfrom
ci-signing-keychain-import-format
Oct 16, 2026
Merged

lawrencecchen merged 2 commits into
mainfrom
ci-signing-keychain-import-format

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fix forward for #20996. The first nightly on main after it (https://github.com/manaflow-ai/cmux/actions/runs/38723131700) failed in Import signing cert for all three variants:

security: SecKeychainItemImport: Unknown format in import.

scripts/ci/signing-keychain.sh create decoded the certificate into certificate.XXXXXX (no extension). security import infers the format from the file name; the old inline step used /tmp/cert.p12. The file is now certificate.p12 inside a private mktemp -d directory, the import passes -f pkcs12, and the decode uses printf '%s\n' like the old echo. The directory is removed right after the import and again by delete.

The run published nothing (the failure is before any signature).

Testing

  • tests/test_notarize_nightly_dmg.sh now requires a .p12 file and -f pkcs12 in the security import call. First commit: fails. Second commit: passes (Linux VM, fake security).
  • tests/test_ci_self_hosted_guard.sh keychain checks pass.
  • Not verified before merge: a real import. The next nightly from main proves it; this change touches only the import line of the tool.

Changelog

none


Summary by cubic

Fixes the nightly CI failure in Import signing cert where security import couldn't infer the format of the decoded certificate because it lacked a .p12 extension.

  • The certificate is now written as certificate.p12 in a private mktemp -d directory, and the import passes -f pkcs12.
  • The fake-security test now requires a .p12 file name and the explicit format flag.

Written for commit 1f8dfb8. Summary will update on new commits.

View guided diff Turn on auto-fix

Summary by CodeRabbit

  • Maintenance
    • Improved signing certificate import and temporary-file cleanup reliability.
    • Updated automated checks to verify the certificate format and keychain lock timeout.

The first nightly after #20996 failed at Import signing cert with
"SecKeychainItemImport: Unknown format in import": the decoded certificate
file had no .p12 extension, and security import infers the format from it.
This case now requires a .p12 file and -f pkcs12; the next commit fixes it.

Refs cmuxterm-hq#2053. Bead cx-yzoow.
signing-keychain.sh create decoded the certificate into a file without an
extension, and security import refused it ("Unknown format in import"),
which failed Import signing cert in every nightly variant after #20996. The
file is now certificate.p12 in a private directory, the import passes
-f pkcs12, and the decode keeps the trailing newline of the old inline step.

Refs cmuxterm-hq#2053. Bead cx-yzoow.
@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 78db36ae-19e2-420e-bfc0-f0f22423836d
📥 Commits

Reviewing files that changed from the base of the PR and between 2ca9448 and 1f8dfb8.

📒 Files selected for processing: 2
  • scripts/ci/signing-keychain.sh
  • tests/test_notarize_nightly_dmg.sh

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

📝 Walkthrough

The signing-keychain script now stores certificates as .p12 files in temporary directories, imports them with the explicit pkcs12 format, and removes those directories recursively. The test checks the file extension and import format.

Changes: Signing Keychain

Layer / File(s) Summary
Certificate import and cleanup
scripts/ci/signing-keychain.sh, tests/test_notarize_nightly_dmg.sh
create_keychain writes the certificate as certificate.p12 and passes -f pkcs12 to security import. Cleanup removes certificate directories recursively. The test checks the .p12 path, import format, and 600-second idle-lock setting.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix

Suggested reviewers: teamleaderleo

Merge Risk: ⚪ Minimal · up to 1f8df

This change fixes the CI certificate import by using a named .p12 file and an explicit pkcs12 format. No concrete merge-blocking risk was found. A real import will be confirmed by the next nightly run.

Pre-merge checks: Passed 24 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 24 passed
Check name Status Explanation
Description check Passed The description clearly explains the nightly signing failure, the fix, the tests run, the unverified real import, and the internal-only changelog entry. The Proof and Checklist sections from the templ…
Title check Passed The title is concise, specific, and accurately describes the primary change: importing the signing certificate as a named .p12 file.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Cmux Cloud Persistent Session And Early Input Passed PASS: The pull request changes only CI signing-certificate import cleanup and related tests. It does not change Cloud terminal creation, cmux-tui transport, manual renderer gating, input ownership, au…
Cmux Swift Actor Isolation Passed PASS: The pull request changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. The authoritative diff contains no Swift production changes, so it introduces no Swift 6 acto…
Cmux Swift Blocking Runtime Passed PASS: The pull request changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. It introduces no production Swift changes and no synchronization constructs covered by th…
Cmux Browser Automation Off-Main Passed The PR changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. The diff contains no browser socket commands, WebKit/AppKit routing, socketWorkerMethods, mainActor, or proce…
Cmux Expensive Synchronous Load Passed The pull request changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. The reviewed diff contains no Swift files and no agent-history loading or interactive Swift cal…
Cmux Cache Substitution Correctness Passed PASS: The pull request changes only Bash CI logic and a Bash test. It does not contain production Swift, TypeScript, or JavaScript changes. The diff updates certificate-file naming, security import …
Cmux No Hacky Sleeps Passed The pull request adds no fixed sleep, timer, polling loop, backoff, or wall-clock wait. The production shell change only changes certificate file naming, format selection, and cleanup. The existing 60…
Cmux Algorithmic Complexity Passed PASS: The pull request changes a CI shell script and its test. It adds temporary-directory creation, file decoding, explicit security import -f pkcs12, and recursive cleanup. It does not add nested …
Cmux Swift Concurrency Passed The pull request changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. The diff introduces no cmux-owned Swift code and no Swift concurrency patterns.
Cmux Swift @Concurrent Passed The pull request changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. The authoritative diff contains no Swift files or Swift async functions, so it cannot violate t…
Cmux Swift Package Boundaries Passed PASS: The pull request changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. It introduces no production Swift changes, so the Swift package boundary rule does not ap…
Cmux Swiftpm Lockfiles Passed PASS: The pull request changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. It does not change a SwiftPM package, Xcode project package references, .gitignore, wor…
Cmux Swift Logging Passed PASS: The pull request changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. Neither file contains Swift logging. The diff adds shell command output and test assertio…
Cmux User-Facing Error Privacy Passed PASS: The diff changes an internal CI signing helper and its test. The helper runs from GitHub Actions signing jobs and uses security import; the changed output is CI/operator diagnostics, not cmux …
Cmux Full Internationalization Passed The PR changes only CI signing-keychain logic and its shell test. It adds no Swift UI text, app catalog entries, web UI/API copy, metadata, markdown, or changelog content. The added comments and test …
Cmux Swiftui State Layout Passed PASS: The pull request changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. The diff contains shell and test-script changes, with no SwiftUI, ObservableObject, `@P…
Cmux Architecture Rethink Passed PASS: The pull request changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. It introduces no Swift architecture change, lifecycle ownership change, timing repair, ob…
Cmux Swift Auxiliary Window Close Shortcuts Passed PASS: The pull request changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. The authoritative diff contains no Swift changes and no auxiliary window code. The cmux a…
Cmux Source Artifacts Passed The diff changes only the hand-written CI script scripts/ci/signing-keychain.sh and the test tests/test_notarize_nightly_dmg.sh. It adds runtime temporary-directory cleanup and .p12 handling, bu…
Cmux No Test Or Debug Seam In Production Source Passed PASS. The pull request changes only scripts/ci/signing-keychain.sh and tests/test_notarize_nightly_dmg.sh. The authoritative diff contains no Swift files under a production Sources/ path, so it …
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lawrencecchen

Copy link
Copy Markdown
Contributor Author

Correctness review (subagent): approve, no blocking finding.

  • The cause is confirmed. Without -f, security import takes the format from the file extension. The new file name had none, and that was the only real change from the old inline step.
  • -f pkcs12 and the argument order are valid.
  • printf '%s\n' gives the same input as the old echo.
  • umask, the trap and the directory cleanup are correct.
  • Low, optional: the old rm -f /tmp/cert.p12 cleanup lines in release.yml and nightly.yml are now dead code, but they do no harm. The test checks the arguments only; a fake security cannot reproduce how the real tool reads the format. The next nightly from main is the real proof.

@lawrencecchen
lawrencecchen force-pushed the ci-signing-keychain-import-format branch from 74e9809 to 1f8dfb8 Compare October 16, 2026 05:17
@github-actions

Copy link
Copy Markdown
Contributor

Probably yours: Fast static checks failed: a static check failed, FAILED feature-flags (1.43s).

CI failed on 1f8dfb8d44 (run 38855018590 attempt 1): 1 code.

Job Verdict Why
Fast static checks code a static check failed
Matched log lines
Fast static checks: FAILED feature-flags (1.43s)

Not re-run automatically: Fast static checks is not a machine failure.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

@github-actions

Copy link
Copy Markdown
Contributor

CI fast guards failed on 1f8dfb8d44 (https://github.com/manaflow-ai/cmux/actions/runs/38855018590). It does not block the merge; a red guard merged into main breaks it for every open PR.
The log named no failed step; see the run.

Agents: python3 scripts/ci/guard_attribution.py fix applies the mechanical fixes locally. This comment is updated in place on each push.

@lawrencecchen
lawrencecchen merged commit c0f6ef3 into main Oct 16, 2026
112 of 115 checks passed
@lawrencecchen
lawrencecchen deleted the ci-signing-keychain-import-format branch October 16, 2026 05:41
@github-actions

Copy link
Copy Markdown
Contributor

Merge receipt for 1f8dfb8d44, merged 2026-10-16 05:41:24 UTC

  • Not verified at merge: ci-status (failure), Fast static checks (failure), linux-preflight (failure)
  • Verified: backend migrations applied, CI fast guards, CI timing, guards (19), plan, web-validation
  • Skipped by policy: apply-production, apply-staging, browser, Claude wrapper regressions, Dogfood build #​${{ github.event.pull_request.number }}, GhosttyKit release check, macos, macOS admission gate, remote-daemon, suite-coverage, ui-tests, web, and 3 more
  • Full suite: runs on main after merge.

Labeled merged-unverified: if main breaks near this merge, look here first.

@github-actions github-actions Bot added the merged-unverified A judging check was not green at merge; see the merge receipt comment label Oct 16, 2026
lawrencecchen added a commit that referenced this pull request Oct 16, 2026
* ci: real macOS import test for the signing keychain tool

tests/test_signing_keychain_real_import.sh runs the real signing-keychain.sh
create, a codesign with the imported identity, and delete on macOS with a
throwaway self-signed identity and a random password (no secret), in the new
signing-keychain-macos.yml workflow on a fresh runner. The fake-security case
alone did not catch the import format failure fixed in #21043.

Refs cmuxterm-hq#2053. Bead cx-yzoow.

* ci: real import test runs only in CI or by opt-in; push trigger only on main

Review findings on #21142. Refs cmuxterm-hq#2053. Bead cx-yzoow.

* ci: select the pinned Xcode in the real import job; push on both trunks

The macOS-jobs guard requires scripts/select-ci-xcode.sh in every macOS job.
Refs cmuxterm-hq#2053. Bead cx-yzoow.
lawrencecchen added a commit that referenced this pull request Oct 16, 2026
The certificate secret's .p12 carries Apple's Developer ID G2 intermediate, so
security import adds it and import-apple-developer-id-intermediates.sh then
failed on "already in build.keychain" in every signing job (first main
nightly with #21043, run 38857402565). The helper now accepts a certificate
that is already in the keychain; its count check still requires both
intermediates.

Refs cmuxterm-hq#2053. Bead cx-yzoow.
lawrencecchen added a commit that referenced this pull request Oct 16, 2026
…added (#21143)

* ci: accept a Developer ID intermediate that the signing .p12 already added

Since a2380e7 / #21043 the .p12 import works (named certificate.p12, -f pkcs12),
and it adds the Developer ID G2 intermediate that the certificate carries. Then
import-apple-developer-id-intermediates.sh ran security add-certificates for the
same certificate, which exits 1 with "already in build.keychain", and every Import
signing cert step failed (main nightly run 38857402565 on d16b03c, all 3 arches).

add_intermediate now treats only that "already in" result as success; any other
add-certificates error still fails. The existing count check still requires both
Developer ID intermediates in the keychain.

* ci: accept an already-present intermediate only when its SHA-1 matches

Review follow-up: "already in" alone is error text. The keychain must hold the
exact vendored certificate (SHA-1 fingerprint from openssl, compared with
security find-certificate -Z), else the import still fails. The hash list is
captured first, so grep -q cannot end security early under pipefail.

* ci: require a 40-hex SHA-1 before the fingerprint match, and match it as a fixed string

Security review P3 (hq-84).
lawrencecchen added a commit that referenced this pull request Oct 16, 2026
…added (#21145)

* ci: accept a Developer ID intermediate that the signing .p12 already added

Since a2380e7 / #21043 the .p12 import works (named certificate.p12, -f pkcs12),
and it adds the Developer ID G2 intermediate that the certificate carries. Then
import-apple-developer-id-intermediates.sh ran security add-certificates for the
same certificate, which exits 1 with "already in build.keychain", and every Import
signing cert step failed (main nightly run 38857402565 on d16b03c, all 3 arches).

add_intermediate now treats only that "already in" result as success; any other
add-certificates error still fails. The existing count check still requires both
Developer ID intermediates in the keychain.

* ci: accept an already-present intermediate only when its SHA-1 matches

Review follow-up: "already in" alone is error text. The keychain must hold the
exact vendored certificate (SHA-1 fingerprint from openssl, compared with
security find-certificate -Z), else the import still fails. The hash list is
captured first, so grep -q cannot end security early under pipefail.

* ci: require a 40-hex SHA-1 before the fingerprint match, and match it as a fixed string

Security review P3 (hq-84).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merged-unverified A judging check was not green at merge; see the merge receipt comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant