ci: add workflow to mirror 3rd-party integrations #10402
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Upload to Testflight | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - v8.x | |
| pull_request: | |
| workflow_dispatch: | |
| # Concurrency configuration: | |
| # - We use workflow-specific concurrency groups to prevent multiple TestFlight uploads of the same build, | |
| # as these operations involve app building, signing, and upload to Apple's servers. | |
| # - For pull requests, we cancel in-progress runs when testing workflow changes since only the | |
| # latest configuration needs validation before merging. | |
| # - For main branch pushes (actual uploads), we never cancel uploads to ensure every main branch | |
| # commit gets properly built and distributed to TestFlight for testing by our team. | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| files-changed: | |
| name: Detect File Changes | |
| runs-on: ubuntu-latest | |
| outputs: | |
| run_testflight_for_prs: ${{ steps.changes.outputs.run_testflight_for_prs }} | |
| run_testflight_for_pushes: ${{ steps.changes.outputs.run_testflight_for_pushes }} | |
| is_contributor: ${{ contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR", "CONTRIBUTOR"]'), github.event.pull_request.author_association) }} | |
| is_dependabot: ${{ github.actor == 'dependabot[bot]' }} | |
| is_fork: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Get changed files | |
| id: changes | |
| uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2 | |
| with: | |
| token: ${{ github.token }} | |
| filters: .github/file-filters.yml | |
| skip-testflight-for-non-contributors: | |
| name: Skip Testflight for Non-Contributors | |
| runs-on: ubuntu-latest | |
| needs: files-changed | |
| # Skip for non-contributors or fork PRs, but not for dependabot (handled in upload_to_testflight) | |
| if: | | |
| github.event_name == 'pull_request' && | |
| needs.files-changed.outputs.run_testflight_for_prs == 'true' && | |
| (needs.files-changed.outputs.is_contributor == 'false' || needs.files-changed.outputs.is_fork == 'true') && | |
| needs.files-changed.outputs.is_dependabot == 'false' | |
| steps: | |
| - name: Skip Testflight for Non-Contributors | |
| run: | | |
| echo "Skipping testflight for non-contributors" | |
| exit 0 | |
| upload_to_testflight: | |
| # Run for pushes with changes, or for PRs with related changes (including dependabot) | |
| if: | | |
| ( | |
| github.event_name != 'pull_request' && | |
| needs.files-changed.outputs.run_testflight_for_pushes == 'true' | |
| ) || ( | |
| github.event_name == 'pull_request' && | |
| needs.files-changed.outputs.run_testflight_for_prs == 'true' && | |
| needs.files-changed.outputs.is_fork != 'true' && ( | |
| needs.files-changed.outputs.is_contributor == 'true' || | |
| needs.files-changed.outputs.is_dependabot == 'true' | |
| ) | |
| ) | |
| needs: files-changed | |
| name: Build and Upload iOS-Swift to Testflight | |
| runs-on: macos-26 | |
| steps: | |
| - name: Warm CoreSimulator | |
| run: xcrun simctl list runtimes -j > /dev/null 2>&1 & | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup Xcode | |
| uses: ./.github/actions/setup-xcode | |
| with: | |
| version: "26" | |
| resolve-simulators: "false" | |
| - name: Setup Ruby | |
| uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0 | |
| with: | |
| bundler-cache: true | |
| # As the DistributionSample project uses local SPM, xcodebuild resolves SPM dependencies for all | |
| # sample projects. The Package.swift references binary targets, which in release branch commits points | |
| # to non-existent download URLs. This creates chicken-egg failures when building these sample apps for | |
| # a release commit build. When building these sample apps for a release commit, xcodebuild tries to | |
| # resolve all SPM dependencies, including the binary targets pointing to these non-existent URLs. The | |
| # sample projects don't use SPM for including Sentry. Only the DistributionSample uses local SPM. | |
| # Therefore, we only keep the local DistributionSample reference in the Package.swift as a workaround. | |
| - name: Only keep distribution lib and target in Package.swift | |
| run: ./scripts/prepare-package.sh --remove-binary-targets true | |
| - run: make init-ci-build | |
| - run: make xcode-ci | |
| # We upload a new version to TestFlight on every commit on main | |
| # So we need to bump the build number each time | |
| - name: Bump Build Version | |
| env: | |
| FASTLANE_BUILD_NUMBER: ${{ github.run_number }} | |
| run: bundle exec fastlane bump_build_number | |
| - name: Remove preview version suffixes | |
| run: bundle exec fastlane remove_preview_version_suffixes | |
| - name: Build iOS-Swift | |
| env: | |
| MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} | |
| MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} | |
| MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} | |
| FASTLANE_BUNDLE_VERSION: ${{ github.run_number }} | |
| FASTLANE_KEYCHAIN_PASSWORD: ${{ secrets.FASTLANE_KEYCHAIN_PASSWORD }} | |
| run: bundle exec fastlane build_ios_swift skip_codesigning:${{ needs.files-changed.outputs.is_dependabot == 'true' }} | |
| - name: Upload to TestFlight | |
| if: needs.files-changed.outputs.is_dependabot != 'true' | |
| env: | |
| APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} | |
| APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} | |
| APP_STORE_CONNECT_KEY: ${{ secrets.APP_STORE_CONNECT_KEY }} | |
| SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} | |
| run: bundle exec fastlane ios_swift_to_testflight | |
| - name: TestFlight upload skipped | |
| if: needs.files-changed.outputs.is_dependabot == 'true' | |
| run: | | |
| echo "::warning::TestFlight upload was SKIPPED ON PURPOSE for dependabot PR. Code signing secrets are not available for dependabot PRs." | |
| - name: Archiving | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: dSYMs | |
| path: | | |
| ${{ github.workspace }}/iOS-Swift.* | |
| ${{ github.workspace }}/*.dSYM.zip | |
| ${{ github.workspace }}/dSYMs/ | |
| - name: Run CI Diagnostics | |
| uses: ./.github/actions/ci-diagnostics | |
| if: failure() | |
| # This check validates that either upload_to_testflight passed or was skipped, which allows us | |
| # to make testflight a required check with only running the upload_to_testflight when required. | |
| # So, we don't have to run upload_to_testflight, for example, for unrelated changes. | |
| testflight-required-check: | |
| needs: | |
| [ | |
| files-changed, | |
| upload_to_testflight, | |
| skip-testflight-for-non-contributors, | |
| ] | |
| name: Testflight | |
| # This is necessary since a failed/skipped dependent job would cause this job to be skipped | |
| if: always() | |
| runs-on: ubuntu-latest | |
| steps: | |
| # If any jobs we depend on fails gets cancelled or times out, this job will fail. | |
| # Skipped jobs are not considered failures. | |
| - name: Check for failures | |
| if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') | |
| run: | | |
| echo "One of the testflight jobs has failed." && exit 1 |