From fb3b9196cbd1299e07f5d3ea423161a8fc716f00 Mon Sep 17 00:00:00 2001 From: Theo Gravity Date: Mon, 26 Oct 2026 05:56:10 -0700 Subject: [PATCH] fix(ci): put the helper signing keychain ON the search list #457 stopped unlisting the helper keychain but never listed it: on this runner image 'security create-keychain' does not append to the user's search list, so the identity stayed invisible to codesign and cli/desktop darwin shards still died with 'item could not be found'. Probe run 40325026239 on macos-14 proved the split: the same keychain fails while unlisted and signs cleanly once listed, and --keychain alone never helps. List it as the sole entry exactly as the CLI darwin shards already do (the path that signed cli-server-v3.0.2 today); the trap restores the baseline at step end. --- .github/workflows/release.yml | 56 +++++++++++++++++------------------ docs/release-and-ci.md | 17 ++++++----- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 435793bad..d9fbfb169 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -897,20 +897,21 @@ jobs: # which runs BEFORE Tauri's keychain exists (it arrives at bundle # time), and a release helper must carry the Developer ID, not an # ad-hoc signature, because the permission grant follows the - # cdhash. Build a second keychain for exactly that one call. The - # build script names it explicitly through - # APPLE_SIGNING_KEYCHAIN (--keychain), and it also stays on the - # user's search list, because that is where codesign resolves - # identities: measured on the 2026-10-26 dispatch (run - # 40306776766), a --keychain call pointed at an UNLISTED keychain - # still died with "The specified item could not be found in the - # keychain". When Tauri's bundle-time keychain joins the list - # later, both hold the SAME identity from the SAME p12, and the - # tauri#11992 trap is about DIFFERENT identities in one view: - # with identical material there is no wrong key to pick. + # cdhash. Build a second keychain for exactly that one call and + # make it the SOLE entry of the user's search list, the same way + # the CLI shards provision theirs above: codesign resolves a + # named identity through the search list, not the --keychain + # argument (probe run 40325026239 on this image: the same + # keychain failed "item could not be found" while unlisted and + # signed cleanly once listed). Login stays off the list exactly + # as on the CLI path. When Tauri's bundle-time keychain takes the + # list over later, both hold the SAME identity from the SAME p12, + # so the tauri#11992 trap - DIFFERENT identities in one view - + # cannot bite. The trap restores the baseline at step end. KC="$CI_TMP/helper-sign.keychain-db" KCPW="$(/usr/bin/openssl rand -hex 16)" security create-keychain -p "$KCPW" "$KC" + security list-keychains -d user -s "$KC" security unlock-keychain -p "$KCPW" "$KC" printf '%s' "$MACOS_CERT_P12_BASE64" | base64 -d > "$CI_TMP/cert.p12" security import "$CI_TMP/cert.p12" -k "$KC" -P "$MACOS_CERT_PASSWORD" -T /usr/bin/codesign @@ -918,9 +919,8 @@ jobs: security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KCPW" "$KC" >/dev/null 2>&1 security find-identity -v -p codesigning "$KC" | grep -q "Developer ID Application" \ || { echo "imported p12 yielded no valid Developer ID Application identity"; exit 1; } - # create-keychain left this keychain on the search list; that is - # where codesign needs it, so nothing unlists it mid-build. The - # trap restores the baseline when the step ends. + # The keychain is the search list for this step (listed above); + # the trap restores the baseline when the step ends. trap 'rm -rf "$CI_TMP"; security delete-keychain "$KC" 2>/dev/null || true; security list-keychains -d user -s "$HOME/Library/Keychains/login.keychain-db"' EXIT export APPLE_SIGNING_KEYCHAIN="$KC" ;; @@ -1561,20 +1561,21 @@ jobs: # which runs BEFORE Tauri's keychain exists (it arrives at bundle # time), and a release helper must carry the Developer ID, not an # ad-hoc signature, because the permission grant follows the - # cdhash. Build a second keychain for exactly that one call. The - # build script names it explicitly through - # APPLE_SIGNING_KEYCHAIN (--keychain), and it also stays on the - # user's search list, because that is where codesign resolves - # identities: measured on the 2026-10-26 dispatch (run - # 40306776766), a --keychain call pointed at an UNLISTED keychain - # still died with "The specified item could not be found in the - # keychain". When Tauri's bundle-time keychain joins the list - # later, both hold the SAME identity from the SAME p12, and the - # tauri#11992 trap is about DIFFERENT identities in one view: - # with identical material there is no wrong key to pick. + # cdhash. Build a second keychain for exactly that one call and + # make it the SOLE entry of the user's search list, the same way + # the CLI shards provision theirs above: codesign resolves a + # named identity through the search list, not the --keychain + # argument (probe run 40325026239 on this image: the same + # keychain failed "item could not be found" while unlisted and + # signed cleanly once listed). Login stays off the list exactly + # as on the CLI path. When Tauri's bundle-time keychain takes the + # list over later, both hold the SAME identity from the SAME p12, + # so the tauri#11992 trap - DIFFERENT identities in one view - + # cannot bite. The trap restores the baseline at step end. KC="$CI_TMP/helper-sign.keychain-db" KCPW="$(/usr/bin/openssl rand -hex 16)" security create-keychain -p "$KCPW" "$KC" + security list-keychains -d user -s "$KC" security unlock-keychain -p "$KCPW" "$KC" printf '%s' "$MACOS_CERT_P12_BASE64" | base64 -d > "$CI_TMP/cert.p12" security import "$CI_TMP/cert.p12" -k "$KC" -P "$MACOS_CERT_PASSWORD" -T /usr/bin/codesign @@ -1582,9 +1583,8 @@ jobs: security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KCPW" "$KC" >/dev/null 2>&1 security find-identity -v -p codesigning "$KC" | grep -q "Developer ID Application" \ || { echo "imported p12 yielded no valid Developer ID Application identity"; exit 1; } - # create-keychain left this keychain on the search list; that is - # where codesign needs it, so nothing unlists it mid-build. The - # trap restores the baseline when the step ends. + # The keychain is the search list for this step (listed above); + # the trap restores the baseline when the step ends. trap 'rm -rf "$CI_TMP"; security delete-keychain "$KC" 2>/dev/null || true; security list-keychains -d user -s "$HOME/Library/Keychains/login.keychain-db"' EXIT export APPLE_SIGNING_KEYCHAIN="$KC" ;; diff --git a/docs/release-and-ci.md b/docs/release-and-ci.md index 4419bbdf7..829796d90 100644 --- a/docs/release-and-ci.md +++ b/docs/release-and-ci.md @@ -765,13 +765,16 @@ the experimental probe. That signing runs during `cargo build`, before Tauri builds its own throwaway keychain at bundle time, so the desktop shards build a dedicated keychain for it and hand its path to the build script through `APPLE_SIGNING_KEYCHAIN`. The -keychain stays on the user's search list for the build: `codesign` resolves a -named identity through the search list, not the `--keychain` argument, so the -keychain has to be listed for the identity to be found (run 40306776766 failed -with "item could not be found" when it was created, imported, and then taken -back off the list). It carries the same single identity as Tauri's later bundle -keychain, so listing both is no ambiguity, and the step's trap restores the -baseline search list when it ends. +shard then makes that keychain the sole entry of the user's search list, exactly +as the CLI darwin shards provision theirs: `codesign` resolves a named identity +through the search list, not the `--keychain` argument, and on this runner image +`security create-keychain` does not add the keychain to that list. Run +40306776766 failed with "item could not be found" for exactly that reason, and +probe run 40325026239 on the same image confirmed the split: the same keychain +refused the identity while unlisted and signed cleanly once listed. When Tauri's +bundle-time keychain takes the list over later it carries the same single +identity from the same p12, so the two views are never in conflict, and the +step's trap restores the baseline search list when it ends. The helper has its own `Info.plist` version, which must increase when its code changes. Both apps reuse the newest installed helper; neither may downgrade it