name: release

permissions:
  contents: read

on:
  pull_request:
    paths:
    - 'scripts/release_testing_setup.sh'
    - '.github/workflows/release.yml'
    - 'Gemfile*'
  workflow_dispatch:
  schedule:
    # Run every day at 10pm (PDT) / 1am (EDT) - cron uses UTC times
    - cron:  '0 5 * * *'

env:
  FIREBASE_CI: true

concurrency:
    group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
    cancel-in-progress: true

jobs:
  specs_checking:
    # Don't run on private repo unless it is a PR.
    if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'workflow_dispatch'
    runs-on: macos-14
    env:
      botaccess: ${{ secrets.RELEASE_TESTING_PAT }}
      local_repo: specsreleasing
      podspec_repo_branch: main
    outputs:
      matrix: ${{ steps.generate_matrix.outputs.matrix }}
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
      with:
        fetch-depth: 0
    - name: Generate matrix
      id: generate_matrix
      run: |
        cd "${GITHUB_WORKSPACE}/ReleaseTooling"
        swift run manifest --sdk-repo-url "${GITHUB_WORKSPACE}" --output-file-path ./output.json --for-gha-matrix-generation
        echo "::set-output name=matrix::{\"include\":$( cat output.json )}"
    - name: Update SpecsReleasing repo setup
      run: |
         podspec_repo_branch="${podspec_repo_branch}" \
           scripts/release_testing_setup.sh release_testing
    - name: Clean spec repo
      run: |
         git clone --quiet https://"$botaccess"@github.com/Firebase/SpecsReleasing.git "${local_repo}"
         cd "${local_repo}"
         # Remove all unhidden dirs, i.e. all podspec dir from the spec repo.
         rm -Rf -- */
         git add .
         # commit without diff will throw an error. `git diff --exit-code` can avoid such error.
         git diff --staged --exit-code || git commit -m "Empty spec repo."
         # Attempt to push. If it fails, print a detailed error message and exit.
         git push || {
           echo "--------------------------------------------------------------------------------"
            echo "ERROR: Failed to push to Firebase/SpecsReleasing."
            echo "This is likely due to an expired Personal Access Token (PAT)."
            echo "Please take the following steps to resolve this:"
            echo "1. Refresh the OSS bot's scoped access token for the Firebase/SpecsReleasing repo."
            echo "   This can be done in the OSS bot's GitHub account settings. Ensure the token "
            echo "   has the 'public_repo' scope."
            echo "2. Update the 'RELEASE_TESTING_PAT' secret in this repo's settings."
            echo "   (https://github.com/Firebase/firebase-ios-sdk/settings/secrets/actions)"
            echo "--------------------------------------------------------------------------------"
            exit 1
         }
    - uses: actions/upload-artifact@v4
      with:
        name: firebase-ios-sdk
        path: |
          *.podspec
          *.podspec.json

  buildup_SpecsReleasing_repo_FirebaseCore:
    needs: specs_checking
    # Don't run on private repo unless it is a PR.
    if: github.repository == 'Firebase/firebase-ios-sdk'
    runs-on: macos-15
    env:
      botaccess: ${{ secrets.RELEASE_TESTING_PAT }}
      local_repo: specsreleasing
      local_sdk_repo_dir: /tmp/test/firebase-ios-sdk
      targeted_pod: FirebaseCore
    steps:
    - uses: actions/checkout@v4
    - name: Set Xcode version
      run: sudo xcode-select -s /Applications/Xcode_16.4.app
    - uses: actions/download-artifact@v4.1.7
      with:
        name: firebase-ios-sdk
        path: ${{ env.local_sdk_repo_dir }}
    - name: Update SpecsReleasing repo
      run: |
        cd scripts/create_spec_repo/
        swift build
        pod repo add --silent "${local_repo}" https://"$botaccess"@github.com/Firebase/SpecsReleasing.git
        BOT_TOKEN="${botaccess}" ${GITHUB_WORKSPACE}/scripts/third_party/travis/retry.sh .build/debug/spec-repo-builder \
                                --sdk-repo "${local_sdk_repo_dir}" \
                                --local-spec-repo-name "${local_repo}" \
                                --pod-sources 'https://github.com/Firebase/SpecsReleasing' "https://github.com/firebase/SpecsStaging.git" "https://github.com/CocoaPods/Specs.git" \
                                --include-pods "${targeted_pod}" --keep-repo
    - name: Clean Artifacts
      if: ${{ always() }}
      run: pod repo remove "${local_repo}"

  buildup_SpecsReleasing_repo:
    needs: [buildup_SpecsReleasing_repo_FirebaseCore, specs_checking]
    # Don't run on private repo unless it is a PR.
    if: github.repository == 'Firebase/firebase-ios-sdk' || github.event_name == 'workflow_dispatch'
    runs-on: macos-15
    strategy:
      fail-fast: false
      matrix: ${{fromJson(needs.specs_checking.outputs.matrix)}}
    env:
      botaccess: ${{ secrets.RELEASE_TESTING_PAT }}
      local_repo: specsreleasing
      local_sdk_repo_dir: /tmp/test/firebase-ios-sdk
      targeted_pod: ${{ matrix.podspec }}
    steps:
    - uses: actions/checkout@v4
    - name: Set Xcode version
      run: sudo xcode-select -s /Applications/Xcode_16.4.app
    - uses: actions/download-artifact@v4.1.7
      with:
        name: firebase-ios-sdk
        path: ${{ env.local_sdk_repo_dir }}
    # Addresses flaky pushes due to missing git config on runner.
    - name: Set git config
      run: |
        git config --global user.email "google-oss-bot@example.com"
        git config --global user.name "google-oss-bot"
    - name: Update SpecsReleasing repo
      run: |
        [[ ${{ matrix.allowwarnings }} == true ]] && ALLOWWARNINGS=true
        cd scripts/create_spec_repo/
        swift build
        pod repo add --silent "${local_repo}" https://"$botaccess"@github.com/Firebase/SpecsReleasing.git
        # ${ALLOWWARNINGS:+--allow-warnings} will add --allow-warnings to the
        # command if ${ALLOWWARNINGS} is not null.
        BOT_TOKEN="${botaccess}" ${GITHUB_WORKSPACE}/scripts/third_party/travis/retry.sh .build/debug/spec-repo-builder \
                                --sdk-repo "${local_sdk_repo_dir}" \
                                --local-spec-repo-name "${local_repo}" \
                                --pod-sources 'https://github.com/Firebase/SpecsReleasing' "https://github.com/firebase/SpecsStaging.git" "https://github.com/CocoaPods/Specs.git" \
                                --include-pods "${targeted_pod}" \
                                --keep-repo ${ALLOWWARNINGS:+--allow-warnings}
    - name: Clean Artifacts
      if: ${{ always() }}
      run: pod repo remove "${local_repo}"

  quickstart:
    # Don't run on private repo unless it is a PR.
    if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'workflow_dispatch'
    needs: buildup_SpecsReleasing_repo
    strategy:
      matrix:
        include:
          - product: Performance
            run_tests: true
            swift: true
          - product: Storage
            run_tests: true
            swift: true
            is_legacy: true
          - product: Config
            run_tests: true
            objc: true
          - product: Messaging
            run_tests: false
            objc: true
            swift: true
          - product: InAppMessaging
            run_tests: true
            objc: true
            swift: true
          - product: Firestore
            run_tests: false
            objc: true
          - product: Database
            run_tests: false
            objc: true
            swift: true
          - product: Authentication
            run_tests: false
            objc: true
          - product: Crashlytics
            run_tests: true
            swift: true
            is_legacy: true
            setup_command: |
              mkdir -p quickstart-ios/crashlytics/LegacyCrashlyticsQuickstart/Pods/FirebaseCrashlytics
              # Set the deployed pod location of run and upload-symbols with the development pod version.
              cp Crashlytics/run quickstart-ios/crashlytics/LegacyCrashlyticsQuickstart/Pods/FirebaseCrashlytics/
              cp Crashlytics/upload-symbols quickstart-ios/crashlytics/LegacyCrashlyticsQuickstart/Pods/FirebaseCrashlytics/
          - product: ABTesting
            run_tests: true
            objc: true
            is_legacy: true
    env:
      plist_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
      botaccess: ${{ secrets.RELEASE_TESTING_PAT }}
      LEGACY: ${{ matrix.is_legacy && true || '' }}
    runs-on: macos-15
    steps:
    - uses: actions/checkout@v4
    - name: Set Xcode version
      run: sudo xcode-select -s /Applications/Xcode_16.4.app
    - uses: ruby/setup-ruby@354a1ad156761f5ee2b7b13fa8e09943a5e8d252 # v1
    - name: Setup testing repo and quickstart
      run: BOT_TOKEN="${botaccess}" scripts/setup_quickstart.sh ${{ matrix.product }} nightly_release_testing
    - name: Install Secret GoogleService-Info.plist
      run: |
        scripts/decrypt_gha_secret.sh scripts/gha-encrypted/qs-${{ matrix.product }}.plist.gpg \
          quickstart-ios/${{ matrix.product }}/GoogleService-Info.plist "$plist_secret"
    - name: Run setup command, if needed.
      if: matrix.setup_command != ''
      run: ${{ matrix.setup_command }}
    - name: Build Obj-C quickstart
      if: matrix.objc == true
      uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3
      with:
        timeout_minutes: 15
        max_attempts: 3
        retry_wait_seconds: 120
        command: scripts/test_quickstart.sh ${{ matrix.product }} ${{ matrix.run_tests }}
    - name: Build Swift quickstart
      if: matrix.swift == true
      uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3
      with:
        timeout_minutes: 15
        max_attempts: 3
        retry_wait_seconds: 120
        command: scripts/test_quickstart.sh ${{ matrix.product }} ${{ matrix.run_tests }} swift
    - name: Remove data before upload
      if: ${{ failure() }}
      run: scripts/remove_data.sh ${{ matrix.product }}
    - uses: actions/upload-artifact@v4
      if: ${{ failure() }}
      with:
        name: quickstart_artifacts_${{ matrix.product }}
        path: quickstart-ios/

  # TODO: The functions quickstart uses Material which isn't supported by Xcode 15
  # functions_quickstart:
  #   # Don't run on private repo unless it is a PR.
  #   if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
  #   needs: buildup_SpecsReleasing_repo
  #   env:
  #     plist_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
  #     botaccess: ${{ secrets.RELEASE_TESTING_PAT }}
  #     LEGACY: true
  #   runs-on: macos-12
  #   steps:
  #   - uses: actions/checkout@v4
  #   - uses: ruby/setup-ruby@354a1ad156761f5ee2b7b13fa8e09943a5e8d252 # v1
  #   - name: Setup testing repo and quickstart
  #     run: BOT_TOKEN="${botaccess}" scripts/setup_quickstart.sh functions nightly_release_testing
  #   - name: install secret googleservice-info.plist
  #     run: scripts/decrypt_gha_secret.sh scripts/gha-encrypted/qs-functions.plist.gpg \
  #         quickstart-ios/functions/GoogleService-Info.plist "$plist_secret"
  #   - name: Setup custom URL scheme
  #     run: sed -i '' 's/REVERSED_CLIENT_ID/com.googleusercontent.apps.1025801074639-6p6ebi8amuklcjrto20gvpe295smm8u6/' quickstart-ios/functions/LegacyFunctionsQuickstart/FunctionsExample/Info.plist
  #   - name: Test objc quickstart
  #     run: ([ -z $plist_secret ] ||
  #           scripts/third_party/travis/retry.sh scripts/test_quickstart.sh Functions true)
  #   - name: Test swift quickstart
  #     run: ([ -z $plist_secret ] ||
  #           scripts/third_party/travis/retry.sh scripts/test_quickstart.sh Functions true swift)
  #   - name: Remove data before upload
  #     if: ${{ failure() }}
  #     run: scripts/remove_data.sh functions
  #   - uses: actions/upload-artifact@v4
  #     if: ${{ failure() }}
  #     with:
  #       name: quickstart_artifacts_functions
  #       path: quickstart-ios/
