name: iOS build and tests on: push: branches: [main] pull_request: workflow_dispatch: permissions: contents: read concurrency: group: ios-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: simulator: runs-on: macos-15 timeout-minutes: 25 steps: - uses: actions/checkout@v4 with: persist-credentials: false - name: Inspect toolchain and project run: | xcodebuild -version swift --version python3 tools/validate_project.py xcodebuild -list -project MusicBridge.xcodeproj - name: Choose available iPhone simulator run: | xcrun simctl list devices available --json > /tmp/musicbridge-simulators.json python3 tools/select_simulator.py /tmp/musicbridge-simulators.json "$(xcrun --sdk iphonesimulator --show-sdk-version)" >> "$GITHUB_ENV" - name: Build and run XCTest shell: bash run: | set -o pipefail mkdir -p build python3 -u tools/tls_fixture.py > build/tls-fixture.log 2>&1 & TLS_PID=$! trap 'kill "$TLS_PID" 2>/dev/null || true' EXIT for attempt in {1..30}; do if grep -q 'TLS fixtures ready' build/tls-fixture.log; then break; fi if ! kill -0 "$TLS_PID" 2>/dev/null; then cat build/tls-fixture.log; exit 1; fi sleep 1 done grep -q 'TLS fixtures ready' build/tls-fixture.log || { cat build/tls-fixture.log; exit 1; } xcodebuild test \ -project MusicBridge.xcodeproj \ -scheme MusicBridge \ -configuration Debug \ -destination "platform=iOS Simulator,id=$SIMULATOR_ID" \ -destination-timeout 120 \ -derivedDataPath DerivedData \ -resultBundlePath build/MusicBridge.xcresult \ CODE_SIGNING_ALLOWED=NO \ | tee build/xcodebuild.log - name: Save diagnostics if: always() uses: actions/upload-artifact@v4 with: name: ios-test-results path: | build/xcodebuild.log build/tls-fixture.log build/MusicBridge.xcresult if-no-files-found: warn retention-days: 7 - name: Archive simulator application run: ditto -c -k --sequesterRsrc --keepParent DerivedData/Build/Products/Debug-iphonesimulator/MusicBridge.app build/MusicBridge-simulator.zip - name: Save simulator application uses: actions/upload-artifact@v4 with: name: MusicBridge-simulator path: build/MusicBridge-simulator.zip retention-days: 7 - name: Build iPhone IPA for local signing shell: bash run: bash tools/package_ipa.sh - name: Save iPhone IPA uses: actions/upload-artifact@v4 with: name: MusicBridge-iPhone path: build/MusicBridge-iPhone.ipa if-no-files-found: error retention-days: 7 - name: Save device build log if: always() uses: actions/upload-artifact@v4 with: name: ios-device-build-log path: build/device-build.log if-no-files-found: ignore retention-days: 7