diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml new file mode 100644 index 0000000..fcc17c5 --- /dev/null +++ b/.github/workflows/ios.yml @@ -0,0 +1,92 @@ +name: iOS Build + Test + +on: + pull_request: + push: + branches: [main] + +# Cancel in-flight runs on a branch when a new commit lands — we only care +# about the latest revision of any given PR / push. +concurrency: + group: ios-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + name: Build + unit tests + # Use the latest macOS image available; xcodebuild + iOS Simulator + # destinations are pre-installed on GitHub Actions macOS runners. + runs-on: macos-latest + timeout-minutes: 25 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Show selected Xcode + available simulators + # Capture environment up-front so a runner-image change that breaks + # the build is easy to diagnose from CI logs. + run: | + sudo xcode-select -p + xcodebuild -version + xcrun simctl list devices available | head -40 + + - name: Resolve a usable iOS Simulator destination + id: pick-sim + # `name=iPhone 17` is fragile — the runner image may be on iPhone 16 + # or earlier. Pick the first available iPhone simulator at runtime + # so the workflow doesn't break every Xcode-image bump. + run: | + DEVICE=$(xcrun simctl list devices available --json \ + | python3 -c 'import json,sys; d=json.load(sys.stdin)["devices"]; + for runtime, devs in d.items(): + if "iOS" not in runtime: continue + for dev in devs: + if dev.get("isAvailable") and "iPhone" in dev["name"]: + print(dev["name"]); sys.exit(0) + sys.exit(1)') + echo "Using simulator: $DEVICE" + echo "device=$DEVICE" >> "$GITHUB_OUTPUT" + + - name: Pre-trust Swift package plugins + # Without trusted fingerprints, `swift-secp256k1`'s SharedSourcesPlugin + # silently fails to enable optional libsecp256k1 modules (ECDH, + # extrakeys, recovery, schnorrsig) — local-only symbols like + # `_secp256k1_ecdh` end up undefined at link time. Setting these + # defaults BEFORE resolving packages allows plugins to run with full + # define expansion. `-skipPackagePluginValidation` alone is not enough. + run: | + defaults write com.apple.dt.Xcode IDEPackageSupportUseBuiltinSCM YES + defaults write com.apple.dt.Xcode IDESkipPackagePluginFingerprintValidatation -bool YES + defaults write com.apple.dt.Xcode IDESkipMacroFingerprintValidation -bool YES + + - name: Resolve packages + run: | + xcodebuild -resolvePackageDependencies \ + -project Clave.xcodeproj \ + -scheme Clave \ + -skipPackagePluginValidation \ + -skipMacroValidation + + - name: xcodebuild test + env: + SIM_DEVICE: ${{ steps.pick-sim.outputs.device }} + run: | + xcodebuild test \ + -project Clave.xcodeproj \ + -scheme Clave \ + -sdk iphonesimulator \ + -destination "platform=iOS Simulator,name=$SIM_DEVICE,OS=latest" \ + -skip-testing:ClaveUITests \ + -skipPackagePluginValidation \ + -skipMacroValidation \ + -resultBundlePath TestResults.xcresult \ + CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO + + - name: Upload xcresult bundle on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: TestResults-${{ github.run_id }} + path: TestResults.xcresult + retention-days: 14 diff --git a/Clave.xcodeproj/project.pbxproj b/Clave.xcodeproj/project.pbxproj index 22b7996..c5a5e69 100644 --- a/Clave.xcodeproj/project.pbxproj +++ b/Clave.xcodeproj/project.pbxproj @@ -708,7 +708,7 @@ CURRENT_PROJECT_VERSION = 31; DEVELOPMENT_TEAM = 944AF56S27; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 26.4; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; MARKETING_VERSION = 0.1.0; PRODUCT_BUNDLE_IDENTIFIER = dev.nostr.ClaveTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -730,7 +730,7 @@ CURRENT_PROJECT_VERSION = 31; DEVELOPMENT_TEAM = 944AF56S27; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 26.4; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; MARKETING_VERSION = 0.1.0; PRODUCT_BUNDLE_IDENTIFIER = dev.nostr.ClaveTests; PRODUCT_NAME = "$(TARGET_NAME)";