name: iOS CI on: workflow_call: permissions: contents: read pull-requests: write issues: write jobs: lint: name: Lint iOS Code runs-on: macos-15 steps: - name: Checkout code uses: actions/checkout@v4 - name: Select Xcode 16.3 uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: '16.3' - name: Verify Xcode run: | xcodebuild -version swift --version - name: Install linting tools continue-on-error: true shell: bash run: | # Check if tools are already installed, install if not if ! which swiftlint >/dev/null 2>&1; then echo "Installing swiftlint..." brew install swiftlint || echo "Failed to install swiftlint" else echo "swiftlint is already installed at: $(which swiftlint)" fi if ! which swiftformat >/dev/null 2>&1; then echo "Installing swiftformat..." brew install swiftformat || echo "Failed to install swiftformat" else echo "swiftformat is already installed at: $(which swiftformat)" fi # Show final status echo "SwiftLint: $(which swiftlint || echo 'not found')" echo "SwiftFormat: $(which swiftformat || echo 'not found')" - name: Run SwiftFormat (check mode) id: swiftformat continue-on-error: true run: | cd ios swiftformat . --lint 2>&1 | tee ../swiftformat-output.txt echo "result=${PIPESTATUS[0]}" >> $GITHUB_OUTPUT - name: Run SwiftLint id: swiftlint continue-on-error: true run: | cd ios swiftlint 2>&1 | tee ../swiftlint-output.txt echo "result=${PIPESTATUS[0]}" >> $GITHUB_OUTPUT - name: Read SwiftFormat Output if: always() id: swiftformat-output run: | if [ -f swiftformat-output.txt ]; then echo 'content<> $GITHUB_OUTPUT cat swiftformat-output.txt >> $GITHUB_OUTPUT echo 'EOF' >> $GITHUB_OUTPUT else echo "content=No output" >> $GITHUB_OUTPUT fi - name: Read SwiftLint Output if: always() id: swiftlint-output run: | if [ -f swiftlint-output.txt ]; then echo 'content<> $GITHUB_OUTPUT cat swiftlint-output.txt >> $GITHUB_OUTPUT echo 'EOF' >> $GITHUB_OUTPUT else echo "content=No output" >> $GITHUB_OUTPUT fi - name: Report SwiftFormat Results if: always() uses: ./.github/actions/lint-reporter with: title: 'iOS Formatting (SwiftFormat)' lint-result: ${{ steps.swiftformat.outputs.result == '0' && 'success' || 'failure' }} lint-output: ${{ steps.swiftformat-output.outputs.content }} github-token: ${{ secrets.GITHUB_TOKEN }} - name: Report SwiftLint Results if: always() uses: ./.github/actions/lint-reporter with: title: 'iOS Linting (SwiftLint)' lint-result: ${{ steps.swiftlint.outputs.result == '0' && 'success' || 'failure' }} lint-output: ${{ steps.swiftlint-output.outputs.content }} github-token: ${{ secrets.GITHUB_TOKEN }} build: name: Build iOS App runs-on: macos-15 needs: lint timeout-minutes: 30 steps: - name: Checkout code uses: actions/checkout@v4 - name: Select Xcode 16.3 uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: '16.3' - name: Install build tools run: | gem install xcpretty - name: Resolve Dependencies run: | echo "Resolving iOS package dependencies..." xcodebuild -resolvePackageDependencies -workspace VibeTunnel.xcworkspace || echo "Dependency resolution completed" - name: Show build settings run: | xcodebuild -showBuildSettings -workspace VibeTunnel.xcworkspace -scheme VibeTunnel-iOS -destination "generic/platform=iOS" || true - name: Build iOS app run: | set -o pipefail xcodebuild build \ -workspace VibeTunnel.xcworkspace \ -scheme VibeTunnel-iOS \ -destination "generic/platform=iOS" \ -configuration Release \ CODE_SIGNING_ALLOWED=NO \ CODE_SIGNING_REQUIRED=NO \ ONLY_ACTIVE_ARCH=NO \ -derivedDataPath ios/build/DerivedData \ COMPILER_INDEX_STORE_ENABLE=NO \ 2>&1 | tee build.log | xcpretty || { echo "Build failed. Last 100 lines of output:" tail -100 build.log exit 1 } - name: List build products if: always() run: | echo "Searching for iOS build products..." find ios/build -name "*.app" -type d 2>/dev/null || echo "No build products found" ls -la ios/build/DerivedData/Build/Products/ 2>/dev/null || echo "Build products directory not found" # Also check workspace-level build directory ls -la build/DerivedData/Build/Products/ 2>/dev/null || echo "Workspace build products directory not found" - name: Upload build artifacts uses: actions/upload-artifact@v4 if: success() with: name: ios-build-artifacts path: ios/build/DerivedData/Build/Products/Release-iphoneos/ retention-days: 7 test: name: Test iOS App runs-on: macos-15 needs: lint timeout-minutes: 30 steps: - name: Checkout code uses: actions/checkout@v4 - name: Select Xcode 16.3 uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: '16.3' - name: Install test tools run: | gem install xcpretty - name: Resolve Test Dependencies run: | echo "Resolving dependencies for tests..." xcodebuild -resolvePackageDependencies -workspace VibeTunnel.xcworkspace || echo "Dependency resolution completed" - name: Run iOS tests run: | cd ios echo "Running iOS tests using Swift Testing framework..." # Use the provided test script which handles Swift Testing properly chmod +x run-tests.sh ./run-tests.sh || { echo "::error::iOS tests failed" exit 1 } - name: Upload test logs on failure if: failure() run: | echo "Tests failed. Check the logs above for details." # Swift Testing doesn't produce xcresult bundles with run-tests.sh