name: Apple CI

on:
  push:
    branches: [main]
    paths:
      - clients/apple/**
      - protocol/**
      - server/src/types/protocol.ts
      - .github/workflows/apple.yml
  pull_request:

permissions:
  contents: read

concurrency:
  group: apple-ci-${{ github.event_name }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  changes:
    name: Detect Apple changes
    runs-on: ubuntu-latest
    outputs:
      relevant: ${{ steps.filter.outputs.relevant }}
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
      - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
        id: filter
        with:
          filters: |
            relevant:
              - 'clients/apple/**'
              - 'protocol/**'
              - 'server/src/types/protocol.ts'
              - '.github/workflows/apple.yml'

  coverage:
    name: Apple coverage
    needs: changes
    if: needs.changes.outputs.relevant == 'true'
    runs-on: macos-26
    timeout-minutes: 30
    env:
      DEVELOPER_DIR: /Applications/Xcode_26.6.app/Contents/Developer
      OPPI_SIM_POOL_COUNT: "1"
    steps:
      - name: Checkout
        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

      - name: Setup Bun
        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
        with:
          bun-version: 1.3.11

      - name: Verify Apple build tools
        id: apple-tools
        run: |
          brew install ripgrep swiftlint xcodegen
          rg --version
          swiftlint version
          xcodegen --version
          XCODE_VERSION="$(xcodebuild -version)"
          echo "$XCODE_VERSION"
          XCODE_BUILD="$(awk '/Build version/ { print $3 }' <<<"$XCODE_VERSION")"
          [[ -n "$XCODE_BUILD" ]]
          echo "xcode_build=$XCODE_BUILD" >> "$GITHUB_OUTPUT"

      - name: Restore bounded Swift package cache
        id: swiftpm-cache
        continue-on-error: true
        uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
        with:
          path: |
            ${{ runner.temp }}/oppi-swiftpm/cache/repositories
            ${{ runner.temp }}/oppi-swiftpm/cache/artifacts
          key: apple-swiftpm-v1-${{ runner.os }}-${{ runner.arch }}-xcode-${{ steps.apple-tools.outputs.xcode_build }}-${{ hashFiles('clients/apple/Oppi.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }}

      - name: Generate the ephemeral Xcode project
        working-directory: clients/apple
        run: xcodegen generate

      - name: Run full iOS unit coverage
        working-directory: clients/apple
        env:
          OPPI_SWIFT_PACKAGE_CACHE_ROOT: ${{ runner.temp }}/oppi-swiftpm
          OPPI_SWIFT_PACKAGE_CACHE_HIT: ${{ steps.swiftpm-cache.outputs.cache-hit }}
        run: ./scripts/check-coverage.sh

      - name: Upload Apple test artifacts
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
        with:
          name: apple-coverage-${{ github.run_id }}
          if-no-files-found: warn
          retention-days: 7
          path: |
            clients/apple/build/coverage/**/*.xcresult
            clients/apple/.build/logs/*.log
            clients/apple/.build/logs/*.json

  required:
    name: Apple CI required
    needs: [changes, coverage]
    if: always()
    runs-on: ubuntu-latest
    steps:
      - name: Enforce relevant coverage result
        env:
          CHANGES_RESULT: ${{ needs.changes.result }}
          RELEVANT: ${{ needs.changes.outputs.relevant }}
          RESULT: ${{ needs.coverage.result }}
        run: |
          if [[ "$CHANGES_RESULT" != "success" || ! "$RELEVANT" =~ ^(true|false)$ ]]; then
            echo "Apple path detection failed (result=$CHANGES_RESULT, relevant=$RELEVANT)." >&2
            exit 1
          fi
          if [[ "$RELEVANT" == "true" && "$RESULT" != "success" ]]; then
            echo "Apple coverage was required but finished with: $RESULT" >&2
            exit 1
          fi
          echo "Apple coverage requirement satisfied (relevant=$RELEVANT, result=$RESULT)."
