Use selected Xcode SDK for local builds - #1294
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
One reliability gap worth addressing before merge:
Minor/unrelated-but-flagging: the default |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e3e3146e26
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # Rust invokes the system compiler through `cc`; without an explicit SDK it | ||
| # can resolve Command Line Tools even when DEVELOPER_DIR points at Xcode. | ||
| # Keep every compiler on the same selected Xcode SDK. | ||
| export SDKROOT="$DEVELOPER_DIR/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" |
There was a problem hiding this comment.
Invalidate cached Rust artifacts when selecting the SDK
When a checkout already contains the Rust build caches, this export does not make the packaged artifacts use the selected SDK: build-kanata.sh and build-kanata-simulator.sh hash only sources, while the host-bridge fingerprint records DEVELOPER_DIR, which was already set before this change. Consequently, build-and-sign.sh can report cache hits and ship binaries previously linked through Command Line Tools; include the SDK/compiler identity or a cache-schema version in each fingerprint so this new build input forces one rebuild.
AGENTS.md reference: AGENTS.md:L56-L65
Useful? React with 👍 / 👎.
|
|
||
| KEYPATH_STABLE_XCODE_VERSION="${KEYPATH_STABLE_XCODE_VERSION:-26.6}" | ||
| KEYPATH_STABLE_XCODE_DEVELOPER_DIR="${KEYPATH_STABLE_XCODE_DEVELOPER_DIR:-/Applications/Xcode-26.6.0.app/Contents/Developer}" | ||
| KEYPATH_STABLE_XCODE_DEVELOPER_DIR="${KEYPATH_STABLE_XCODE_DEVELOPER_DIR:-/Applications/Xcode-26.6.app/Contents/Developer}" |
There was a problem hiding this comment.
Update the documented stable Xcode path
Changing the default to Xcode-26.6.app leaves the canonical workflow documentation telling developers that scripts select /Applications/Xcode-26.6.0.app, even though the same instructions require the stable directory and matching literals to move together. Update that path so setup and future pin changes do not follow a stale installation contract.
AGENTS.md reference: AGENTS.md:L56-L65
Useful? React with 👍 / 👎.
Summary
Validation
⏱️ Timeout: 240s
🛣️ Test lane: full
🔎 Test filter: DeploymentScriptContractTests
🏗️ Test prebuild: 1 | disable XCTest: 0 | reset module cache: 0
🧪 SWIFT_TEST=1 | SKIP_EVENT_TAP_TESTS=1
🪵 KEYPATH_LOG_LEVEL=3 | KEYPATH_TEST_VERBOSE_LOGS=0
🧹 Refreshing generated /Users/malpern/local-code/KeyPath/.worktrees/xcode-sdk-selection/.build/debug symlink
♻️ Reusing generated module cache: /Users/malpern/local-code/KeyPath/.worktrees/xcode-sdk-selection/.build/ModuleCache.noindex
🎯 Swift test args: --filter DeploymentScriptContractTests
📦 Scratch: /Users/malpern/local-code/KeyPath/.worktrees/xcode-sdk-selection/.build | HOME=/private/var/folders/0s/42v7yl697hn0l1cdnx0vrvyr0000gn/T/tmp.EQ4YcqRE1V
🗂️ Module cache: /Users/malpern/local-code/KeyPath/.worktrees/xcode-sdk-selection/.build/ModuleCache.noindex
🔨 Building tests...
[0/1] Planning build
[1/1] Compiling plugin CompileKeyboardStageMetal
[2/2] Compiling plugin GenerateManual
[3/3] Compiling plugin GenerateDoccReference
Building for debugging...
[3/18] Write swift-version--112E4EF74740DA65.txt
Build complete! (2.94s)
🚀 Launching swift test...
[0/1] Planning build
Test Suite 'Selected tests' started at 2026-09-13 09:12:07.749.
Test Suite 'KeyPathPackageTests.xctest' started at 2026-09-13 09:12:07.750.
Test Suite 'DeploymentScriptContractTests' started at 2026-09-13 09:12:07.750.
Test Case '-[KeyPathTests.DeploymentScriptContractTests testBuildAndSignSupportsNonDeployingCandidateBuilds]' started.
Test Case '-[KeyPathTests.DeploymentScriptContractTests testBuildAndSignSupportsNonDeployingCandidateBuilds]' passed (0.002 seconds).
Test Case '-[KeyPathTests.DeploymentScriptContractTests testCanonicalBuildScriptsUseStableXcodeContract]' started.
Test Case '-[KeyPathTests.DeploymentScriptContractTests testCanonicalBuildScriptsUseStableXcodeContract]' passed (0.000 seconds).
Test Case '-[KeyPathTests.DeploymentScriptContractTests testCIRunnerInstallerReadsGitHubJSONRegistration]' started.
Test Case '-[KeyPathTests.DeploymentScriptContractTests testCIRunnerInstallerReadsGitHubJSONRegistration]' passed (0.000 seconds).
Test Case '-[KeyPathTests.DeploymentScriptContractTests testInstalledAppDeployScriptsUseCrossWorktreeLock]' started.
Test Case '-[KeyPathTests.DeploymentScriptContractTests testInstalledAppDeployScriptsUseCrossWorktreeLock]' passed (0.000 seconds).
Test Case '-[KeyPathTests.DeploymentScriptContractTests testInstalledAppVerifierRequiresPackagedSwiftPMResources]' started.
Test Case '-[KeyPathTests.DeploymentScriptContractTests testInstalledAppVerifierRequiresPackagedSwiftPMResources]' passed (0.000 seconds).
Test Case '-[KeyPathTests.DeploymentScriptContractTests testLocalBuildsSharePinnedWorktreeCache]' started.
Test Case '-[KeyPathTests.DeploymentScriptContractTests testLocalBuildsSharePinnedWorktreeCache]' passed (0.001 seconds).
Test Case '-[KeyPathTests.DeploymentScriptContractTests testQuickDeployPreservesBuildFailureDiagnostics]' started.
Test Case '-[KeyPathTests.DeploymentScriptContractTests testQuickDeployPreservesBuildFailureDiagnostics]' passed (0.001 seconds).
Test Case '-[KeyPathTests.DeploymentScriptContractTests testReleaseBuildReadsVersionMetadataFromPlistPaths]' started.
Test Case '-[KeyPathTests.DeploymentScriptContractTests testReleaseBuildReadsVersionMetadataFromPlistPaths]' passed (0.000 seconds).
Test Case '-[KeyPathTests.DeploymentScriptContractTests testSafeTestFailuresAlwaysPrintArtifactPaths]' started.
Test Case '-[KeyPathTests.DeploymentScriptContractTests testSafeTestFailuresAlwaysPrintArtifactPaths]' passed (0.001 seconds).
Test Case '-[KeyPathTests.DeploymentScriptContractTests testSwiftPMWorkflowsRequireInteractiveSafeRunner]' started.
Test Case '-[KeyPathTests.DeploymentScriptContractTests testSwiftPMWorkflowsRequireInteractiveSafeRunner]' passed (0.001 seconds).
Test Case '-[KeyPathTests.DeploymentScriptContractTests testUninstallerPathsTrackAppResources]' started.
Test Case '-[KeyPathTests.DeploymentScriptContractTests testUninstallerPathsTrackAppResources]' passed (0.002 seconds).
Test Suite 'DeploymentScriptContractTests' passed at 2026-09-13 09:12:07.759.
Executed 11 tests, with 0 failures (0 unexpected) in 0.009 (0.010) seconds
Test Suite 'KeyPathPackageTests.xctest' passed at 2026-09-13 09:12:07.759.
Executed 11 tests, with 0 failures (0 unexpected) in 0.009 (0.010) seconds
Test Suite 'Selected tests' passed at 2026-09-13 09:12:07.759.
Executed 11 tests, with 0 failures (0 unexpected) in 0.009 (0.011) seconds
Test run started.
Testing Library Version: 1902
Target Platform: arm64e-apple-macos14.0
Test run with 0 tests in 0 suites passed after 0.001 seconds.
✅ All tests passed (12 passed)
📊 Runner summary: lane=full exit=0 prebuild=1 disable_xctest=0 reset_module_cache=0 build=4s test=1s total=6s build_log=252 bytes build_log_swift_warnings=0 build_log_module_cache_warnings=0 log=3554 bytes test_log_swift_warnings=0 test_log_module_cache_warnings=0 test_log_app_warnings=0 test_log_app_errors=0
✅ Sources/KeyPathHelper/KeyPathHelper.entitlements exists
✅ kanata.entitlements exists
✅ Scripts/build-and-sign.sh exists
✅ Scripts/release-doctor.sh exists
✅ Scripts/verify-release-signing-contract.sh is executable
✅ KeyPath.entitlements is a valid plist
✅ Sources/KeyPathHelper/KeyPathHelper.entitlements is a valid plist
✅ kanata.entitlements is a valid plist
✅ KeyPath.entitlements pins com.apple.security.app-sandbox = false
✅ KeyPath.entitlements pins com.apple.security.network.client = true
✅ KeyPath.entitlements pins com.apple.security.automation.apple-events = true
✅ Sources/KeyPathHelper/KeyPathHelper.entitlements pins com.apple.security.app-sandbox = false
✅ kanata.entitlements pins com.apple.security.device.hid = true
✅ kanata.entitlements pins com.apple.security.device.input-monitoring = true
✅ helper entitlements source is explicit
✅ helper signing uses stable helper identifier
✅ helper signing applies helper entitlements
✅ main app entitlements source is explicit
✅ main app signing applies app entitlements
✅ CLI signing uses helper-trusted stable identifier
✅ release signing uses hardened runtime
✅ Kanata Engine inner binary is hardened-runtime signed
✅ Kanata Engine bundle is hardened-runtime signed
✅ Kanata launcher is hardened-runtime signed
✅ Kanata host bridge is hardened-runtime signed
✅ Kanata simulator is hardened-runtime signed
✅ build-and-sign runs installed-app identity verification
✅ build-and-sign runs source signing-contract verification
✅ build-and-sign refuses to deploy without a stapled notarization ticket
✅ build-and-sign deploys the stapled bundle verbatim (no re-sign on deploy)
✅ notarize-resume deploys the stapled bundle verbatim (no re-sign on deploy)
✅ release-doctor runs source signing-contract verification
✅ Release signing contract passed.
✅ Sparkle signing identity 'keypath' matches SUPublicEDKey
🦀 Building Rust artifacts in parallel (kanata, simulator, host bridge)...
🔬 Building Kanata Simulator from source...
🦀 Building Kanata from source (with TCC-safe caching)...
🧩 Building KeyPath Kanata host bridge...
📁 Kanata source: /Users/malpern/local-code/KeyPath/.worktrees/xcode-sdk-selection/External/kanata
📁 Build directory: /Users/malpern/local-code/KeyPath/.worktrees/xcode-sdk-selection/build
📁 Kanata source: /Users/malpern/local-code/KeyPath/.worktrees/xcode-sdk-selection/External/kanata
📁 Build directory: /Users/malpern/local-code/KeyPath/.worktrees/xcode-sdk-selection/build
✅ Using cached simulator binary
✅ Using cached kanata binary (TCC identity preserved)
kanata-sim 0.1.0
✅ Cached kanata ready: kanata 1.12.1-prerelease-1
📊 Size: 3.1M
🎯 Cache HIT: Host bridge inputs unchanged, verifying existing artifacts
bridge version: 0.1.0
default cfg count: 0
✅ Host bridge ready
✅ All Rust builds complete
🔐 Building privileged helper...
🔐 Building KeyPathHelper (privileged helper)...
1️⃣ Building helper executable...
[0/1] Planning build
Building for production...
[0/3] Write swift-version--112E4EF74740DA65.txt
[1/2] Linking KeyPathHelper
Build of product 'KeyPathHelper' complete! (2.50s)
2️⃣ Signing helper...
✅ Helper build complete: .build/arm64-apple-macosx/release/KeyPathHelper
⏭️ Skipping screenshot regeneration (dev build)
🏗️ Building KeyPath and plugins...
[0/1] Planning build
[1/1] Compiling plugin CompileKeyboardStageMetal
[2/2] Compiling plugin GenerateManual
[3/3] Compiling plugin GenerateDoccReference
Building for production...
[3/12] Write swift-version--112E4EF74740DA65.txt
[4/5] Linking KeyPathHelper
Build complete! (2.17s)
📦 Creating app bundle...
🔌 Assembling Insights.bundle...
✅ Assembled Insights.bundle
📦 Embedding privileged helper (SMAppService layout)...
✅ Verified kanata plist uses Contents/Library/KeyPath/kanata-launcher and omits --debug
✅ Helper embedded: dist/KeyPath.app/Contents/Library/HelperTools/KeyPathHelper
✅ Helper plist embedded: dist/KeyPath.app/Contents/Library/LaunchDaemons/com.keypath.helper.plist
✅ Kanata daemon plist embedded: dist/KeyPath.app/Contents/Library/LaunchDaemons/com.keypath.kanata.plist
✅ Copied app resources
✅ Copied resource bundle: KeyPath_KeyPath.bundle
✅ Copied resource bundle: KeyPath_KeyPathAppKit.bundle
✅ Copied resource bundle: KeyPath_KeyPathInstallationWizard.bundle
🧾 Writing BuildInfo.plist...
✍️ Signing executables...
Applying entitlements from KeyPath.entitlements...
✅ Verifying signatures...
[identity-contract] PASS: Kanata Engine binary exists
[identity-contract] PASS: Kanata daemon shell exists
[identity-contract] PASS: privileged helper exists
[identity-contract] PASS: Kanata daemon plist exists
[identity-contract] PASS: privileged helper plist exists
[identity-contract] PASS: signed Kanata Engine bundle ID is com.keypath.kanata-engine
[identity-contract] PASS: signed Kanata daemon label is com.keypath.kanata
[identity-contract] PASS: signed Kanata daemon BundleProgram is Contents/Library/KeyPath/kanata-launcher
[identity-contract] PASS: signed Kanata daemon associated bundle ID is com.keypath.KeyPath
[identity-contract] PASS: signed helper launchd label is com.keypath.helper
[identity-contract] PASS: signed helper BundleProgram is Contents/Library/HelperTools/KeyPathHelper
[identity-contract] PASS: Kanata Engine.app signing identifier is com.keypath.kanata-engine
[identity-contract] PASS: Kanata Engine.app signed by Developer ID Application: Micah Alpern (X2RKZ5TG99)
[identity-contract] PASS: Kanata Engine.app team identifier is X2RKZ5TG99
[identity-contract] PASS: Kanata Engine.app designated requirement is stable
[identity-contract] PASS: Kanata Engine binary signing identifier is com.keypath.kanata-engine
[identity-contract] PASS: Kanata Engine binary signed by Developer ID Application: Micah Alpern (X2RKZ5TG99)
[identity-contract] PASS: Kanata Engine binary team identifier is X2RKZ5TG99
[identity-contract] PASS: Kanata Engine binary designated requirement is stable
[identity-contract] PASS: KeyPathHelper signing identifier is com.keypath.helper
[identity-contract] PASS: KeyPathHelper signed by Developer ID Application: Micah Alpern (X2RKZ5TG99)
[identity-contract] PASS: KeyPathHelper team identifier is X2RKZ5TG99
[identity-contract] PASS: KeyPathHelper designated requirement is stable
[identity-contract] PASS: kanata-launcher signing identifier is kanata-launcher
[identity-contract] PASS: kanata-launcher signed by Developer ID Application: Micah Alpern (X2RKZ5TG99)
[identity-contract] PASS: kanata-launcher team identifier is X2RKZ5TG99
[identity-contract] PASS: kanata-launcher designated requirement is stable
[identity-contract] all checks passed
⏭️ Skipping notarization (SKIP_NOTARIZE=1)
🎉 Build complete!
📍 Signed app: dist/KeyPath.app
✨ Creating Sparkle update archive...
📦 Creating versioned archive: KeyPath-1.0.2.zip
📝 Generating and signing complete appcast with Sparkle...
Wrote 1 new update, updated 0 existing updates, and removed 0 old updates in appcast.xml
✅ Sparkle archive and signed appcast verified
💿 Creating DMG installer...
✅ DMG created: dist/sparkle/KeyPath-1.0.2.dmg
✅ Sparkle archive created:
📦 Archive: dist/sparkle/KeyPath-1.0.2.zip
📝 Signed appcast: dist/sparkle/appcast.xml
💿 DMG: dist/sparkle/KeyPath-1.0.2.dmg
📂 Deploying to /Applications...
✅ Deployed latest KeyPath to /Applications/KeyPath.app
🚪 Restarting app...
Starting new KeyPath... (production Xcode 26.6; complete signed candidate build)