ci: put CI keychain first in codesign search list
All checks were successful
TestFlight / testflight (push) Successful in 1m27s

codesign resolves signing identities through the user keychain search
list (first match wins) and ignores --keychain for the lookup. This
runner hosts another project (Sybil-2) whose keychain holds the same
Apple Distribution identity, so if that keychain is locked and appears
earlier in the search list, codesign fails with errSecInternalComponent
no matter how correctly our own keychain is set up. Prepend the fresh
CI keychain to the search list for the build and always delete it
afterward, which restores the original list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-11 13:16:13 -07:00
parent 1632e5fbd4
commit 45b09a13d3

View File

@@ -93,6 +93,14 @@ platform :ios do
) )
end end
# CI signs headlessly, so match needs a fresh unlocked keychain to import
# into. codesign resolves identities through the user keychain search
# list (first match wins; the --keychain flag does not restrict the
# lookup), and other projects' keychains on this runner hold the same
# identity but are usually locked — so ours must come first. delete_keychain
# in the beta lane's ensure removes both the keychain and its search-list
# entry, which also keeps our (later locked) copy from shadowing those
# other projects.
private_lane :prepare_ci_keychain do private_lane :prepare_ci_keychain do
next unless ci? next unless ci?
@@ -102,9 +110,15 @@ platform :ios do
password: CI_KEYCHAIN_PASSWORD, password: CI_KEYCHAIN_PASSWORD,
unlock: true, unlock: true,
timeout: 3600, timeout: 3600,
add_to_search_list: true add_to_search_list: false
) )
others = sh("security list-keychains -d user", log: false)
.scan(/"([^"]+)"/)
.flatten
.reject { |path| path.include?(CI_KEYCHAIN_NAME) }
sh("security list-keychains -d user -s #{([CI_KEYCHAIN_DB_PATH] + others).shelljoin}")
ENV["MATCH_KEYCHAIN_NAME"] = CI_KEYCHAIN_NAME ENV["MATCH_KEYCHAIN_NAME"] = CI_KEYCHAIN_NAME
ENV["MATCH_KEYCHAIN_PASSWORD"] = CI_KEYCHAIN_PASSWORD ENV["MATCH_KEYCHAIN_PASSWORD"] = CI_KEYCHAIN_PASSWORD
end end
@@ -166,5 +180,7 @@ platform :ios do
api_key: api_key, api_key: api_key,
skip_waiting_for_build_processing: true skip_waiting_for_build_processing: true
) )
ensure
delete_keychain(name: CI_KEYCHAIN_NAME) if ci? && File.file?(CI_KEYCHAIN_DB_PATH)
end end
end end