From 1564490277de98d9be6bfc891c3c95e8705b5757 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Wed, 22 Oct 2025 10:32:08 -0300 Subject: [PATCH 1/2] chore: Test Cirrus Labs runner --- .github/workflows/api-stability.yml | 93 ---- .../assemble-xcframework-variant.yml | 212 -------- .github/workflows/auto-update-tools.yml | 131 ----- .github/workflows/benchmarking.yml | 221 -------- .../build-xcframework-variant-slices.yml | 173 ------ .github/workflows/build.yml | 378 ------------- .../workflows/changes-in-high-risk-code.yml | 80 --- .github/workflows/cirrus-labs.yml | 12 + .github/workflows/codeql-analysis.yml | 94 ---- .../create-issue-for-unreferenced-pr.yml | 103 ---- .github/workflows/danger.yml | 21 - .github/workflows/integration-test.yml | 87 --- .github/workflows/lint-clang-formatting.yml | 83 --- .github/workflows/lint-cocoapods-specs.yml | 93 ---- .github/workflows/lint-dprint-formatting.yml | 66 --- .../workflows/lint-shellcheck-formatting.yml | 66 --- .github/workflows/lint-swift-formatting.yml | 80 --- .../workflows/lint-swiftlint-formatting.yml | 71 --- .github/workflows/lint-xcode-analyze.yml | 65 --- .../workflows/objc-conversion-analysis.yml | 105 ---- .github/workflows/release-comment-issues.yml | 33 -- .../workflows/release-upload-xcframework.yml | 47 -- .github/workflows/release.yml | 370 ------------- .github/workflows/test-cross-platform.yml | 123 ----- .github/workflows/test.yml | 508 ------------------ .github/workflows/testflight.yml | 109 ---- .github/workflows/ui-tests-common.yml | 179 ------ .github/workflows/ui-tests-critical.yml | 153 ------ .github/workflows/ui-tests.yml | 154 ------ .github/workflows/version-bump-util.yml | 124 ----- 30 files changed, 12 insertions(+), 4022 deletions(-) delete mode 100644 .github/workflows/api-stability.yml delete mode 100644 .github/workflows/assemble-xcframework-variant.yml delete mode 100644 .github/workflows/auto-update-tools.yml delete mode 100644 .github/workflows/benchmarking.yml delete mode 100644 .github/workflows/build-xcframework-variant-slices.yml delete mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/changes-in-high-risk-code.yml create mode 100644 .github/workflows/cirrus-labs.yml delete mode 100644 .github/workflows/codeql-analysis.yml delete mode 100644 .github/workflows/create-issue-for-unreferenced-pr.yml delete mode 100644 .github/workflows/danger.yml delete mode 100644 .github/workflows/integration-test.yml delete mode 100644 .github/workflows/lint-clang-formatting.yml delete mode 100644 .github/workflows/lint-cocoapods-specs.yml delete mode 100644 .github/workflows/lint-dprint-formatting.yml delete mode 100644 .github/workflows/lint-shellcheck-formatting.yml delete mode 100644 .github/workflows/lint-swift-formatting.yml delete mode 100644 .github/workflows/lint-swiftlint-formatting.yml delete mode 100644 .github/workflows/lint-xcode-analyze.yml delete mode 100644 .github/workflows/objc-conversion-analysis.yml delete mode 100644 .github/workflows/release-comment-issues.yml delete mode 100644 .github/workflows/release-upload-xcframework.yml delete mode 100644 .github/workflows/release.yml delete mode 100644 .github/workflows/test-cross-platform.yml delete mode 100644 .github/workflows/test.yml delete mode 100644 .github/workflows/testflight.yml delete mode 100644 .github/workflows/ui-tests-common.yml delete mode 100644 .github/workflows/ui-tests-critical.yml delete mode 100644 .github/workflows/ui-tests.yml delete mode 100644 .github/workflows/version-bump-util.yml diff --git a/.github/workflows/api-stability.yml b/.github/workflows/api-stability.yml deleted file mode 100644 index d4b1cc8c7e4..00000000000 --- a/.github/workflows/api-stability.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: API Stability Check - -on: - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple API stability checks on the same code, -# as these analyze public API changes and generate detailed breaking change reports. -# - We always cancel in-progress runs since this workflow only runs on pull requests, and only -# the latest commit's API changes matter for determining if the PR introduces breaking changes. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - # This job detects if the PR contains changes that require running API stability checks. - # If yes, the job will output a flag that will be used by the next job to run the API stability checks. - # If no, the job will output a flag that will be used by the next job to skip running the API stability checks. - # At the end of this workflow, we run a check that validates that either all API stability checks passed or were - # skipped, called api-stability-required-check. - files-changed: - name: Detect File Changes - runs-on: ubuntu-latest - # Map a step output to a job output - outputs: - run_api_stability_for_prs: ${{ steps.changes.outputs.run_api_stability_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - api-stability: - name: Check API Stability (${{ matrix.version }}) - if: needs.files-changed.outputs.run_api_stability_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - name: Checkout code - uses: actions/checkout@v5 - with: - fetch-depth: 0 - - - name: Generate HEAD SDK - run: | - mv sdk_api.json sdk_api_base.json - ./scripts/update-api.sh - - - name: Diagnose breaking changes - run: | - if diff -q "sdk_api_base.json" "sdk_api.json" > /dev/null; then - echo "No API changes detected." - else - echo "❌ Public API changes are detected. If they're intended run "make generate-public-api" and commit the changes." - diff "sdk_api_base.json" "sdk_api.json" || true - xcrun --sdk iphoneos swift-api-digester \ - -diagnose-sdk \ - -o result.json \ - -input-paths sdk_api_base.json \ - -input-paths sdk_api.json \ - -json \ - -v - cat result.json - exit 1 - fi - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - # This check validates that either all API stability checks passed or were skipped, which allows us - # to make API stability checks a required check with only running the API stability checks when required. - # So, we don't have to run API stability checks, for example, for Changelog or ReadMe changes. - - api-stability-required-check: - needs: - [ - files-changed, - api-stability, - ] - name: API Stability - # 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 API stability check jobs has failed." && exit 1 diff --git a/.github/workflows/assemble-xcframework-variant.yml b/.github/workflows/assemble-xcframework-variant.yml deleted file mode 100644 index 238e3880ca8..00000000000 --- a/.github/workflows/assemble-xcframework-variant.yml +++ /dev/null @@ -1,212 +0,0 @@ -name: Assemble XCFramework Variant - -on: - workflow_call: - inputs: - scheme: - description: |- - The Sentry project target to build an XCFramework slice for. - Possible values: Sentry, SentrySwiftUI. - required: true - type: string - - suffix: - description: |- - The suffix to add to the build product name. - E.g. "-Dynamic" or "-WithoutUIKitOrAppKit". - required: false - type: string - - configuration-suffix: - description: |- - The suffix to add to the build product name to build an alternate configuration of the target. - E.g. "WithoutUIKit". - required: false - type: string - - variant-id: - description: |- - The ID of the variant to build an XCFramework slice for. Used to collect appropriate slices for final deliverable assembly. - E.g. "sentry-static", "sentry-dynamic" or "sentry-withoutuikit-dynamic" - required: true - type: string - - signed: - description: |- - Whether or not the assembled XCFramework should be signed. - required: false - type: boolean - default: false - - sdks: - description: |- - The SDK slices to assemble into an XCFramework. - required: false - type: string - default: "iphoneos,iphonesimulator,macosx,maccatalyst,appletvos,appletvsimulator,watchos,watchsimulator,xros,xrsimulator" - - release-version: - description: |- - For release workflows, the version to inject into the SDK. - required: false - type: string - - excluded-archs: - description: |- - The archs to exclude from the XCFramework. - required: false - type: string - - override-name: - description: |- - The name to use for the XCFramework. If not provided, the default name will be used. - required: false - type: string - -jobs: - assemble-xcframework-variant: - name: ${{ inputs.override-name || format('{0}{1}', inputs.scheme, inputs.suffix) }} - - runs-on: macos-14 - steps: - - uses: actions/checkout@v5 - - - uses: ruby/setup-ruby@v1 - if: ${{ inputs.signed }} - with: - bundler-cache: true - - - name: "Download Fastlane Certificate" - if: ${{ inputs.signed }} - run: bundle exec fastlane prepare_xcframework_signing - 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 }} - FASTLANE_KEYCHAIN_PASSWORD: ${{ secrets.FASTLANE_KEYCHAIN_PASSWORD }} - MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - - - name: Get version - id: get-version - env: - RELEASE_VERSION: ${{ inputs.release-version }} - run: | - if [ -n "$RELEASE_VERSION" ]; then - echo "VERSION=$RELEASE_VERSION" >> $GITHUB_ENV - else - echo "VERSION=$(grep MARKETING_VERSION Sources/Configuration/Versioning.xcconfig | cut -d ' ' -f 3)+${{ github.sha }}" >> $GITHUB_ENV - fi - shell: sh - - - name: Set XCFramework name - id: set-xcframework-name - env: - OVERRIDE_NAME: ${{ inputs.override-name }} - SCHEME: ${{ inputs.scheme }} - SUFFIX: ${{ inputs.suffix }} - run: | - if [ -n "$OVERRIDE_NAME" ]; then - echo "XCFRAMEWORK_NAME=$OVERRIDE_NAME" >> $GITHUB_ENV - else - echo "XCFRAMEWORK_NAME=$SCHEME$SUFFIX" >> $GITHUB_ENV - fi - - - name: Compute cache key - env: - SDKS: ${{ inputs.sdks }} - VARIANT_ID: ${{ inputs.variant-id }} - SIGNED: ${{ inputs.signed }} - VERSION: ${{ env.VERSION }} - run: | - sdks_string="$SDKS" - sdks_string_slugified="${sdks_string//,/_}" - echo "SENTRY_XCFRAMEWORK_CACHE_KEY=${{runner.os}}-xcframework-$VARIANT_ID-$sdks_string_slugified-$SIGNED-$VERSION-${{hashFiles('Sources/**')}}-${{hashFiles('Sentry.xcodeproj/**')}}" >> $GITHUB_ENV - - - name: Restore XCFramework cache - id: cache-xcframework - uses: actions/cache@v4 - with: - key: ${{env.SENTRY_XCFRAMEWORK_CACHE_KEY}} - path: ${{env.XCFRAMEWORK_NAME}}.xcframework.zip - - - name: Download ${{inputs.variant-id}} Slices - if: steps.cache-xcframework.outputs.cache-hit != 'true' - uses: actions/download-artifact@v5 - with: - pattern: xcframework-${{inputs.variant-id}}-slice-* - path: xcframework-slices - - - name: Unzip slice artifact ZIP archives - if: steps.cache-xcframework.outputs.cache-hit != 'true' - run: | - find xcframework-slices -type f -print0 | xargs -t0I @ unzip @ -d xcframework-slices - shell: bash - - - name: Remove excluded archs - if: ${{ steps.cache-xcframework.outputs.cache-hit != 'true' && inputs.excluded-archs != '' }} - env: - EXCLUDED_ARCHS: ${{ inputs.excluded-archs }} - run: ./scripts/remove-architectures.sh xcframework-slices/ "$EXCLUDED_ARCHS" - shell: bash - - - name: Assemble XCFramework - if: steps.cache-xcframework.outputs.cache-hit != 'true' - env: - SCHEME: ${{ inputs.scheme }} - SUFFIX: ${{ inputs.suffix }} - CONFIGURATION_SUFFIX: ${{ inputs.configuration-suffix }} - SDKS: ${{ inputs.sdks }} - run: ./scripts/assemble-xcframework.sh "$SCHEME" "$SUFFIX" "$CONFIGURATION_SUFFIX" "$SDKS" "/Users/runner/work/sentry-cocoa/sentry-cocoa/xcframework-slices/SDK_NAME.xcarchive" - shell: bash - - - name: Rename XCFramework - env: - OVERRIDE_NAME: ${{ inputs.override-name }} - XCFRAMEWORK_NAME: ${{ env.XCFRAMEWORK_NAME }} - SCHEME: ${{ inputs.scheme }} - SUFFIX: ${{ inputs.suffix }} - if: ${{ inputs.override-name != '' }} - run: | - mv "${{env.SCHEME}}${{env.SUFFIX}}.xcframework" "${{env.OVERRIDE_NAME}}.xcframework" - shell: bash - - - name: Validate XCFramework structure - # only validate if the xcframework was not cached - if: steps.cache-xcframework.outputs.cache-hit != 'true' - run: ./scripts/validate-xcframework-format.sh "${{env.XCFRAMEWORK_NAME}}.xcframework" - shell: bash - env: - XCFRAMEWORK_NAME: ${{ env.XCFRAMEWORK_NAME }} - - - name: Zip XCFramework - if: steps.cache-xcframework.outputs.cache-hit != 'true' - env: - SIGNED: ${{ inputs.signed }} - SCHEME: ${{ inputs.scheme }} - SUFFIX: ${{ inputs.suffix }} - run: | - if [ "$SIGNED" = "true" ]; then - ./scripts/compress-xcframework.sh --sign "${{env.XCFRAMEWORK_NAME}}" - else - ./scripts/compress-xcframework.sh --not-signed "${{env.XCFRAMEWORK_NAME}}" - fi - shell: bash - - - name: Cache XCFramework - uses: actions/cache@v4 - with: - key: ${{env.SENTRY_XCFRAMEWORK_CACHE_KEY}} - path: ${{env.XCFRAMEWORK_NAME}}.xcframework.zip - - - name: Upload XCFramework - uses: actions/upload-artifact@v4 - with: - overwrite: true - name: xcframework-${{github.sha}}-${{inputs.override-name || inputs.variant-id}} - if-no-files-found: error - path: ${{env.XCFRAMEWORK_NAME}}.xcframework.zip - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh diff --git a/.github/workflows/auto-update-tools.yml b/.github/workflows/auto-update-tools.yml deleted file mode 100644 index 2088b9c2d89..00000000000 --- a/.github/workflows/auto-update-tools.yml +++ /dev/null @@ -1,131 +0,0 @@ -# This workflow is used to update the custom tooling versions for the project. -# -# We prefer to use Dependabot to update external dependencies, but at this time it does not include Homebrew as a supported package manager (https://docs.github.com/en/code-security/dependabot/ecosystems-supported-by-dependabot/supported-ecosystems-and-repositories). -# Furthermore, neither `swiftlint` nor `clang-format` are listed as dependencies in our repository, therefore also not picked up by Dependabot. -# -# Therefore we are using a custom workflow to update relevant files and open a pull request with the changes. - -name: "Automation: Update tooling versions" - -on: - schedule: - - cron: "0 0 * * *" - workflow_dispatch: - pull_request: - -# Permissions configuration: -# - 'contents: write' is required to allow the workflow to commit changes to the repository -# when updating the tooling version files and creating branches for pull requests. -# - 'pull-requests: write' is required to allow the workflow to create pull requests -# using the peter-evans/create-pull-request action when tooling version updates are available. -permissions: - contents: write - pull-requests: write - -# Concurrency configuration: -# - We use a named concurrency group to prevent multiple instances of this workflow from running -# simultaneously, which could lead to race conditions when creating branches and pull requests. -# Since this workflow modifies version files and creates PRs, concurrent runs could interfere -# with each other, resulting in conflicting branches or duplicate PRs. -# - We enable cancellation of in-progress runs because only the most recent run matters for -# version updates. There's no value in completing outdated runs, especially for scheduled -# workflows that might queue up overnight. This approach conserves GitHub Actions minutes -# and ensures we're always working with the latest repository state. -concurrency: - group: "auto-update-tools" - cancel-in-progress: true - -jobs: - # This job detects if the PR contains changes that require running auto-update-tools. - # If yes, the job will output a flag that will be used by the next job to run the auto-update-tools. - # If no, the job will output a flag that will be used by the next job to skip running the auto-update-tools. - # At the end of this workflow, we run a check that validates that either auto_update_tools-required-check passed or were - # skipped, which is called auto_update_tools-required-check. - files-changed: - name: Detect File Changes - runs-on: ubuntu-latest - # Map a step output to a job output - outputs: - run_auto_update_tools_for_prs: ${{ steps.changes.outputs.run_auto_update_tools_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - auto-update-tools: - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_auto_update_tools_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - name: Checkout Repository - uses: actions/checkout@v5 - - - name: Update Homebrew - run: brew update - - - name: Install Tools - run: make init - - - name: Update tooling versions - run: make update-versions - - - name: Check tooling versions - run: make check-versions - - - name: Print git status and changes - run: | - git status - git diff HEAD - - - name: Create pull request for clang-format version - uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e #v7.0.8 - if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} - with: - add-paths: scripts/.clang-format-version - branch: github-actions/auto-update-tools-clang-format - commit-message: "chore(deps): Update clang-format version" - delete-branch: true - title: "chore(deps): Update clang-format version" - sign-commits: true - base: main - - - name: Create pull request for swiftlint version - uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e #v7.0.8 - if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} - with: - add-paths: scripts/.swiftlint-version - branch: github-actions/auto-update-tools-swiftlint - commit-message: "chore(deps): Update swiftlint version" - delete-branch: true - title: "chore(deps): Update swiftlint version" - sign-commits: true - base: main - - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - # This check validates that either auto-update-tools passed or was skipped, which allows us - # to make auto-update-tools a required check with only running the auto-update-tools when required. - # So, we don't have to run auto-update-tools, for example, for unrelated changes. - auto_update_tools-required-check: - needs: - [ - files-changed, - auto-update-tools, - ] - name: Auto Update Tools - # 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 auto-update-tools jobs has failed." && exit 1 diff --git a/.github/workflows/benchmarking.yml b/.github/workflows/benchmarking.yml deleted file mode 100644 index 9f2ee182d17..00000000000 --- a/.github/workflows/benchmarking.yml +++ /dev/null @@ -1,221 +0,0 @@ -name: Benchmarking -on: - push: - branches: - - main - - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple benchmark runs on the same code, -# as benchmarks are extremely resource-intensive and require dedicated device time on SauceLabs. -# - For pull requests, we cancel in-progress runs when new commits are pushed to avoid wasting -# expensive external testing resources and provide timely performance feedback. -# - For main branch pushes, we never cancel benchmarks to ensure we have complete performance -# baselines for every main branch commit, which are critical for performance regression detection. -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_benchmarking_for_prs: ${{ steps.changes.outputs.run_benchmarking_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - build-benchmark-test-target: - name: Build App and Test Runner - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_benchmarking_for_prs == 'true' - needs: files-changed - runs-on: macos-14 - steps: - - uses: actions/checkout@v5 - - run: ./scripts/ci-select-xcode.sh 15.4 - - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - name: Install old xcodegen - # Install xcodegen 2.43.0 for since newer versions don't work with Xcode older than Xcode 16 - # We need to set HOMEBREW_DEVELOPER=1 to allow installing from a local formula - run: | - HOMEBREW_DEVELOPER=1 brew install --formula ./scripts/xcodegen.rb - brew pin xcodegen - - run: make init-ci-build - - run: make xcode-ci - - name: Install SentryCli - run: brew install getsentry/tools/sentry-cli - - name: Cache iOS-Swift App and dSYM build products - id: ios-swift-cache - uses: actions/cache@v4 - with: - path: | - DerivedData/Build/Products/Debug-iphoneos/iOS-Swift.app.dSYM - DerivedData/Build/Products/Debug-iphoneos/iOS-Swift.app - key: ios-swift-for-ui-testing-cache-key-${{ hashFiles('Samples/iOS-Swift/**') }}-${{ hashFiles('Sources/Sentry/**') }} - - name: Cache iOS-Swift UI Test Runner App build product - id: ios-swift-benchmark-runner-cache - uses: actions/cache@v4 - with: - path: | - DerivedData/Build/Products/Debug-iphoneos/iOS-Benchmarking-Runner.app - key: ios-swift-for-ui-testing-cache-key-${{ hashFiles('Samples/iOS-Benchmarking/**') }} - - run: bundle exec fastlane build_ios_swift_for_tests - 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 }} - FASTLANE_KEYCHAIN_PASSWORD: ${{ secrets.FASTLANE_KEYCHAIN_PASSWORD }} - MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - - run: bundle exec fastlane build_ios_benchmark_test - 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 }} - FASTLANE_KEYCHAIN_PASSWORD: ${{ secrets.FASTLANE_KEYCHAIN_PASSWORD }} - MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - - name: Upload dSYMs - run: | - sentry-cli --auth-token ${{ secrets.SENTRY_AUTH_TOKEN }} upload-dif --org sentry-sdks --project sentry-cocoa DerivedData/Build/Products/Debug-iphoneos/iOS-Swift.app.dSYM - - name: Archiving DerivedData - uses: actions/upload-artifact@v4 - with: - name: DerivedData-Xcode - path: | - **/Debug-iphoneos/iOS-Swift.app - **/Debug-iphoneos/iOS-Benchmarking-Runner.app - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - run-ui-tests-with-sauce: - name: Run Benchmarks ${{matrix.suite}} - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_benchmarking_for_prs == 'true' - runs-on: ubuntu-latest - needs: - [ - files-changed, - build-benchmark-test-target, - ] - strategy: - fail-fast: false - matrix: - suite: ["High-end device", "Mid-range device", "Low-end device"] - steps: - - uses: actions/checkout@v5 - - uses: actions/download-artifact@v5 - with: - name: DerivedData-Xcode - - run: npm install -g saucectl@0.186.0 - - name: Run Benchmarks in SauceLab - id: run-benchmarks-in-sauce-lab - env: - SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - # Note: We are not setting continue-on-error here, because we want the step to be marked as failed. - run: | - set -o pipefail && saucectl run \ - --select-suite "${{matrix.suite}}" \ - --config .sauce/benchmarking-config.yml \ - --tags benchmark \ - --verbose \ - 2>&1 | tee output.log - - - name: Recovery - Extract Test ID from output - id: should-retry-test - # Note: We need to use always() here, because the previous run step might be marked as failed. - if: ${{ always() && steps.run-benchmarks-in-sauce-lab.outcome == 'failure' }} - uses: actions/github-script@v8 - env: - SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - with: - # Retry Logic: This step only runs when the benchmark test has failed. - # We determine if the failure was due to SauceLabs infrastructure issues - # (which can be fixed by retrying) or legitimate test failures (which cannot). - # SauceLabs internal errors frequently cause CI failures that can be resolved - # by re-running the test. See scripts/saucelabs-helpers.js for detailed logic. - script: | - const fs = require('fs'); - const { execSync } = require('child_process'); - - console.log("Extracting test ID from output log"); - const outputLog = fs.readFileSync('output.log', 'utf8'); - - // Lookup for the test ID in the output log - // Note: The CLI output might change over time, so this might need to be updated. - const match = outputLog.match(/https:\/\/app\.saucelabs\.com\/tests\/([^\s]+)/); - const testId = match?.[1] ?? ''; - - if (!testId) { - core.warning("No SauceLabs test ID found in CLI output, it might have changed, retrying..."); - core.setOutput('RETRY_TEST', 'true'); - - return; - } - - try { - console.log(`Checking if the test exists in SauceLabs: ${testId}`); - execSync(`saucectl jobs get ${testId}`, { - env: process.env, - stdio: 'inherit' - }); - - console.log("Test exists but failed, not retrying."); - core.setFailed('Test exists but failed'); - } catch (error) { - console.log("Failed to get job, retrying..."); - core.setOutput('RETRY_TEST', 'true'); - } - - - name: Run Benchmarks in SauceLab - Retry 1 - id: run-benchmarks-in-sauce-lab-retry-1 - # Note: We need to use always() here, because the previous run step might be marked as failed. - if: ${{ always() && steps.should-retry-test.outputs.RETRY_TEST == 'true' }} - env: - SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - run: | - echo "::warning SauceLabs benchmark tests need to be retried" - saucectl run \ - --select-suite "${{matrix.suite}}" \ - --config .sauce/benchmarking-config.yml \ - --tags benchmark \ - --verbose - - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - benchmarking-required-check: - needs: - [ - files-changed, - build-benchmark-test-target, - run-ui-tests-with-sauce, - ] - name: Benchmarking - # 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 benchmark jobs has failed." && exit 1 diff --git a/.github/workflows/build-xcframework-variant-slices.yml b/.github/workflows/build-xcframework-variant-slices.yml deleted file mode 100644 index 273ed0249ff..00000000000 --- a/.github/workflows/build-xcframework-variant-slices.yml +++ /dev/null @@ -1,173 +0,0 @@ -name: Build XCFramework Slice - -on: - workflow_call: - inputs: - sdk-list: - description: |- - The list of Apple platform SDKs for which to build slices and assemble into an XCFramework. This must be a JSON array of strings, itself in a string since GitHub Actions doesn't support arrays as inputs. - Possible values: iphoneos, iphonesimulator, macosx, appletvos, appletvsimulator, watchos, watchsimulator, xros, xrsimulator. - required: false - default: '["iphoneos", "iphonesimulator", "macosx", "maccatalyst", "appletvos", "appletvsimulator", "watchos", "watchsimulator", "xros", "xrsimulator"]' - type: string - - name: - description: |- - The Sentry project target to build an XCFramework slice for. - Possible values: Sentry, SentrySwiftUI. - required: true - type: string - - suffix: - description: |- - The suffix to add to the build product name. - E.g. "-Dynamic" or "-WithoutUIKitOrAppKit". - required: false - type: string - - macho-type: - description: |- - The Mach-O type of the build product. - Possible values: mh_dylib, staticlib. - required: false - type: string - default: "mh_dylib" - - configuration-suffix: - description: |- - The suffix to add to the build product name to build an alternate configuration of the target. - E.g. "WithoutUIKit". - required: false - type: string - - variant-id: - description: |- - The ID of the variant to build an XCFramework slice for. Used to collect appropriate slices for final deliverable assembly. - required: true - type: string - - release-version: - description: |- - For release workflows, the version to inject into the SDK. - required: false - type: string - -jobs: - build-xcframework-variant-slices: - name: ${{matrix.sdk}} - - # We must compile this on an arm64 runner, cause it's required for visionOS. macos-14 uses arm64. - # To see the available runners see https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories. - runs-on: macos-14 - - strategy: - matrix: - sdk: ${{ fromJson(inputs.sdk-list) }} - - steps: - - uses: actions/checkout@v5 - - # We have to compile on Xcode 15.2 because compiling on Xcode 15.4 fails with - # Data+SentryTracing.swift:21:62: error: 'ReadingOptions' aliases 'Foundation.ReadingOptions' - # and cannot be used here because C++ types from imported module 'Foundation' do not support - # library evolution; this is an error in the Swift 6 language mode - # We also can't use Xcode 16.x because validating the XCFramework then fails with Xcode 15.x. - - run: ./scripts/ci-select-xcode.sh 15.2 - shell: bash - - - name: Get version - id: get-version - env: - GITHUB_SHA: ${{ github.sha }} - RELEASE_VERSION: ${{ inputs.release-version }} - run: | - if [ -n "$RELEASE_VERSION" ]; then - echo "VERSION=$RELEASE_VERSION" >> $GITHUB_ENV - else - echo "VERSION=$(grep MARKETING_VERSION Sources/Configuration/Versioning.xcconfig | cut -d ' ' -f 3)+$GITHUB_SHA" >> $GITHUB_ENV - fi - shell: sh - - - name: Compute cache key - env: - RUNNER_OS: ${{ runner.os }} - VARIANT_ID: ${{ inputs.variant-id }} - MATRIX_SDK: ${{ matrix.sdk }} - VERSION: ${{ env.VERSION }} - run: | - echo "SENTRY_XCFRAMEWORK_CACHE_KEY=${RUNNER_OS}-xcframework-${VARIANT_ID}-slice-${MATRIX_SDK}-${VERSION}-${{hashFiles('Sources/**')}}-${{hashFiles('Sentry.xcodeproj/**')}}" >> $GITHUB_ENV - - - name: Restore xcarchive cache - id: cache-xcarchive - uses: actions/cache@v4 - with: - key: ${{env.SENTRY_XCFRAMEWORK_CACHE_KEY}} - path: ${{inputs.name}}${{inputs.suffix}}.xcarchive.zip - - - name: Bump version - if: steps.cache-xcarchive.outputs.cache-hit != 'true' - env: - VERSION: ${{ env.VERSION }} - run: | - ./scripts/ci-select-xcode.sh 15.2 - make bump-version TO=$VERSION - - - name: Build ${{inputs.name}}${{inputs.suffix}} XCFramework slice for ${{matrix.sdk}} - if: steps.cache-xcarchive.outputs.cache-hit != 'true' - env: - MATRIX_SDK: ${{ matrix.sdk }} - INPUT_NAME: ${{ inputs.name }} - INPUT_SUFFIX: ${{ inputs.suffix }} - INPUT_MACHO_TYPE: ${{ inputs.macho-type }} - INPUT_CONFIG_SUFFIX: ${{ inputs.configuration-suffix }} - run: ./scripts/build-xcframework-slice.sh "$MATRIX_SDK" "$INPUT_NAME" "$INPUT_SUFFIX" "$INPUT_MACHO_TYPE" "$INPUT_CONFIG_SUFFIX" - shell: bash - - # The SentrySwiftUI archive build also builds Sentry.framework as a byproduct of the dependency. We need to remove that to avoid downstream assembly tasks from tripping on these extra files. In the future we could investigate using this byproduct instead of running a separate task for Sentry.framework, or use the one already built by that other task instead of rebuilding it here. - - name: Remove Sentry.framework from SentrySwiftUI build - if: steps.cache-xcarchive.outputs.cache-hit != 'true' && inputs.name == 'SentrySwiftUI' - env: - GITHUB_WORKSPACE: ${{ github.workspace }} - run: | - find "$GITHUB_WORKSPACE/Carthage/archive" -name "Sentry.framework" -print0 | xargs -t0 rm -rf - find "$GITHUB_WORKSPACE/Carthage/archive" -name "Sentry.framework.dSYM" -print0 | xargs -t0 rm -rf - shell: bash - - # the upload action broke symlinks in the mac sdk slice's xcarchive - - name: Zip xcarchive - if: steps.cache-xcarchive.outputs.cache-hit != 'true' - env: - GITHUB_WORKSPACE: ${{ github.workspace }} - INPUT_NAME: ${{ inputs.name }} - INPUT_SUFFIX: ${{ inputs.suffix }} - MATRIX_SDK: ${{ matrix.sdk }} - run: | - ditto -c -k -X --rsrc --keepParent ${GITHUB_WORKSPACE}/Carthage/archive/${INPUT_NAME}${INPUT_SUFFIX}/${MATRIX_SDK}.xcarchive ${INPUT_NAME}${INPUT_SUFFIX}.xcarchive.zip - shell: bash - - - name: Cache xcarchive - if: steps.cache-xcarchive.outputs.cache-hit != 'true' - uses: actions/cache@v4 - with: - key: ${{env.SENTRY_XCFRAMEWORK_CACHE_KEY}} - path: ${{inputs.name}}${{inputs.suffix}}.xcarchive.zip - - - name: Upload xcarchive - uses: actions/upload-artifact@v4 - with: - name: xcframework-${{inputs.variant-id}}-slice-${{matrix.sdk}} - if-no-files-found: error - path: | - ${{inputs.name}}${{inputs.suffix}}.xcarchive.zip - - - name: Upload build log if failed - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-build-output-build-xcframework-${{inputs.variant-id}}-${{matrix.sdk}} - path: | - *.log - - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 0748b5e9f9c..00000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,378 +0,0 @@ -name: Build -on: - push: - branches: - - main - - release/** - - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple build runs of the same code, -# which would waste CI resources without providing additional value. -# - For pull requests, we cancel in-progress builds when new commits are pushed since only the -# latest commit's build results matter for merge decisions. -# - For main branch pushes, we never cancel builds to ensure all release and sample builds complete, -# as broken builds on main could block releases and affect downstream consumers. -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_build_for_prs: ${{ steps.changes.outputs.run_build_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - # We had issues that the release build was broken on main. - # With this we catch potential issues already in the PR. - ios-swift-release: - name: Release Build of iOS Swift - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - uses: actions/checkout@v5 - - run: ./scripts/ci-select-xcode.sh 16.4 - - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - run: make init-ci-build - - run: make xcode-ci - - name: Run Fastlane - 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 }} - FASTLANE_KEYCHAIN_PASSWORD: ${{ secrets.FASTLANE_KEYCHAIN_PASSWORD }} - MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - run: bundle exec fastlane build_ios_swift - - - name: Debug Xcode environment - if: ${{ failure() || cancelled() }} - run: ./scripts/ci-diagnostics.sh - - build-sample: - name: Sample ${{ matrix.scheme }} ${{ matrix.config }} - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - strategy: - fail-fast: false - matrix: - # other sample projects are built in ui-tests - include: - - scheme: watchOS-Swift WatchKit App - config: Debug - - scheme: macOS-SwiftUI - config: Debug - - scheme: SessionReplay-CameraTest - config: Debug - - scheme: iOS-Swift - config: DebugV9 - - scheme: macOS-Swift - config: DebugV9 - - scheme: tvOS-Swift - config: DebugV9 - - scheme: visionOS-Swift - config: DebugV9 - - scheme: iOS-SwiftUI - config: DebugV9 - - scheme: iOS-ObjectiveC - config: DebugV9 - - scheme: DistributionSample - config: Debug - - steps: - - uses: actions/checkout@v5 - - run: ./scripts/ci-select-xcode.sh 16.4 - - run: make init-ci-build - - run: make xcode-ci - - # Note: Due to complexity in implementing the CODE_SIGNING_ALLOWED flag in the sentry-xcodebuild.sh script, - # we did not yet migrate this step to use the script yet. - - run: >- - set -o pipefail && NSUnbufferedIO=YES xcodebuild - -workspace Sentry.xcworkspace - -scheme '${{matrix.scheme}}' - -configuration '${{matrix.config}}' - CODE_SIGNING_ALLOWED="NO" - build 2>&1 - | tee raw-build-output.log - | xcbeautify --preserve-unbeautified - - - name: Archiving Raw Build Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-build-output-scheme-${{matrix.scheme}} - path: | - raw-build-output.log - - - name: Debug Xcode environment - if: ${{ failure() || cancelled() }} - run: ./scripts/ci-diagnostics.sh - - build-distribution: - name: Build the distribution framework - runs-on: macos-15 - needs: files-changed - steps: - - uses: actions/checkout@v5 - - - run: ./scripts/ci-select-xcode.sh 16.4 - shell: sh - - run: rm -r Sentry.xcodeproj && rm -r Sentry.xcworkspace - - run: set -o pipefail && NSUnbufferedIO=YES xcodebuild build -scheme SentryDistribution -sdk iphoneos -destination 'generic/platform=iphoneos' | tee raw-build-output-spm.log | xcbeautify - shell: sh - - name: Upload SPM Build Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-build-output-spm - path: | - raw-build-output-spm.log - - build-spm: - name: Build with SPM - runs-on: macos-15 - # Don't run this on release branches, cause the SPM Package.swift points to the unreleased versions. - if: startsWith(github.ref, 'refs/heads/release/') == false && (github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true') - needs: files-changed - steps: - - uses: actions/checkout@v5 - - - run: ./scripts/ci-select-xcode.sh 16.4 - shell: sh - - run: rm -r Sentry.xcodeproj && rm -r Sentry.xcworkspace - - run: set -o pipefail && NSUnbufferedIO=YES EXPERIMENTAL_SPM_BUILDS=1 xcodebuild build -scheme SentrySPM -sdk watchos -destination 'generic/platform=watchOS' | tee raw-build-output-spm-watchos.log | xcbeautify - shell: sh - - run: set -o pipefail && NSUnbufferedIO=YES EXPERIMENTAL_SPM_BUILDS=1 xcodebuild build -scheme SentrySPM -sdk iphoneos -destination 'generic/platform=iphoneos' | tee raw-build-output-spm-iphoneos.log | xcbeautify - shell: sh - - - name: Upload SPM Build Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-build-output-spm - path: | - raw-build-output-spm-watchos.log - raw-build-output-spm-iphoneos.log - - - name: Debug Xcode environment - if: ${{ failure() || cancelled() }} - run: ./scripts/ci-diagnostics.sh - - build-v9: - name: Build SDK v9 - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - uses: actions/checkout@v5 - - run: ./scripts/ci-select-xcode.sh 16.4 - - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform iOS \ - --os 18.4 \ - --command build \ - --device "iPhone 16 Pro" \ - --configuration DebugV9 - - name: Archiving Raw Build Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-build-output-v9 - path: | - raw-build-output.log - - name: Debug Xcode environment - if: ${{ failure() || cancelled() }} - run: ./scripts/ci-diagnostics.sh - - check-debug-without-UIKit: - name: Check no UIKit linkage (DebugWithoutUIKit) - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - uses: actions/checkout@v5 - - - run: ./scripts/ci-select-xcode.sh 16.4 - - - name: Build for Debug - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform iOS \ - --os 18.4 \ - --ref ${{ github.ref }} \ - --command build \ - --device "iPhone 16 Pro" \ - --configuration DebugWithoutUIKit \ - --derived-data uikit-check-build - - - name: Ensure UIKit is not linked - run: ./scripts/check-uikit-linkage.sh DebugWithoutUIKit uikit-check-build unlinked SentryWithoutUIKit - - - name: Debug Xcode environment - if: ${{ failure() || cancelled() }} - run: ./scripts/ci-diagnostics.sh - - check-release-without-UIKit: - name: Check no UIKit linkage (ReleaseWithoutUIKit) - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - uses: actions/checkout@v5 - - - run: ./scripts/ci-select-xcode.sh 16.4 - - - name: Build for Release - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform iOS \ - --os 18.4 \ - --ref ${{ github.ref }} \ - --command build \ - --device "iPhone 16 Pro" \ - --configuration ReleaseWithoutUIKit \ - --derived-data uikit-check-build - - - name: Ensure UIKit is not linked - run: ./scripts/check-uikit-linkage.sh ReleaseWithoutUIKit uikit-check-build unlinked SentryWithoutUIKit - - - name: Debug Xcode environment - if: ${{ failure() || cancelled() }} - run: ./scripts/ci-diagnostics.sh - - check-debug-with-UIKit: - name: Check UIKit linkage (Debug) - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - uses: actions/checkout@v5 - - - run: ./scripts/ci-select-xcode.sh 16.4 - - - name: Build for Debug - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform iOS \ - --os 18.4 \ - --ref ${{ github.ref }} \ - --command build \ - --device "iPhone 16 Pro" \ - --configuration Debug \ - --derived-data uikit-check-build - - - name: Ensure UIKit is linked - run: ./scripts/check-uikit-linkage.sh Debug uikit-check-build linked Sentry - - - name: Debug Xcode environment - if: ${{ failure() || cancelled() }} - run: ./scripts/ci-diagnostics.sh - - check-release-with-UIKit: - name: Check UIKit linkage (Release) - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - uses: actions/checkout@v5 - - - run: ./scripts/ci-select-xcode.sh 16.4 - - - name: Build for Release - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform iOS \ - --os 18.4 \ - --ref ${{ github.ref }} \ - --command build \ - --device "iPhone 16 Pro" \ - --configuration Release \ - --derived-data uikit-check-build - - - name: Ensure UIKit is linked - run: ./scripts/check-uikit-linkage.sh Release uikit-check-build linked Sentry - - - name: Debug Xcode environment - if: ${{ failure() || cancelled() }} - run: ./scripts/ci-diagnostics.sh - - # The compiler only evaluates SentryAsyncSafeLogs that get printed based on the SENTRY_ASYNC_SAFE_LOG_LEVEL. - # So if the level is set to error, which is the default, and a SENTRY_ASYNC_SAFE_LOG_DEBUG has a compiler error, - # you only get the compiler error when setting the SENTRY_ASYNC_SAFE_LOG_LEVEL to SENTRY_ASYNC_SAFE_LOG_LEVEL_DEBUG or lower. - - check-compiling-async-safe-logs: - name: Check compiling Async Safe Logs - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - uses: actions/checkout@v5 - - # If the SentryAsyncSafeLog doesn't contain the SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR this fails. - - name: Async Safe Log Level is Error - run: grep -c "SENTRY_ASYNC_SAFE_LOG_LEVEL SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR" Sources/Sentry/SentryAsyncSafeLog.h - - - name: Set Async Safe Log Level to Debug - run: | - sed -i '' 's/#define SENTRY_ASYNC_SAFE_LOG_LEVEL SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR/#define SENTRY_ASYNC_SAFE_LOG_LEVEL SENTRY_ASYNC_SAFE_LOG_LEVEL_TRACE/' Sources/Sentry/SentryAsyncSafeLog.h - shell: bash - - - run: ./scripts/ci-select-xcode.sh 16.4 - - - name: Build for Debug - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform iOS \ - --os 18.4 \ - --ref ${{ github.ref }} \ - --command build \ - --device "iPhone 16 Pro" \ - --configuration Debug - - - name: Debug Xcode environment - if: ${{ failure() || cancelled() }} - run: ./scripts/ci-diagnostics.sh - - build-required-check: - needs: - [ - files-changed, - ios-swift-release, - build-sample, - build-distribution, - build-spm, - build-v9, - check-debug-without-UIKit, - check-release-without-UIKit, - check-debug-with-UIKit, - check-release-with-UIKit, - check-compiling-async-safe-logs, - ] - name: Build - # 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 build jobs has failed." && exit 1 diff --git a/.github/workflows/changes-in-high-risk-code.yml b/.github/workflows/changes-in-high-risk-code.yml deleted file mode 100644 index 0bb747ac8d6..00000000000 --- a/.github/workflows/changes-in-high-risk-code.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: Changes In High Risk Code -on: - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple high-risk code analysis runs, -# as these detect changes to critical code paths and trigger additional validation workflows. -# - We always cancel in-progress runs since this workflow only runs on pull requests, and only -# the latest commit's high-risk code changes matter for determining which additional tests to run. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - files-changed: - name: Detect File Changes - runs-on: ubuntu-latest - # Map a step output to a job output - outputs: - high_risk_code: ${{ steps.changes.outputs.high_risk_code }} - high_risk_code_files: ${{ steps.changes.outputs.high_risk_code_files }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - # Enable listing of files matching each filter. - # Paths to files will be available in `${FILTER_NAME}_files` output variable. - list-files: csv - - validate-high-risk-code: - name: Validate High-Risk Code - if: needs.files-changed.outputs.high_risk_code == 'true' - needs: files-changed - runs-on: ubuntu-latest - steps: - - name: Remove previous comments - uses: actions/github-script@v8 - with: - script: | - core.debug('Listing comments') - const response = await github.rest.issues.listComments({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo - }) - if (!response.data) { - core.info('No comments found') - return - } - core.debug(`Found ${response.data.length} comments`) - for (const comment of response.data) { - if (comment.user.login === 'github-actions[bot]' && comment.body.includes('### 🚨 Detected changes in high risk code 🚨')) { - core.info(`Deleting comment ${comment.id}`) - await github.rest.issues.deleteComment({ - comment_id: comment.id, - owner: context.repo.owner, - repo: context.repo.repo, - }) - } - } - - name: Comment on PR to notify of changes in high risk files - uses: actions/github-script@v8 - env: - high_risk_code: ${{ needs.files-changed.outputs.high_risk_code_files }} - with: - script: | - const highRiskFiles = process.env.high_risk_code; - const fileList = highRiskFiles.split(',').map(file => `- [ ] ${file}`).join('\n'); - - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: `### 🚨 Detected changes in high risk code 🚨 \n High-risk code can easily blow up and is hard to test. We had severe bugs in the past. Be extra careful when changing these files, and have an extra careful look at these:\n ${fileList}` - }) diff --git a/.github/workflows/cirrus-labs.yml b/.github/workflows/cirrus-labs.yml new file mode 100644 index 00000000000..1d950414932 --- /dev/null +++ b/.github/workflows/cirrus-labs.yml @@ -0,0 +1,12 @@ +name: Cirrus Labs +on: + pull_request: + +jobs: + macos: + name: "Test Cirrus Labs" + runs-on: ghcr.io/cirruslabs/macos-runner:ventura + steps: + - uses: actions/checkout@v4 + - name: List Installed Xcodes + run: xcodes installed diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 7affaee6d7a..00000000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,94 +0,0 @@ -name: CodeQL - -on: - push: - branches: [main] - pull_request: - branches: - - main - schedule: - - cron: "40 4 * * 6" # Weekly scheduled run to catch issues regardless of changes - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple CodeQL security analysis runs, -# as these are comprehensive security scans that shouldn't run simultaneously. -# - For pull requests, we cancel in-progress runs when new commits are pushed since only the -# latest security analysis results matter for identifying potential vulnerabilities. -# - For main branch pushes and scheduled runs, we never cancel security analysis to ensure -# complete security validation and maintain our security baseline with weekly scheduled scans. -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_codeql_analysis_for_prs: ${{ steps.changes.outputs.run_codeql_analysis_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - analyze: - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_codeql_analysis_for_prs == 'true' - needs: files-changed - name: Analyze (${{ matrix.language }}) - runs-on: macos-14 - - strategy: - fail-fast: false - matrix: - language: ["cpp"] - - steps: - - name: Checkout repository - uses: actions/checkout@v5 - - - name: Initialize CodeQL - uses: github/codeql-action/init@v4 - with: - languages: ${{ matrix.language }} - - - run: | - set -o pipefail && NSUnbufferedIO=YES xcodebuild \ - -workspace Sentry.xcworkspace \ - -scheme Sentry \ - -configuration Release \ - -destination platform="iOS Simulator,OS=16.4,name=iPhone 14 Pro" \ - build 2>&1 | - tee raw-analyze-output.log | - xcbeautify - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 - - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - # This check validates that either analyze passed or was skipped, which allows us - # to make CodeQL analysis a required check with only running the analysis when required. - # So, we don't have to run CodeQL analysis, for example, for unrelated changes. - codeql_analysis-required-check: - needs: - [ - files-changed, - analyze, - ] - name: Analyze - # 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 CodeQL analysis jobs has failed." && exit 1 diff --git a/.github/workflows/create-issue-for-unreferenced-pr.yml b/.github/workflows/create-issue-for-unreferenced-pr.yml deleted file mode 100644 index cfe192e0689..00000000000 --- a/.github/workflows/create-issue-for-unreferenced-pr.yml +++ /dev/null @@ -1,103 +0,0 @@ -# This GitHub Action workflow checks if a new or updated pull request -# references a GitHub issue in its title or body. If no reference is found, -# it automatically creates a new issue. This helps ensure all work is -# tracked, especially when syncing with tools like Linear. - -name: Create issue for unreferenced PR - -# This action triggers on pull request events -on: - pull_request: - types: [opened, edited, reopened, synchronize, ready_for_review] - -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - check_for_issue_reference: - runs-on: ubuntu-latest - steps: - - name: Check PR Body and Title for Issue Reference - uses: actions/github-script@v8 - with: - script: | - const pr = context.payload.pull_request; - if (!pr) { - core.setFailed('Could not get PR from context.'); - return; - } - - // Don't create an issue for draft PRs - if (pr.draft) { - console.log(`PR #${pr.number} is a draft, skipping issue creation.`); - return; - } - - // Check if the PR is already approved - const reviewsResponse = await github.rest.pulls.listReviews({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: pr.number, - }); - - if (reviewsResponse.data.some(review => review.state === 'APPROVED')) { - console.log(`PR #${pr.number} is already approved, skipping issue creation.`); - return; - } - - const prBody = pr.body || ''; - const prTitle = pr.title || ''; - const prAuthor = pr.user.login; - const prUrl = pr.html_url; - const prNumber = pr.number; - - // Regex for GitHub issue references (e.g., #123, fixes #456) - const issueRegexGitHub = /(?:(?:close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)\s*)?#\d+/i; - - // Regex for Linear issue references (e.g., ENG-123, resolves ENG-456) - const issueRegexLinear = /(?:(?:close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)\s*)?[A-Z]+-\d+/i; - - const contentToCheck = `${prTitle} ${prBody}`; - const hasIssueReference = issueRegexGitHub.test(contentToCheck) || issueRegexLinear.test(contentToCheck); - - if (hasIssueReference) { - console.log(`PR #${prNumber} contains a valid issue reference.`); - return; - } - - core.warning(`PR #${prNumber} does not have an issue reference. Creating a new issue so it can be tracked in Linear.`); - - // Construct the title and body for the new issue - const issueTitle = `${prTitle}`; - const issueBody = `> [!NOTE] - > The pull request "[${prTitle}](${prUrl})" was created by @${prAuthor} but did not reference an issue. Therefore this issue was created for better visibility in external tools like Linear. - - ${prBody} - `; - - // Create the issue using the GitHub API - const newIssue = await github.rest.issues.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: issueTitle, - body: issueBody, - assignees: [prAuthor] - }); - - const issueID = newIssue.data.number; - console.log(`Created issue #${issueID}.`); - - // Update the PR body to reference the new issue - const updatedPrBody = `${prBody}\n\nCloses #${issueID}`; - - await github.rest.pulls.update({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: prNumber, - body: updatedPrBody - }); - - console.log(`Updated PR #${prNumber} to reference newly created issue #${issueID}.`); diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml deleted file mode 100644 index 6d6f1e288cb..00000000000 --- a/.github/workflows/danger.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Danger - -on: - pull_request: - types: [opened, synchronize, reopened, edited, ready_for_review] - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple Danger runs on the same PR, -# as Danger performs PR validation and comment generation that should be based on the latest code. -# - We always cancel in-progress runs since this workflow only runs on pull requests, and only -# the latest commit's validation results matter for providing accurate PR feedback and reviews. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - danger: - name: Danger - runs-on: ubuntu-latest - steps: - - uses: getsentry/github-workflows/danger@v3 diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml deleted file mode 100644 index 4583cb9d51b..00000000000 --- a/.github/workflows/integration-test.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: Test CocoaPods -on: - push: - branches: - - main - - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple CocoaPods integration tests, -# as these tests involve complex dependency resolution and build processes. -# - For pull requests, we cancel in-progress runs when new commits are pushed since only the -# latest integration test results matter for validating CocoaPods compatibility. -# - For main branch pushes, we never cancel integration tests to ensure our CocoaPods -# integration remains functional for all downstream consumers relying on our library. -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_integration_test_for_prs: ${{ steps.changes.outputs.run_integration_test_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - test: - name: CocoaPods Integration - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_integration_test_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - name: Checkout Repository - uses: actions/checkout@v5 - - - name: Select Xcode - run: ./scripts/ci-select-xcode.sh 16.4 - - - name: Setup Ruby - uses: ruby/setup-ruby@32110d4e311bd8996b2a82bf2a43b714ccc91777 # v1.221.0 - with: - bundler-cache: true - - - name: Run Integration Test - run: bundle exec fastlane cocoapods_integration_test - working-directory: Samples/iOS-Cocoapods-Swift6 - - - name: Upload Result Bundle - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: integration-test-iOS-Cocoapods-Swift6.xcresult - path: Samples/iOS-Cocoapods-Swift6/fastlane/test_results/results.xcresult - - - name: Run CI Diagnostics - if: failure() - shell: bash - run: ./scripts/ci-diagnostics.sh - - # This check validates that either all integration tests passed or were skipped, which allows us - # to make integration tests a required check with only running the integration tests when required. - # So, we don't have to run integration tests, for example, for Changelog or ReadMe changes. - integration_test-required-check: - needs: - [ - files-changed, - test, - ] - name: Integration Test - # 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 integration test jobs has failed." && exit 1 diff --git a/.github/workflows/lint-clang-formatting.yml b/.github/workflows/lint-clang-formatting.yml deleted file mode 100644 index 07854da1e67..00000000000 --- a/.github/workflows/lint-clang-formatting.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Lint Clang - -on: - push: - branches: - - main - - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, -# as linting checks are deterministic and don't require parallel validation. -# - For pull requests, we cancel in-progress runs when new commits are pushed since only the -# latest linting matters for merge decisions. -# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent style -# standards across the entire project. -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_lint_clang_formatting_for_prs: ${{ steps.changes.outputs.run_lint_clang_formatting_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - lint: - # While ubuntu runners have clang-format preinstalled, they use an older version. We want to use the most recent one, - # that we can easily install locally via brew. - name: Lint - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_clang_formatting_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - uses: actions/checkout@v5 - - name: Install tooling - run: make init-ci-format - - - name: Format with Clang - run: make format-clang - - - name: Check for Formatting Changes - run: | - if [[ -n "$(git status --porcelain)" ]]; then - echo "❌ Some code formatted with clang-format is not formatted correctly. Please run 'make format' and commit the changes." - git status - git diff - exit 1 - else - echo "✅ All code is formatted correctly." - fi - - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - lint_clang_formatting-required-check: - needs: - [ - files-changed, - lint, - ] - name: Lint Clang - # 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 clang formatting check jobs has failed." && exit 1 diff --git a/.github/workflows/lint-cocoapods-specs.yml b/.github/workflows/lint-cocoapods-specs.yml deleted file mode 100644 index 81fa144d040..00000000000 --- a/.github/workflows/lint-cocoapods-specs.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: Lint CocoaPods Specs - -on: - push: - branches: - - main - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, -# as linting checks are deterministic and don't require parallel validation. -# - For pull requests, we cancel in-progress runs when new commits are pushed since only the -# latest linting matters for merge decisions. -# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent style -# standards across the entire project. -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_lint_cocoapods_specs_for_prs: ${{ steps.changes.outputs.run_lint_cocoapods_specs_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - lint-podspec: - name: ${{ matrix.podspec}} ${{ matrix.library_type }} ${{ matrix.platform}} - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_cocoapods_specs_for_prs == 'true' - needs: files-changed - runs-on: macos-14 - strategy: - fail-fast: false - matrix: - podspec: ["Sentry", "SentrySwiftUI"] - platform: ["ios", "macos", "tvos", "watchos"] - library_type: ["dynamic", "static"] - - steps: - - uses: actions/checkout@v5 - - run: ./scripts/ci-select-xcode.sh 15.4 - # We need to update the spec-repo, because it can happen that it is not up to date and then the lint fails. - - run: pod repo update - - name: Validate Podspec - run: ./scripts/pod-lib-lint.sh ${{ matrix.platform }} ${{ matrix.podspec}} ${{ matrix.library_type}} - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - lint-hybrid-sdk-podspec: - name: Sentry/HybridSDK - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_cocoapods_specs_for_prs == 'true' - needs: files-changed - runs-on: macos-14 - - steps: - - uses: actions/checkout@v5 - - run: ./scripts/ci-select-xcode.sh 15.4 - - run: pod repo update - - name: Validate HybridPod Podspec - run: pod lib lint ./Tests/HybridSDKTest/HybridPod.podspec --allow-warnings --verbose --platforms=ios "--include-podspecs={Sentry.podspec}" - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - lint_cocoapods_Specs-required-check: - needs: - [ - files-changed, - lint-podspec, - lint-hybrid-sdk-podspec, - ] - name: Lint CocoaPods Specs - # 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 CocoaPods specs linting jobs has failed." && exit 1 diff --git a/.github/workflows/lint-dprint-formatting.yml b/.github/workflows/lint-dprint-formatting.yml deleted file mode 100644 index 7242d7acd3c..00000000000 --- a/.github/workflows/lint-dprint-formatting.yml +++ /dev/null @@ -1,66 +0,0 @@ -# We want to run dprint for only the files it checks without running the other linters, which are -# expensive. For example, dprint should run for markdown changes, but pod lib lint doesn't need to -# run for markdown changes. Therefore, we run it in an extra workflow. - -name: Lint dprint - -on: - push: - branches: - - main - - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, -# as linting checks are deterministic and don't require parallel validation. -# - For pull requests, we cancel in-progress runs when new commits are pushed since only the latest -# linting matters for merge decisions. -# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent -# style standards across the entire project. -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_lint_dprint_for_prs: ${{ steps.changes.outputs.run_lint_dprint_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - lint: - name: Lint - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_dprint_for_prs == 'true' - needs: files-changed - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - uses: dprint/check@v2.3 - - lint-dprint-required-check: - needs: - [ - files-changed, - lint, - ] - name: Lint dprint - # 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 lint dprint jobs has failed." && exit 1 diff --git a/.github/workflows/lint-shellcheck-formatting.yml b/.github/workflows/lint-shellcheck-formatting.yml deleted file mode 100644 index 5823276b352..00000000000 --- a/.github/workflows/lint-shellcheck-formatting.yml +++ /dev/null @@ -1,66 +0,0 @@ -# We want only to run the shellcheck when sh files change without running the other linters, which are -# expensive. For example, pod lib lint doesn't need to run for sh changes. Therefore, we run it in an -# extra workflow. - -name: Lint Shellcheck - -on: - push: - branches: - - main - - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, -# as linting checks are deterministic and don't require parallel validation. -# - For pull requests, we cancel in-progress runs when new commits are pushed since only the latest -# linting matters for merge decisions. -# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent -# style standards across the entire project. -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_lint_shellcheck_for_prs: ${{ steps.changes.outputs.run_lint_shellcheck_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - lint: - name: Lint - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_shellcheck_for_prs == 'true' - needs: files-changed - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - run: shellcheck **/*.sh - - lint-shellcheck-required-check: - needs: - [ - files-changed, - lint, - ] - name: Lint Shellcheck - # 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 shellcheck jobs has failed." && exit 1 diff --git a/.github/workflows/lint-swift-formatting.yml b/.github/workflows/lint-swift-formatting.yml deleted file mode 100644 index 0a8f019f5cd..00000000000 --- a/.github/workflows/lint-swift-formatting.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: Lint Swift - -on: - push: - branches: - - main - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, -# as linting checks are deterministic and don't require parallel validation. -# - For pull requests, we cancel in-progress runs when new commits are pushed since only the latest -# linting matters for merge decisions. -# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent -# style standards across the entire project. -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_lint_swift_formatting_for_prs: ${{ steps.changes.outputs.run_lint_swift_formatting_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - lint: - name: Lint - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_swift_formatting_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - uses: actions/checkout@v5 - - - name: Install tooling - run: make init-ci-format - - - name: Run SwiftLint - run: make format-swift-all - - - name: Check for Formatting Changes - run: | - if [[ -n "$(git status --porcelain)" ]]; then - echo "❌ Some Swift code is not formatted correctly. Please run 'make format' and commit the changes." - git status - git diff - exit 1 - else - echo "✅ All code is formatted correctly." - fi - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - lint_swift_formatting-required-check: - needs: - [ - files-changed, - lint, - ] - name: Lint Swift Formatting - # 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 Swift formatting check jobs has failed." && exit 1 diff --git a/.github/workflows/lint-swiftlint-formatting.yml b/.github/workflows/lint-swiftlint-formatting.yml deleted file mode 100644 index 6fd85bc6ba5..00000000000 --- a/.github/workflows/lint-swiftlint-formatting.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: Lint SwiftLint - -on: - push: - branches: - - main - - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, -# as linting checks are deterministic and don't require parallel validation. -# - For pull requests, we cancel in-progress runs when new commits are pushed since only the latest -# linting matters for merge decisions. -# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent -# style standards across the entire project. -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_lint_swiftlint_for_prs: ${{ steps.changes.outputs.run_lint_swiftlint_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - lint: - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_swiftlint_for_prs == 'true' - needs: files-changed - name: Lint - runs-on: macos-14 - steps: - - uses: actions/checkout@v5 - - name: Install tooling - run: make init-ci-format - - run: swiftlint --version - - name: Run SwiftLint - run: swiftlint --strict - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - # This check validates that either lint passed or was skipped, which allows us - # to make lint-swiftlint a required check with only running the lint when required. - # So, we don't have to run lint-swiftlint, for example, for unrelated changes. - lint_swiftlint-required-check: - needs: - [ - files-changed, - lint, - ] - name: Lint SwiftLint - # 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 lint-swiftlint jobs has failed." && exit 1 diff --git a/.github/workflows/lint-xcode-analyze.yml b/.github/workflows/lint-xcode-analyze.yml deleted file mode 100644 index 3339a07b956..00000000000 --- a/.github/workflows/lint-xcode-analyze.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: Lint Xcode - -on: - push: - branches: - - main - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, -# as linting checks are deterministic and don't require parallel validation. -# - For pull requests, we cancel in-progress runs when new commits are pushed since only the latest -# linting matters for merge decisions. -# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent -# style standards across the entire project. -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_lint_xcode_analyze_for_prs: ${{ steps.changes.outputs.run_lint_xcode_analyze_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - lint: - name: Lint - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_xcode_analyze_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - uses: actions/checkout@v5 - - run: ./scripts/ci-select-xcode.sh 16.4 - - run: make analyze - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - lint_xcode_analyze-required-check: - needs: - [ - files-changed, - lint, - ] - name: Lint Xcode - # 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 lint check jobs has failed." && exit 1 diff --git a/.github/workflows/objc-conversion-analysis.yml b/.github/workflows/objc-conversion-analysis.yml deleted file mode 100644 index e9063916f23..00000000000 --- a/.github/workflows/objc-conversion-analysis.yml +++ /dev/null @@ -1,105 +0,0 @@ -name: Objective-C Conversion Analysis - -on: - push: - branches: - - main - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple Objective-C conversion analysis runs, -# as these analyze code conversion progress and generate tracking reports. -# - For pull requests, we cancel in-progress runs when new commits are pushed since only the -# latest conversion analysis matters for tracking progress on SwiftConversion changes. -# - For main branch pushes, we never cancel conversion analysis to ensure we maintain accurate -# tracking of our Objective-C to Swift conversion progress across the entire project. -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_objc_conversion_analysis_for_prs: ${{ steps.changes.outputs.run_objc_conversion_analysis_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - analyze-objc-conversion: - name: Analyze Objective-C to Swift Conversion - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_objc_conversion_analysis_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - timeout-minutes: 10 - - steps: - - name: Checkout code - uses: actions/checkout@v5 - - - name: Setup Ruby - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # pin@v5.4.3 - with: - ruby-version: "3.2" - bundler-cache: true - - - name: Install Graphviz - run: brew install graphviz - - - name: Run Objective-C conversion analyzer - working-directory: SwiftConversion - run: | - ruby objc_conversion_analyzer.rb - - - name: Generate Graphviz DOT file - working-directory: SwiftConversion - run: | - ruby generate_graphviz.rb - - - name: Convert DOT to SVG - working-directory: SwiftConversion - run: | - dot -Tsvg objc_dependencies_topo.dot -o objc_dependencies_topo.svg - - - name: Upload analysis artifacts - uses: actions/upload-artifact@v4 - with: - name: objc-conversion-analysis - path: | - SwiftConversion/objc_conversion_analysis.json - SwiftConversion/objc_dependencies_topo.dot - SwiftConversion/objc_dependencies_topo.svg - retention-days: 30 - - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - # This check validates that either all Objective-C conversion analysis passed or was skipped, which allows us - # to make the analysis a required check with only running the analysis when required. - # So, we don't have to run analysis, for example, for Changelog or ReadMe changes. - - objc_conversion_analysis-required-check: - needs: - [ - files-changed, - analyze-objc-conversion, - ] - name: Objective-C Conversion Analysis - # 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 Objective-C conversion analysis jobs has failed." && exit 1 diff --git a/.github/workflows/release-comment-issues.yml b/.github/workflows/release-comment-issues.yml deleted file mode 100644 index ecf61b50824..00000000000 --- a/.github/workflows/release-comment-issues.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: "Automation: Notify issues for release" -on: - release: - types: - - published - workflow_dispatch: - inputs: - version: - description: Which version to notify issues for - required: false - -# This workflow is triggered when a release is published -jobs: - release-comment-issues: - runs-on: ubuntu-24.04 - name: Notify issues - steps: - - name: Get version - id: get_version - run: echo "version=${VERSION}" >> $GITHUB_OUTPUT - env: - VERSION: ${{ github.event.inputs.version || github.event.release.tag_name }} - - - name: Comment on linked issues that are mentioned in release - if: | - steps.get_version.outputs.version != '' - && !contains(steps.get_version.outputs.version, 'a') - && !contains(steps.get_version.outputs.version, 'b') - && !contains(steps.get_version.outputs.version, 'rc') - uses: getsentry/release-comment-issues-gh-action@v1 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - version: ${{ steps.get_version.outputs.version }} diff --git a/.github/workflows/release-upload-xcframework.yml b/.github/workflows/release-upload-xcframework.yml deleted file mode 100644 index b1549e5ccb0..00000000000 --- a/.github/workflows/release-upload-xcframework.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Upload XCFrameworks -on: - push: - branches: - - release/** - -jobs: - # Craft uses the Git commit hash to query GitHub Actions for artifacts - # uploaded in a workflow run associated with that commit. - # - # To support this, we download the XCFramework already built and uploaded - # in release.yml (triggered via workflow_dispatch), and reupload it here. - # This associates it with the new commit in the release branch, which is - # created by getsentry/action-prepare-release in release.yml. - # - # This is necessary because Swift Package Manager requires a checksum for - # XCFrameworks, creating a chicken-and-egg problem: we need the XCFramework - # to generate the checksum, but we also need the checksum to update Package.swift. - # - # The sequence is: - # 1. Build the XCFrameworks in release.yml. - # 2. getsentry/action-prepare-release updates Package.swift with the checksum. - # 3. Upload the XCFrameworks again here so Craft can find it by commit. - upload-xcframeworks: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - - name: Get Release workflow run ID - run: echo "FRAMEWORK_RUN_ID=$(./scripts/xcframework-generated-run.sh)" >> $GITHUB_ENV - - - uses: actions/download-artifact@v5 - with: - name: xcframeworks.zip - path: Carthage/ - github-token: ${{ secrets.GITHUB_TOKEN }} - run-id: ${{ env.FRAMEWORK_RUN_ID }} - - - name: Archive XCFrameworks for Craft - uses: actions/upload-artifact@v4 - with: - # Craft uses the git commit hash of the release branch to download the release artifacts. - name: ${{ github.sha }} - if-no-files-found: error - overwrite: true - path: | - ${{github.workspace}}/Carthage/*.zip diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index b795e45f97b..00000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,370 +0,0 @@ -name: Release -run-name: Release ${{ github.event.inputs.version || github.sha }} - -on: - push: - branches: - - main - - pull_request: - - workflow_dispatch: - inputs: - version: - description: Version to release - required: true - force: - description: Force a release even when there are release-blockers (optional) - required: false - merge_target: - description: Target branch to merge into. Uses the default branch as a fallback (optional) - required: false - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple release builds from running -# simultaneously, which could lead to race conditions in artifact generation and storage. -# - For pull requests, we cancel in-progress runs when testing release workflow changes since -# only the latest version needs validation before merging. -# - For main branch pushes (actual releases), we never cancel runs to ensure every release -# process completes fully, as partial releases could corrupt our distribution pipeline. -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_release_for_prs: ${{ steps.changes.outputs.run_release_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - setup-matrix: - runs-on: ubuntu-latest - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_release_for_prs == 'true' - needs: files-changed - steps: - - uses: actions/checkout@v5 - - name: Setup matrix combinations - id: setup-matrix-combinations - run: | - ./scripts/generate_release_matrix.sh - env: - EVENT_NAME: ${{ github.event_name }} - outputs: - slices: ${{ steps.setup-matrix-combinations.outputs.slices }} - variants: ${{ steps.setup-matrix-combinations.outputs.variants }} - sdk-list-array: ${{ steps.setup-matrix-combinations.outputs.sdk-list-array }} - sdk-list-string: ${{ steps.setup-matrix-combinations.outputs.sdk-list-string }} - - build-xcframework-variant-slices: - name: Build XCFramework Slices - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_release_for_prs == 'true' - needs: [files-changed, setup-matrix] - uses: ./.github/workflows/build-xcframework-variant-slices.yml - with: - name: ${{matrix.variant.name}} - suffix: ${{matrix.variant.suffix}} - macho-type: ${{matrix.variant.macho-type}} - configuration-suffix: ${{matrix.variant.configuration-suffix}} - variant-id: ${{matrix.variant.id}} - release-version: ${{ github.event.inputs.version }} - sdk-list: ${{ needs.setup-matrix.outputs.sdk-list-array }} - strategy: - matrix: - variant: ${{ fromJson(needs.setup-matrix.outputs.slices) }} - - assemble-xcframework-variant: - needs: [files-changed, build-xcframework-variant-slices, setup-matrix] - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_release_for_prs == 'true' - name: Assemble XCFramework Variant - uses: ./.github/workflows/assemble-xcframework-variant.yml - secrets: inherit - with: - scheme: ${{matrix.variant.scheme}} - suffix: ${{matrix.variant.suffix}} - configuration-suffix: ${{matrix.variant.configuration-suffix}} - variant-id: ${{matrix.variant.id}} - signed: true - release-version: ${{ github.event.inputs.version }} - excluded-archs: ${{matrix.variant.excluded-archs}} - override-name: ${{matrix.variant.override-name}} - sdks: ${{ needs.setup-matrix.outputs.sdk-list-string }} - strategy: - matrix: - variant: ${{ fromJson(needs.setup-matrix.outputs.variants) }} - - validate-xcframework: - name: Validate XCFramework - runs-on: macos-14 - needs: [files-changed, assemble-xcframework-variant] - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_release_for_prs == 'true' - steps: - - uses: actions/checkout@v5 - - uses: actions/download-artifact@v5 - with: - pattern: xcframework-${{github.sha}}-sentry-static - path: Carthage/ - - uses: actions/download-artifact@v5 - with: - pattern: xcframework-${{github.sha}}-sentry-swiftui - path: Carthage/ - - run: ./scripts/ci-select-xcode.sh 15.4 - - run: make build-xcframework-sample - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - # Use github.event.pull_request.head.sha instead of github.sha when available as - # the github.sha is be the pre merge commit id for PRs. - # See https://github.community/t/github-sha-isnt-the-value-expected/17903/17906. - validate-spm: - name: Validate SPM Static - runs-on: macos-14 - needs: [files-changed, assemble-xcframework-variant] - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_release_for_prs == 'true' - steps: - - uses: actions/checkout@v5 - - uses: actions/download-artifact@v5 - with: - pattern: xcframework-${{github.sha}}-* - merge-multiple: true - - name: Prepare Package.swift - uses: ./.github/actions/prepare-package.swift - with: - is-pr: ${{ github.event_name == 'pull_request' }} - - run: swift build - working-directory: Samples/macOS-SPM-CommandLine - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - validate-spm-dynamic: - name: Validate SPM Dynamic - runs-on: macos-14 - needs: [files-changed, assemble-xcframework-variant] - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_release_for_prs == 'true' - steps: - - uses: actions/checkout@v5 - - uses: actions/download-artifact@v5 - with: - pattern: xcframework-${{github.sha}}-* - merge-multiple: true - - name: Prepare Package.swift - uses: ./.github/actions/prepare-package.swift - with: - is-pr: ${{ github.event_name == 'pull_request' }} - - run: swift build - working-directory: Samples/SPM-Dynamic - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - swift-build: - name: Build Swift Static - runs-on: macos-14 - needs: [files-changed, assemble-xcframework-variant] - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_release_for_prs == 'true' - steps: - - uses: actions/checkout@v5 - - uses: actions/download-artifact@v5 - with: - pattern: xcframework-${{github.sha}}-* - merge-multiple: true - - name: Prepare Package.swift - uses: ./.github/actions/prepare-package.swift - with: - is-pr: ${{ github.event_name == 'pull_request' }} - - run: swift build - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - validate-spm-visionos: - name: Validate SPM Static visionOS - runs-on: macos-14 - needs: [files-changed, assemble-xcframework-variant] - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_release_for_prs == 'true' - steps: - - uses: actions/checkout@v5 - - uses: actions/download-artifact@v5 - with: - pattern: xcframework-${{github.sha}}-* - merge-multiple: true - - name: Prepare Package.swift - uses: ./.github/actions/prepare-package.swift - with: - is-pr: ${{ github.event_name == 'pull_request' }} - - run: set -o pipefail &&xcodebuild build -scheme visionOS-SPM -sdk xros -destination 'generic/platform=xros' | tee raw-build-output-spm-visionOS.log | xcbeautify - working-directory: Samples/visionOS-SPM - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - duplication-tests: - name: Test Sentry Duplication V4 # Up the version with every change to keep track of flaky tests - uses: ./.github/workflows/ui-tests-common.yml - needs: [files-changed, assemble-xcframework-variant] - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_release_for_prs == 'true' - secrets: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - with: - fastlane_command: duplication_test - xcode_version: 16.4 - macos_version: macos-15 - needs_xcframework: true - - app-metrics: - name: Collect App Metrics - runs-on: macos-15 - needs: [files-changed, assemble-xcframework-variant] - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_release_for_prs == 'true' - timeout-minutes: 20 - steps: - - name: Git checkout - uses: actions/checkout@v5 - - run: ./scripts/ci-select-xcode.sh 16.4 - - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - uses: actions/cache@v4 - id: app-plain-cache - with: - path: Tests/Perf/test-app-plain.ipa - key: ${{ github.workflow }}-${{ github.job }}-appplain-${{ hashFiles('fastlane/Fastfile', 'Tests/Perf/test-app-plain/**') }} - - name: Build test app plain - if: steps.app-plain-cache.outputs['cache-hit'] != 'true' - run: bundle exec fastlane build_perf_test_app_plain - 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 }} - FASTLANE_KEYCHAIN_PASSWORD: ${{ secrets.FASTLANE_KEYCHAIN_PASSWORD }} - MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - - uses: actions/download-artifact@v5 - with: - pattern: xcframework-${{github.sha}}-sentry-dynamic - path: Carthage/ - - run: find Carthage -name "Sentry-Dynamic.xcframework.zip" -print0 | xargs -t0I @ unzip @ -d Carthage - - name: Build test app with sentry - run: bundle exec fastlane build_perf_test_app_sentry - 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 }} - FASTLANE_KEYCHAIN_PASSWORD: ${{ secrets.FASTLANE_KEYCHAIN_PASSWORD }} - MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - - name: Collect app metrics - uses: getsentry/action-app-sdk-overhead-metrics@5f2d99b8e5a7b833386524924d24320501099a44 - with: - config: Tests/Perf/metrics-test.yml - sauce-user: ${{ secrets.SAUCE_USERNAME }} - sauce-key: ${{ secrets.SAUCE_ACCESS_KEY }} - - name: Debug Xcode environment - if: ${{ failure() || cancelled() }} - run: ./scripts/ci-diagnostics.sh - - job_release: - runs-on: ubuntu-latest - name: "Release New Version" - needs: [ - files-changed, - validate-xcframework, - validate-spm, - validate-spm-dynamic, - swift-build, - duplication-tests, - app-metrics, - ] - if: ${{ github.event_name == 'workflow_dispatch' }} - steps: - - name: Get auth token - id: token - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 - with: - app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }} - private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }} - - name: Check out current commit (${{ github.sha }}) - uses: actions/checkout@v5 - with: - token: ${{ steps.token.outputs.token }} - fetch-depth: 0 - - - uses: actions/download-artifact@v5 - with: - pattern: xcframework-${{github.sha}}-* - merge-multiple: true - path: Carthage/ - - - name: Archive XCFrameworks for Craft - uses: actions/upload-artifact@v4 - with: - name: xcframeworks.zip - if-no-files-found: error - overwrite: true - path: | - ${{github.workspace}}/Carthage/*.zip - - # update-package-sha.sh uses this env variable to update Package.swift. - # During release Craft calls bump.sh that uses update-package-sha.sh. - - run: export GITHUB_RUN_ID="$GITHUB_RUN_ID" - env: - GITHUB_RUN_ID: ${{ github.run_id }} - - - name: Prepare release - uses: getsentry/action-prepare-release@v1 - env: - GITHUB_TOKEN: ${{ steps.token.outputs.token }} - with: - version: ${{ github.event.inputs.version }} - force: ${{ github.event.inputs.force }} - merge_target: ${{ github.event.inputs.merge_target }} - - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - release-required-check: - needs: - [ - files-changed, - build-xcframework-variant-slices, - assemble-xcframework-variant, - validate-xcframework, - validate-spm, - validate-spm-dynamic, - swift-build, - duplication-tests, - app-metrics, - ] - name: Release - # 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 release check jobs has failed." && exit 1 diff --git a/.github/workflows/test-cross-platform.yml b/.github/workflows/test-cross-platform.yml deleted file mode 100644 index 25198b33ff0..00000000000 --- a/.github/workflows/test-cross-platform.yml +++ /dev/null @@ -1,123 +0,0 @@ -name: Test Cross Platform - -on: - push: - branches: - - main - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple cross-platform tests, -# as these involve complex React Native and cross-platform integration setups. -# - For pull requests, we cancel in-progress runs when new commits are pushed since only the -# latest cross-platform compatibility results matter for validating multi-platform support. -# - For main branch pushes, we never cancel cross-platform tests to ensure our SDK remains -# compatible with React Native and other cross-platform frameworks that depend on us. -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_test_cross_platform_for_prs: ${{ steps.changes.outputs.run_test_cross_platform_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - test-react-native: - name: React Native Installation - # Run the job only for PRs with related changes or non-PR events. - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_test_cross_platform_for_prs == 'true' - needs: files-changed - runs-on: macos-14 - # This job can take a while to run, so we set a timeout. - timeout-minutes: 30 - steps: - - uses: actions/checkout@v5 - with: - repository: getsentry/sentry-cocoa - path: sentry-cocoa - - - name: Initialize tools - run: make init-ci-build - working-directory: sentry-cocoa - - - name: Clone Sentry React Native Repository - uses: actions/checkout@v5 - with: - repository: getsentry/sentry-react-native - path: sentry-react-native - ref: itay/frames_tracker_swift - - - name: Enable Corepack - working-directory: sentry-react-native - run: npm i -g corepack - - - uses: actions/setup-node@v6 - with: - node-version: 18 - cache: "yarn" - cache-dependency-path: sentry-react-native/yarn.lock - - run: ./sentry-cocoa/scripts/ci-select-xcode.sh 16.2 - - - name: Install SDK JS Dependencies - working-directory: sentry-react-native - run: yarn install - - - name: Remove Sentry/HybridSDK Dependency from RNSentry.podspec - run: sed -i '' "s/s.dependency 'Sentry\/HybridSDK', '[0-9]*\.[0-9]*\.[0-9]*'/s.dependency 'Sentry\/HybridSDK'/" sentry-react-native/packages/core/RNSentry.podspec - - - name: Add Sentry/HybridSDK Dependency to RNSentryCocoaTester/Podfile - run: sed -i '' -e "s/RNSentry.podspec'/RNSentry.podspec'\\n pod 'Sentry\/HybridSDK', :path => '..\/..\/..\/..\/sentry-cocoa'/" sentry-react-native/packages/core/RNSentryCocoaTester/Podfile - - - name: Disable test parallelization - working-directory: sentry-react-native/packages/core/RNSentryCocoaTester - run: sed -i '' "s/parallelizable = \"YES\"/parallelizable = \"NO\"/" RNSentryCocoaTester.xcodeproj/xcshareddata/xcschemes/RNSentryCocoaTester.xcscheme - - - name: Install App Pods - working-directory: sentry-react-native/packages/core/RNSentryCocoaTester - run: pod install - - - name: Run iOS Tests - working-directory: sentry-react-native/packages/core/RNSentryCocoaTester - env: - SCHEME: RNSentryCocoaTester - CONFIGURATION: Release - DESTINATION: "platform=iOS Simulator,OS=17.5,name=iPhone 15 Pro" - run: | - set -o pipefail - env NSUnbufferedIO=YES \ - xcodebuild -workspace *.xcworkspace \ - -scheme $SCHEME -configuration $CONFIGURATION \ - -destination "$DESTINATION" \ - test SWIFT_ACTIVE_COMPILATION_CONDITIONS=CROSS_PLATFORM_TEST GCC_PREPROCESSOR_DEFINITIONS"=CROSS_PLATFORM_TEST=1" | xcbeautify - - - name: Run CI Diagnostics - if: failure() - run: ./sentry-cocoa/scripts/ci-diagnostics.sh - - test_cross_platform-required-check: - needs: - [ - files-changed, - test-react-native, - ] - name: Test Cross Platform - # 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 cross-platform test jobs has failed." && exit 1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index cc818f7ebdd..00000000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,508 +0,0 @@ -name: Test -on: - push: - branches: - - main - - release/** - - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to allow independent test runs across different workflows -# while preventing multiple runs of the same test suite on the same branch/commit. -# - For pull requests, we cancel in-progress runs when new commits are pushed to save CI resources -# and provide faster feedback on the latest changes. -# - For main branch pushes and scheduled runs, we never cancel in-progress runs to ensure the complete -# test suite always finishes, maintaining the integrity of our main branch quality gates. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -jobs: - # This job detects if the PR contains changes that require running unit tests. - # If yes, the job will output a flag that will be used by the next job to run the unit tests. - # If no, the job will output a flag that will be used by the next job to skip running the unit tests. - # At the end of this workflow, we run a check that validates that either all unit tests passed or were - # called unit-tests-required-check. - files-changed: - name: Detect File Changes - runs-on: ubuntu-latest - # Map a step output to a job output - outputs: - run_unit_tests_for_prs: ${{ steps.changes.outputs.run_unit_tests_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - build-test-server: - name: Build test server - if: needs.files-changed.outputs.run_unit_tests_for_prs == 'true' - needs: files-changed - runs-on: macos-15 - steps: - - uses: actions/checkout@v5 - - name: Cache for Test Server - id: cache_test_server - uses: actions/cache@v4 - with: - path: ./test-server/.build - key: test-server-${{ hashFiles('./test-server') }}-universal - restore-keys: | - test-server-${{ hashFiles('./test-server') }}-universal - test-server- - - - name: Build Test Server for Intel CPU - if: steps.cache_test_server.outputs.cache-hit != 'true' - working-directory: test-server - run: >- - swift build -c release --triple x86_64-apple-macosx 2>&1 | tee test-server-build-intel.log - - - name: Build Test Server for M1 CPU - if: steps.cache_test_server.outputs.cache-hit != 'true' - working-directory: test-server - run: >- - swift build -c release --arch arm64 2>&1 | tee test-server-build-arm64.log - - - name: Combine Test Server - working-directory: test-server - run: >- - lipo -create -output test-server-exec $(swift build --show-bin-path -c release --triple arm64-apple-macosx)/Run $(swift build --show-bin-path -c release --triple x86_64-apple-macosx)/Run - - - name: Archiving DerivedData - uses: actions/upload-artifact@v4 - with: - name: test-server - path: | - ./test-server/test-server-exec - - - name: Archiving Raw Test Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: test-server-build-log - path: | - test-server-build-intel.log - test-server-build-arm64.log - - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - distribution-tests: - name: Distribution Tests - runs-on: macos-15 - needs: files-changed - steps: - - uses: actions/checkout@v5 - - name: Prepare Package.swift - uses: ./.github/actions/prepare-package.swift - with: - is-pr: ${{ github.event_name == 'pull_request' }} - change-path: false - remove-duplicate: true - - run: rm -r Sentry.xcodeproj && rm -r Sentry.xcworkspace - - run: set -o pipefail && NSUnbufferedIO=YES SKIP_BINARIES=1 xcodebuild test -scheme Sentry-Package -sdk iphonesimulator -destination 'platform=iOS Simulator,OS=18.4,name=iPhone 16 Pro' | tee raw-test-output-distribution.log | xcbeautify --preserve-unbeautified - shell: sh - - name: Upload Distribution Test Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-test-output-distribution - path: | - raw-test-output-distribution.log - - # This matrix runs only the unit tests requiring the test server. - # We do this to speed up the other unit test jobs and to avoid running the - # test server with potential side effects in GH actions for all unit tests. - # We don't run this matrix for all different OS versions, because the chances - # of a bug solely on a specific OS version is minimal. - unit-tests-with-test-server: - name: Unit with Test Server ${{matrix.name}} - runs-on: ${{matrix.runs-on}} - timeout-minutes: 20 - needs: build-test-server - - strategy: - fail-fast: false - matrix: - include: - # Running the tests with simulators is incredibly flaky. Our assumption is that simulators might have difficulties - # with communicating with the test server in CI. - # We are going to add these back in https://github.com/getsentry/sentry-cocoa/issues/6361 - - name: macOS 15 - runs-on: macos-15 - platform: "macOS" - xcode: "16.4" - test-destination-os: "15.0" - - steps: - - uses: actions/checkout@v5 - - uses: actions/download-artifact@v5 - with: - name: test-server - - - name: Start Test Server - run: ./scripts/start-test-server.sh - - run: ./scripts/ci-select-xcode.sh ${{matrix.xcode}} - - # Note: We don't install Slather or gather code coverage for this job because it only runs - # the SentryTestServerTests target, which contains minimal tests that don't significantly - # contribute to overall code coverage metrics. The main unit-tests job handles comprehensive - # code coverage reporting. - - # We split building and running tests in two steps so we know how long running the tests takes. - - name: Build tests - id: build_tests - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform ${{matrix.platform}} \ - --os ${{matrix.test-destination-os}} \ - --ref ${{ github.ref_name }} \ - --command build-for-testing \ - --device "${{matrix.device}}" \ - --configuration TestCI \ - --scheme Sentry \ - --test-plan Sentry_TestServer - - - name: Run tests - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform ${{matrix.platform}} \ - --os ${{matrix.test-destination-os}} \ - --ref ${{ github.ref_name }} \ - --command test-without-building \ - --device "${{matrix.device}}" \ - --configuration TestCI \ - --scheme Sentry \ - --test-plan Sentry_TestServer - - - name: Archiving DerivedData Logs - uses: actions/upload-artifact@v4 - if: steps.build_tests.outcome == 'failure' - with: - name: derived-data-test-server-${{matrix.platform}}-xcode-${{matrix.xcode}} - path: | - /Users/runner/Library/Developer/Xcode/DerivedData/**/Logs/** - - - name: Archiving Raw Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-output-test-server-${{matrix.platform}}-xcode-${{matrix.xcode}} - path: | - raw-build-output.log - raw-build-for-testing-output.log - raw-test-output.log - - - name: Archiving Crash Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: crash-logs-test-server-${{matrix.platform}}-xcode-${{matrix.xcode}} - path: | - ~/Library/Logs/DiagnosticReports/** - - - name: Run CI Diagnostics - if: ${{ failure() || cancelled() }} - run: ./scripts/ci-diagnostics.sh - - - name: Store screenshot - uses: ./.github/actions/capture-screenshot - if: ${{ failure() || cancelled() }} - with: - suffix: ${{ matrix.platform }}-xcode-${{ matrix.xcode }} - - unit-tests: - name: Unit ${{matrix.name}} - runs-on: ${{matrix.runs-on}} - timeout-minutes: 20 - needs: files-changed - if: needs.files-changed.outputs.run_unit_tests_for_prs == 'true' - - strategy: - fail-fast: false - matrix: - # Can't run tests on watchOS because XCTest is not available - include: - # We are running tests on iOS 17 and later, as there were OS-internal changes introduced in succeeding versions. - - # iOS 16 - - name: iOS 16 Sentry - runs-on: macos-13 - platform: "iOS" - xcode: "14.3.1" - test-destination-os: "16.4" - device: "iPhone 14 Pro" - scheme: "Sentry" - - # iOS 17 - - name: iOS 17 Sentry - runs-on: macos-14 - platform: "iOS" - xcode: "15.4" - test-destination-os: "17.5" - device: "iPhone 15 Pro" - scheme: "Sentry" - - # iOS 18 - - name: iOS 18 Sentry - runs-on: macos-15 - platform: "iOS" - xcode: "16.4" - test-destination-os: "18.4" - device: "iPhone 16 Pro" - scheme: "Sentry" - - # iOS 26 with Xcode 26 - - name: iOS 26 Sentry - runs-on: macos-26 - platform: "iOS" - xcode: "26.1" - test-destination-os: "26.1" - device: "iPhone 17 Pro" - scheme: "Sentry" - - # We don't run the unit tests on macOS 13 cause we run them on all on GH actions available iOS versions. - # The chance of missing a bug solely on tvOS 16 that doesn't occur on iOS, macOS 12 or macOS 14 is minimal. - # We are running tests on macOS 14 and later, as there were OS-internal changes introduced in succeeding versions. - - # macOS 14 - - name: macOS 14 Sentry - runs-on: macos-14 - platform: "macOS" - xcode: "15.4" - test-destination-os: "latest" - scheme: "Sentry" - - # macOS 15 - - name: macOS 15 Sentry - runs-on: macos-15 - platform: "macOS" - xcode: "16.4" - test-destination-os: "latest" - scheme: "Sentry" - - # macOS 26 - - name: macOS 26 Sentry - runs-on: macos-26 - platform: "macOS" - xcode: "26.1" - test-destination-os: "26.1" - scheme: "Sentry" - - # Catalyst. We test the latest version, as the risk something breaking on Catalyst and not - # on an older iOS or macOS version is low. - # In addition we are running tests on macOS 14, as there were OS-internal changes introduced in succeeding versions. - - name: Catalyst 14 Sentry - runs-on: macos-14 - platform: "Catalyst" - xcode: "15.4" - test-destination-os: "latest" - scheme: "Sentry" - - - name: Catalyst 15 Sentry - runs-on: macos-15 - platform: "Catalyst" - xcode: "16.4" - test-destination-os: "latest" - scheme: "Sentry" - - ## We don't run unit tests on macCatalyst 26 yet because of https://github.com/getsentry/sentry-cocoa/issues/6165. - - # We don't run the unit tests on tvOS 16 cause we run them on all on GH actions available iOS versions. - # The chance of missing a bug solely on tvOS 16 that doesn't occur on iOS, tvOS 15 or tvOS 16 is minimal. - # We are running tests on tvOS 17 and latest, as there were OS-internal changes introduced in succeeding versions. - - # tvOS 17 - - name: tvOS 17 Sentry - runs-on: macos-14 - platform: "tvOS" - xcode: "15.4" - test-destination-os: "17.5" - scheme: "Sentry" - - # iOS 17 - - name: iOS 17 SentrySwiftUI - runs-on: macos-14 - platform: "iOS" - xcode: "15.4" - test-destination-os: "17.5" - device: "iPhone 15 Pro" - scheme: "SentrySwiftUI" - - # tvOS 18 - - name: tvOS 18 Sentry - runs-on: macos-15 - platform: "tvOS" - xcode: "16.4" - test-destination-os: "18.4" - scheme: "Sentry" - - # tvOS 26 - - name: tvOS 26 Sentry - runs-on: macos-26 - platform: "tvOS" - xcode: "26.1" - test-destination-os: "26.1" - device: "Apple TV" - scheme: "Sentry" - - steps: - - uses: actions/checkout@v5 - - run: ./scripts/ci-select-xcode.sh ${{matrix.xcode}} - - - name: Install Slather - run: gem install slather - - # Based on a comment in CircleCI forum, we need to boot the simulator for Xcode 26: https://discuss.circleci.com/t/xcode-26-rc/54066/18 - - name: Boot simulator - if: ${{matrix.platform == 'iOS' && matrix.test-destination-os == '26.1'}} - run: ./scripts/ci-boot-simulator.sh --xcode ${{matrix.xcode}} - - # We split building and running tests in two steps so we know how long running the tests takes. - - name: Build tests - id: build_tests - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform ${{matrix.platform}} \ - --os ${{matrix.test-destination-os}} \ - --ref ${{ github.ref_name }} \ - --command build-for-testing \ - --device "${{matrix.device}}" \ - --configuration TestCI \ - --scheme ${{matrix.scheme}} - - - name: Run tests - # We call a script with the platform so the destination - # passed to xcodebuild doesn't end up in the job name, - # because GitHub Actions don't provide an easy way of - # manipulating string in expressions. - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform ${{matrix.platform}} \ - --os ${{matrix.test-destination-os}} \ - --ref ${{ github.ref_name }} \ - --command test-without-building \ - --device "${{matrix.device}}" \ - --configuration TestCI \ - --scheme ${{matrix.scheme}} - - - name: Publish Test Report - uses: mikepenz/action-junit-report@3585e9575db828022551b4231f165eb59a0e74e3 # v5.6.2 - if: always() - with: - report_paths: "build/reports/junit.xml" - fail_on_failure: true - fail_on_parse_error: true - detailed_summary: true - - - name: Archiving DerivedData Logs - uses: actions/upload-artifact@v4 - if: steps.build_tests.outcome == 'failure' - with: - name: derived-data-${{matrix.platform}}-xcode-${{matrix.xcode}}-os-${{matrix.test-destination-os}} - path: | - /Users/runner/Library/Developer/Xcode/DerivedData/**/Logs/** - - - name: Archiving Raw Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-output-${{matrix.platform}}-xcode-${{matrix.xcode}}-os-${{matrix.test-destination-os}} - path: | - raw-build-output.log - raw-build-for-testing-output.log - raw-test-output.log - - - name: Archiving Crash Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: crash-logs-${{matrix.platform}}-xcode-${{matrix.xcode}}-os-${{matrix.test-destination-os}} - path: | - ~/Library/Logs/DiagnosticReports/** - - - name: Archiving Test Results - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: result-bundle-${{matrix.platform}}-xcode-${{matrix.xcode}}-os-${{matrix.test-destination-os}} - path: | - results.xcresult - - - name: Gather code coverage information via slather - run: slather coverage --configuration TestCI --scheme Sentry - - # We can upload all coverage reports, because codecov merges them. - # See https://docs.codecov.io/docs/merging-reports - # Checkout .codecov.yml to see the config of Codecov - # We don't upload codecov for release branches, as we don't want a failing coverage check to block a release. - # We don't upload codecov for scheduled runs as CodeCov only accepts a limited amount of uploads per commit. - - name: Push code coverage to codecov - id: codecov_1 - uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # pin@v5.5.1 - if: ${{ contains(matrix.platform, 'iOS') && !contains(github.ref, 'release') && github.event.schedule == '' }} - with: - # Although public repos should not have to specify a token there seems to be a bug with the Codecov GH action, which can - # be solved by specifying the token, see https://github.com/codecov/codecov-action/issues/557#issuecomment-1224970469 - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: false - verbose: true - - # Sometimes codecov uploads etc can fail. Retry one time to rule out e.g. intermittent network failures. - - name: Push code coverage to codecov - id: codecov_2 - uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # pin@v5.5.1 - if: ${{ steps.codecov_1.outcome == 'failure' && contains(matrix.platform, 'iOS') && !contains(github.ref, 'release') && github.event.schedule == '' }} - with: - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: true - verbose: true - - - name: Codecov test analytics - if: ${{ !cancelled() && !contains(github.ref, 'release') && github.event.schedule == '' }} - uses: codecov/test-results-action@47f89e9acb64b76debcd5ea40642d25a4adced9f # pin@v1.1.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - verbose: true - name: sentry-cocoa-unit-tests - flags: unittests-${{ matrix.platform }}-${{ matrix.xcode }}-${{ matrix.test-destination-os }}, unittests - - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - - name: Store screenshot - uses: ./.github/actions/capture-screenshot - if: failure() - with: - suffix: unit-tests-${{ matrix.platform }}-xcode-${{ matrix.xcode }}-os-${{ matrix.test-destination-os }} - - # This check validates that either all unit tests passed or were skipped, which allows us - # to make unit tests a required check with only running the unit tests when required. - # So, we don't have to run unit tests, for example, for Changelog or ReadMe changes. - - unit-tests-required-check: - needs: - [ - files-changed, - build-test-server, - distribution-tests, - unit-tests, - unit-tests-with-test-server, - ] - name: Unit Tests - # 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 unit test jobs has failed." && exit 1 diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml deleted file mode 100644 index 985201e0164..00000000000 --- a/.github/workflows/testflight.yml +++ /dev/null @@ -1,109 +0,0 @@ -name: Upload to Testflight -on: - push: - branches: - - main - - release/** - - 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_changes: ${{ github.event_name == 'pull_request' && steps.changes.outputs.run_testflight_for_prs || steps.changes.outputs.run_testflight_for_pushes }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - upload_to_testflight: - if: needs.files-changed.outputs.run_testflight_for_changes == 'true' - needs: files-changed - name: Build and Upload iOS-Swift to Testflight - runs-on: macos-15 - steps: - - uses: actions/checkout@v5 - - run: ./scripts/ci-select-xcode.sh 16.4 - - uses: ruby/setup-ruby@v1 - with: - bundler-cache: 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: Run Fastlane - 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 }} - FASTLANE_BUNDLE_VERSION: ${{ github.run_number }} - FASTLANE_KEYCHAIN_PASSWORD: ${{ secrets.FASTLANE_KEYCHAIN_PASSWORD }} - MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - run: | - bundle exec fastlane build_ios_swift - bundle exec fastlane ios_swift_to_testflight - - - name: Archiving - uses: actions/upload-artifact@v4 - with: - name: dSYMs - path: | - ${{ github.workspace }}/iOS-Swift.* - ${{ github.workspace }}/*.dSYM.zip - ${{ github.workspace }}/dSYMs/ - - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - # 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, - ] - 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 diff --git a/.github/workflows/ui-tests-common.yml b/.github/workflows/ui-tests-common.yml deleted file mode 100644 index 52edc382841..00000000000 --- a/.github/workflows/ui-tests-common.yml +++ /dev/null @@ -1,179 +0,0 @@ -name: UI Tests Common - -on: - workflow_call: - inputs: - fastlane_command: - description: "The fastlane command to run" - required: true - type: string - files_suffix: - description: "Suffix for the files to upload" - required: false - default: "" - type: string - xcode_version: - description: "Xcode version" - required: true - type: string - build_with_make: - description: "Build with make" - required: false - default: false - type: boolean - macos_version: - description: "macOS version" - required: true - type: string - needs_xcframework: - description: "Whether the workflow needs to download the XCFramework." - required: false - default: false - type: boolean - codecov_test_analytics: - description: "Whether or not to push results to Codecov for analytics." - required: false - default: false - type: boolean - test-destination-os: - description: "Test destination OS" - required: false - default: "" - type: string - device: - description: "Device" - required: false - default: "" - type: string - platform: - description: "Additional platform to install" - required: false - default: "" - type: string - secrets: - CODECOV_TOKEN: - required: true - -jobs: - common-ui-tests: - name: UI Tests Common - runs-on: ${{ inputs.macos_version }} - timeout-minutes: 40 - steps: - - uses: actions/checkout@v5 - - - name: Setup Ruby - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0 - with: - bundler-cache: true - - - name: Install old xcodegen - if: ${{ inputs.xcode_version == '14.3.1' || inputs.xcode_version == '15.4' }} - # Install xcodegen 2.43.0 for since newer versions don't work with Xcode older than Xcode 16 - # We need to set HOMEBREW_DEVELOPER=1 to allow installing from a local formula - run: | - HOMEBREW_DEVELOPER=1 brew install --formula ./scripts/xcodegen.rb - brew pin xcodegen - - - name: Select Xcode version - run: ./scripts/ci-select-xcode.sh "$XCODE_VERSION" - env: - XCODE_VERSION: ${{ inputs.xcode_version }} - - name: Install required platforms for Xcode 26 - if: ${{ inputs.xcode_version == '26.1' }} - env: - PLATFORM: ${{ inputs.platform }} - run: ./scripts/ci-install-xOS-26-platforms.sh --platforms "$PLATFORM" - - - name: Create simulator device for Xcode 26 - if: ${{ inputs.xcode_version == '26.1' }} - env: - PLATFORM: ${{ inputs.platform }} - OS_VERSION: ${{ inputs.test-destination-os }} - DEVICE_NAME: ${{ inputs.device }} - run: ./scripts/ci-create-simulator.sh --platform "$PLATFORM" --os-version "$OS_VERSION" --device-name "$DEVICE_NAME" - - run: make init-ci-build - if: ${{ inputs.build_with_make }} - - - run: make xcode-ci - if: ${{ inputs.build_with_make }} - - - name: Add Microphone permissions - uses: ./.github/actions/add-microphone-permissions - - - name: Download XCFramework - if: ${{ inputs.needs_xcframework }} - uses: actions/download-artifact@v5 - with: - name: xcframework-${{github.sha}}-sentry-static - path: Carthage/ - - - name: Unzip XCFramework - if: ${{ inputs.needs_xcframework }} - run: | - unzip -o Carthage/Sentry.xcframework.zip -d Carthage/ - - - name: Run Fastlane - env: - FASTLANE_COMMAND: ${{ inputs.fastlane_command }} - DEVICE: ${{ inputs.device }} - TEST_DESTINATION_OS: ${{ inputs.test-destination-os }} - run: | - if [ -n "$DEVICE" ] && [ -n "$TEST_DESTINATION_OS" ]; then - bundle exec fastlane "$FASTLANE_COMMAND" device:"$DEVICE ($TEST_DESTINATION_OS)" - else - bundle exec fastlane "$FASTLANE_COMMAND" - fi - - - name: Publish Test Report - uses: mikepenz/action-junit-report@3585e9575db828022551b4231f165eb59a0e74e3 # v5.6.2 - if: always() - with: - report_paths: build/reports/*junit.xml - fail_on_failure: true - fail_on_parse_error: true - detailed_summary: true - - - name: Codecov test analytics - if: ${{ !cancelled() && inputs.codecov_test_analytics }} - uses: codecov/test-results-action@47f89e9acb64b76debcd5ea40642d25a4adced9f # pin@v1.1.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - verbose: true - name: sentry-cocoa-unit-tests - flags: ui-tests-${{ inputs.fastlane_command }}-${{ inputs.xcode_version }}, ui-tests - - - name: Upload Result Bundle - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: ${{ inputs.fastlane_command }}${{ inputs.files_suffix }} - path: | - fastlane/test_results/**/*.xcresult - - - name: Upload iOS Simulator Crash Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: ${{ inputs.fastlane_command }}${{ inputs.files_suffix }}_crash_logs - path: | - ~/Library/Logs/DiagnosticReports/** - - - name: Archiving Raw Test Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: ${{ inputs.fastlane_command }}${{ inputs.files_suffix }}_raw_output - path: | - ~/Library/Logs/scan/*.log - ./fastlane/test_output/** - - - name: Store screenshot - uses: ./.github/actions/capture-screenshot - if: failure() - with: - suffix: ${{ inputs.fastlane_command }}${{ inputs.files_suffix }} - - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh diff --git a/.github/workflows/ui-tests-critical.yml b/.github/workflows/ui-tests-critical.yml deleted file mode 100644 index fc6255ccc9d..00000000000 --- a/.github/workflows/ui-tests-critical.yml +++ /dev/null @@ -1,153 +0,0 @@ -name: Test UI Critical -on: - push: - branches: - - main - - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple critical UI test runs, -# as these test the most essential user interface functionality and are resource-intensive. -# - For pull requests, we cancel in-progress runs when new commits are pushed to provide -# faster feedback on critical functionality and avoid wasting expensive testing resources. -# - For main branch pushes, we never cancel critical UI tests to ensure the most important -# user interface features are always validated before code reaches production. -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_ui_tests_critical_for_prs: ${{ steps.changes.outputs.run_ui_tests_critical_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - run-tests: - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_ui_tests_critical_for_prs == 'true' - needs: files-changed - name: Test ${{matrix.name}} V4 # Up the version with every change to keep track of flaky tests - uses: ./.github/workflows/ui-tests-common.yml - with: - fastlane_command: ui_critical_tests_ios_swiftui_envelope - build_with_make: true - xcode_version: ${{matrix.platform.xcode}} - macos_version: ${{matrix.platform.runs-on}} - files_suffix: _${{matrix.platform.xcode}} - platform: ${{matrix.platform.platform}} - device: ${{matrix.platform.device}} - test-destination-os: ${{matrix.platform.test-destination-os}} - strategy: - fail-fast: false - matrix: - include: - # As of 25th March 2025, the preinstalled iOS simulator version is 16.4 for macOS 13 and Xcode 14.3.1; see - # https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#installed-sdks - - name: iOS 16 - platform: - runs-on: macos-13 - xcode: "14.3.1" - platform: "iOS" - device: "iPhone 14 Pro" - test-destination-os: "16.4" - - # macos-14 iOS 17 not included due to the XCUIServerNotFound errors causing flaky tests - - # As of 14th August 2025, the preinstalled iOS simulator version is 18.4 for macOS 15 and Xcode 16.4; see - # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md#installed-sdks - - name: iOS 18 - platform: - runs-on: macos-15 - xcode: "16.4" - platform: "iOS" - device: "iPhone 16 Pro" - test-destination-os: "18.4" - - - name: iOS 26 - platform: - runs-on: macos-15 - xcode: "26.1" - platform: "iOS" - device: "iPhone 17 Pro" - test-destination-os: "26.1" - - secrets: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - run-swiftui-crash-test: - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_ui_tests_critical_for_prs == 'true' - needs: files-changed - name: Run SwiftUI Crash Test - runs-on: macos-15 - timeout-minutes: 15 - steps: - - uses: actions/checkout@v5 - - - run: ./scripts/ci-select-xcode.sh 16.4 - - - run: make init-ci-build - - run: make xcode-ci - - - name: Enable screenshots permissions - shell: bash - run: ./scripts/ci-enable-permissions.sh - - - name: Boot simulator - run: ./scripts/ci-boot-simulator.sh - - - name: Run SwiftUI Crash Test - run: | - ./TestSamples/SwiftUICrashTest/test-crash-and-relaunch.sh --screenshots-dir "swiftui-crash-test-screenshots" - - - name: Upload SwiftUI Crash Test Screenshots - uses: actions/upload-artifact@v4 - if: always() - with: - name: swiftui-crash-test-screenshots - path: swiftui-crash-test-screenshots - - - name: Collect Logs - if: always() - run: xcrun simctl spawn booted log collect --output $(pwd)/swiftui-crash-test-log.logarchive - - - name: Upload Logs - uses: actions/upload-artifact@v4 - if: always() - with: - name: swiftui-crash-test-log.logarchive - path: swiftui-crash-test-log.logarchive - - - name: Run CI Diagnostics - if: failure() - run: ./scripts/ci-diagnostics.sh - - # This check validates that either all UI tests critical passed or were skipped, which allows us - # to make UI tests critical a required check with only running the UI tests critical when required. - # So, we don't have to run UI tests critical, for example, for unrelated changes. - ui_tests_critical-required-check: - needs: - [ - files-changed, - run-tests, - run-swiftui-crash-test, - ] - name: UI Tests Critical - # 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 UI tests critical jobs has failed." && exit 1 diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml deleted file mode 100644 index c764b88bab5..00000000000 --- a/.github/workflows/ui-tests.yml +++ /dev/null @@ -1,154 +0,0 @@ -name: UI Tests -on: - push: - branches: - - main - - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple UI test runs on the same code, -# as UI tests are resource-intensive and long-running operations. -# - For pull requests, we cancel in-progress runs when new commits are pushed to provide faster -# feedback and avoid wasting expensive UI testing resources on outdated code. -# - For main branch pushes, we never cancel UI tests to ensure complete validation of the user -# interface before the code reaches production, maintaining our quality standards. -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_ui_tests_for_prs: ${{ steps.changes.outputs.run_ui_tests_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - ui-tests: - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_ui_tests_for_prs == 'true' - needs: files-changed - name: Test ${{matrix.name}} V3 # Up the version with every change to keep track of flaky tests - uses: ./.github/workflows/ui-tests-common.yml - strategy: - matrix: - include: - - name: iOS Objective-C - target: ios_objc - - name: tvOS Swift - target: tvos_swift - with: - fastlane_command: ui_tests_${{matrix.target}} - xcode_version: 16.2 - build_with_make: true - macos_version: macos-14 - codecov_test_analytics: true - secrets: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - # SwiftUI only supports iOS 14+ so we run it in a separate matrix here - ui-tests-swift-ui: - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_ui_tests_for_prs == 'true' - needs: files-changed - name: Test SwiftUI V4 # Up the version with every change to keep track of flaky tests - uses: ./.github/workflows/ui-tests-common.yml - with: - fastlane_command: ui_tests_ios_swiftui - xcode_version: 16.4 - build_with_make: true - macos_version: macos-15 - codecov_test_analytics: true - device: iPhone 16 Pro - test-destination-os: "18.4" - secrets: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - ui-tests-swift: - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_ui_tests_for_prs == 'true' - needs: files-changed - name: Test Swift ${{matrix.name}} V5 # Up the version with every change to keep track of flaky tests - uses: ./.github/workflows/ui-tests-common.yml - strategy: - fail-fast: false - matrix: - include: - - name: iOS 16 - runs-on: macos-13 - xcode: "14.3.1" - device: iPhone 14 Pro - test-destination-os: "16.4" - - name: iOS 17 - runs-on: macos-14 - xcode: "15.4" - device: iPhone 15 Pro - test-destination-os: "17.5" - - name: iOS 18 - runs-on: macos-15 - xcode: "16.4" - device: iPhone 16 Pro - test-destination-os: "18.4" - - name: iOS 26 - runs-on: macos-15 - platform: "iOS" - xcode: "26.1" - device: iPhone 17 Pro - test-destination-os: "26.1" - with: - fastlane_command: ui_tests_ios_swift - files_suffix: _xcode_${{matrix.xcode}}-${{matrix.device}} - xcode_version: ${{matrix.xcode}} - build_with_make: true - macos_version: ${{matrix.runs-on}} - platform: ${{matrix.platform}} - test-destination-os: ${{matrix.test-destination-os}} - device: ${{matrix.device}} - codecov_test_analytics: true - secrets: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - ui-tests-swift6: - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_ui_tests_for_prs == 'true' - needs: files-changed - name: Test iOS Swift6 V3 # Up the version with every change to keep track of flaky tests - uses: ./.github/workflows/ui-tests-common.yml - with: - fastlane_command: ui_tests_ios_swift6 - xcode_version: 16.4 - build_with_make: true - macos_version: macos-15 - codecov_test_analytics: true - device: iPhone 16 Pro - test-destination-os: "18.4" - secrets: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - # This check validates that either UI tests passed or were skipped, which allows us - # to make UI tests a required check with only running the UI tests when required. - # So, we don't have to run UI tests, for example, for unrelated changes. - ui_tests-required-check: - needs: - [ - files-changed, - ui-tests, - ui-tests-swift-ui, - ui-tests-swift, - ui-tests-swift6, - ] - name: UI Tests - # 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 UI test jobs has failed." && exit 1 diff --git a/.github/workflows/version-bump-util.yml b/.github/workflows/version-bump-util.yml deleted file mode 100644 index 923da2232e4..00000000000 --- a/.github/workflows/version-bump-util.yml +++ /dev/null @@ -1,124 +0,0 @@ -name: Test Version Bump Util - -on: - push: - branches: - - main - - pull_request: - -# Concurrency configuration: -# - We use workflow-specific concurrency groups to prevent multiple version bump utility tests, -# as these test critical release infrastructure and version management tools. -# - For pull requests, we cancel in-progress runs when new commits are pushed since only the -# latest version utility behavior matters for validating release process changes. -# - For main branch pushes, we never cancel version utility tests to ensure our release -# infrastructure remains reliable and our version bumping tools work correctly. -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_version_bump_util_for_prs: ${{ steps.changes.outputs.run_version_bump_util_for_prs }} - steps: - - uses: actions/checkout@v5 - - name: Get changed files - id: changes - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - with: - token: ${{ github.token }} - filters: .github/file-filters.yml - - run-version-bump: - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_version_bump_util_for_prs == 'true' - needs: files-changed - # The release workflow uses the Makefile to bump the version so it needs to be tested. - name: Run Version Bump (Makefile) - # We intentionally run this on ubuntu because the release workflow also runs on ubuntu, which uses the version bump util. - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - name: Generate Version Number - id: generate-version-number - run: | - TIMESTAMP=$(date +%Y%m%d%H%M%S) - echo "VERSION=100.0.$TIMESTAMP" >> $GITHUB_OUTPUT - # We don't care which version we bump to, as long as it's a valid semver - - run: make bump-version TO=${{ steps.generate-version-number.outputs.VERSION }} - - run: make verify-version TO=${{ steps.generate-version-number.outputs.VERSION }} - - run-version-bump-script: - if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_version_bump_util_for_prs == 'true' - needs: files-changed - # Craft uses the shell script to bump the version so it needs to be tested. - name: Run Version Bump (Shell Script) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - name: Generate Version Number - id: generate-version-number - run: | - OLD_VERSION=$(cat ./Sources/Configuration/Versioning.xcconfig | grep MARKETING_VERSION | cut -d '=' -f 2 | tr -d ' ') - echo "Read old version: ${OLD_VERSION}" - echo "OLD_VERSION=${OLD_VERSION}" >> $GITHUB_OUTPUT - - NEW_VERSION="100.0.$(date +%Y%m%d%H%M%S)" - echo "Generated new version: ${NEW_VERSION}" - echo "NEW_VERSION=${NEW_VERSION}" >> $GITHUB_OUTPUT - - - name: Verify OLD_VERSION is defined - if: ${{ steps.generate-version-number.outputs.OLD_VERSION == '' }} - run: | - echo "OLD_VERSION is not defined. Make sure this script is reading the version from the correct file." - exit 1 - - - name: Create fake xcframework for update-package-sha.sh - run: | - mkdir -p Carthage - echo "" > Carthage/Sentry.xcframework.zip - echo "" > Carthage/Sentry-Dynamic.xcframework.zip - echo "" > Carthage/Sentry-Dynamic-WithARM64e.xcframework.zip - echo "" > Carthage/Sentry-WithoutUIKitOrAppKit.xcframework.zip - echo "" > Carthage/Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework.zip - - - name: Bump version - run: ./scripts/bump.sh ${{ steps.generate-version-number.outputs.OLD_VERSION }} ${{ steps.generate-version-number.outputs.NEW_VERSION }} - - - name: Verify outputs of bump.sh - run: make verify-version TO=${{ steps.generate-version-number.outputs.NEW_VERSION }} - - - name: Verify outputs of update-package-sha.sh - run: | - ./scripts/verify-package-sha.sh \ - --static-checksum "7062a80f8a80f8b6d812698af87384751567a6aaa0df6f03b0596d728b22dcfd" \ - --dynamic-checksum "f6325cd8f05523d60222451fa61b3cd3d58148e5a21236f82abfd3f92750c87c" \ - --dynamic-with-arm64e-checksum "bbb84b054e5792aa705b95541aa4585f793e566a6b95638f8fef8e308d9782c3" \ - --without-uikit-or-appkit-checksum "c647afe93889063325b5dfcabf43101749f6a8f37008cca858833ed280d2a84e" \ - --without-uikit-or-appkit-with-arm64e-checksum "af5af7edc8e107fe04b905bd23524fdc93914fce8e1bd72ccf281408efff9a47" \ - --last-release-runid "${{ github.run_id }}" - - # This check validates that either version-bump-util passed or was skipped, which allows us - # to make version-bump-util a required check with only running the version-bump-util when required. - # So, we don't have to run version-bump-util, for example, for unrelated changes. - version_bump_util-required-check: - needs: - [ - files-changed, - run-version-bump, - run-version-bump-script, - ] - name: Test Version Bump Util - # 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 version-bump-util jobs has failed." && exit 1 From ade99266a186c1313c52132d74b8d506103cb596 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Wed, 22 Oct 2025 10:48:29 -0300 Subject: [PATCH 2/2] Test other runners --- .github/workflows/cirrus-labs.yml | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cirrus-labs.yml b/.github/workflows/cirrus-labs.yml index 1d950414932..b7f80eecbd5 100644 --- a/.github/workflows/cirrus-labs.yml +++ b/.github/workflows/cirrus-labs.yml @@ -3,9 +3,23 @@ on: pull_request: jobs: - macos: - name: "Test Cirrus Labs" - runs-on: ghcr.io/cirruslabs/macos-runner:ventura + # macos-ventura: + # name: "Test Cirrus Labs on macOS Ventura" + # runs-on: ghcr.io/cirruslabs/macos-runner:ventura + # steps: + # - uses: actions/checkout@v4 + # - name: List Installed Xcodes + # run: xcodes installed + macos-sonoma: + name: "Test Cirrus Labs on macOS Sonoma" + runs-on: ghcr.io/cirruslabs/macos-runner:sonoma + steps: + - uses: actions/checkout@v4 + - name: List Installed Xcodes + run: xcodes installed + macos-tahoe: + name: "Test Cirrus Labs on macOS Tahoe" + runs-on: ghcr.io/cirruslabs/macos-runner:tahoe steps: - uses: actions/checkout@v4 - name: List Installed Xcodes