diff --git a/.github/workflows/benchmarking.yml b/.github/workflows/benchmarking.yml deleted file mode 100644 index 5b40200c254..00000000000 --- a/.github/workflows/benchmarking.yml +++ /dev/null @@ -1,217 +0,0 @@ -name: Benchmarking -on: - push: - branches: - - main - - pull_request: - paths: - # test changes to Sentry SDK sources - - "Sources/**" - - # test changes to benchmarking implementation - - "Samples/iOS-Swift/**" - - "Samples/iOS-Swift/PerformanceBenchmarks/**" - - ".github/workflows/benchmarking.yml" - - ".sauce/benchmarking-config.yml" - - "fastlane/**" - - "scripts/ci-select-xcode.sh" - - "scripts/build-xcframework.sh" - -# 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: - build-benchmark-test-target: - name: Build app and test runner - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 15.2 - - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - 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/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/PerformanceBenchmarks-Runner.app - key: ios-swift-for-ui-testing-cache-key-${{ hashFiles('Samples/iOS-Swift/PerformanceBenchmarks/**') }} - - 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/PerformanceBenchmarks-Runner.app - - run-ui-tests-with-sauce: - name: Run benchmarks on Sauce Labs - runs-on: ubuntu-latest - needs: build-benchmark-test-target - strategy: - fail-fast: false - matrix: - suite: ["High-end device", "Mid-range device", "Low-end device"] - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: DerivedData-Xcode - - run: npm install -g saucectl@0.186.0 - - name: Run Benchmarks in SauceLab - id: run-benchmarks-in-sauce-lab - continue-on-error: true - env: - SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - 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 - if: ${{ steps.run-benchmarks-in-sauce-lab.outcome == 'failure' }} - uses: actions/github-script@v7 - env: - SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - with: - 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 - if: ${{ 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 - - app-metrics: - name: Collect app metrics - runs-on: macos-13-xlarge - steps: - - name: Git checkout - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 15.2 - - 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 }} - - name: Build Framework - run: ./scripts/build-xcframework.sh iOSOnly - - - name: Archive build log if failed - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-build-output-build-xcframework - path: | - build-xcframework.log - - - 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@v1 - with: - config: Tests/Perf/metrics-test.yml - sauce-user: ${{ secrets.SAUCE_USERNAME }} - sauce-key: ${{ secrets.SAUCE_ACCESS_KEY }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index dc0b9ef7356..00000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,307 +0,0 @@ -name: Build -on: - push: - branches: - - main - - release/** - - pull_request: - paths: - - "Sources/**" - - "test-server/**" - - "Samples/**" - - ".github/workflows/build.yml" - - "fastlane/**" - - "scripts/ci-select-xcode.sh" - - Sentry.xcworkspace/** - - Sentry.xcodeproj/** - - Gemfile.lock - - "Package.swift" - - "scripts/build-xcframework.sh" - -# 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: - # 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 - runs-on: macos-14 - steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 16.2 - - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - 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 - shell: sh - - build-sample: - name: Sample ${{ matrix.scheme }} - runs-on: ${{ matrix.runs-on }} - strategy: - fail-fast: false - matrix: - # other sample projects are built in ui-tests - include: - - scheme: macOS-Swift - xcode: 15.4 - runs-on: macos-14 - - scheme: iOS13-Swift - xcode: 15.4 - runs-on: macos-14 - - scheme: watchOS-Swift WatchKit App - xcode: 15.4 - runs-on: macos-14 - # Only compiles on Xcode 16+ - - scheme: macOS-SwiftUI - xcode: 16.2 - runs-on: macos-15 - - - scheme: SessionReplay-CameraTest - xcode: 16.2 - runs-on: macos-15 - - # We have to compile on Xcode 16.3 because compiling on Xcode 16.2 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 - - scheme: visionOS-Swift - xcode: 16.3 - runs-on: macos-15 - - steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh ${{ matrix.xcode }} - - - name: List Xcode Build Schemes - run: >- - xcodebuild - -workspace Sentry.xcworkspace - -list - - # 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: >- - env NSUnbufferedIO=YES - xcodebuild - -workspace Sentry.xcworkspace - -scheme '${{matrix.scheme}}' - -configuration Debug - CODE_SIGNING_ALLOWED="NO" - build - - - name: Archiving Raw Build Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-build-output-os-${{matrix.runs-on}}-xcode-${{matrix.xcode}}-scheme-${{matrix.scheme}} - path: | - raw-build-output.log - - build-xcframework: - name: Build XCFramework - # The macos-13 uses an Intel processor and doesn't compile the XCFramework for visionOS. - # The large image compiles on arm64 and successfully creates the XCFramework for visionOS. - runs-on: macos-13-xlarge - steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 15.2 - - run: echo "FRAMEWORK_RUN_ID=$(./scripts/xcframework-generated-run.sh)" >> $GITHUB_ENV - - - uses: actions/download-artifact@v4 - if: startsWith(github.ref, 'refs/heads/release/') - with: - name: xcframeworks.zip - path: Carthage/ - github-token: ${{ secrets.GITHUB_TOKEN }} - run-id: ${{ env.FRAMEWORK_RUN_ID }} - - - name: Check XCFramework - # We dont compile the framework during releases to not change the artefact SHA value - # instead we use the one archive as an artefact - if: startsWith(github.ref, 'refs/heads/release/') - run: | - ls -R Carthage - if [ ! -f Carthage/Sentry.xcframework.zip ]; then - echo "XCFramework is not available" - exit 1 - fi - - - name: Build xcframework - if: startsWith(github.ref, 'refs/heads/release/') == false - run: make build-xcframework - shell: sh - - - name: Archiving XCFramework.zip - uses: actions/upload-artifact@v4 - with: - name: ${{ github.sha }} - if-no-files-found: error - path: | - ${{ github.workspace }}/Carthage/*.zip - - - name: Archive build log if failed - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-build-output-build-xcframework - path: | - build-xcframework.log - - validate-xcframework: - name: Validate XCFramework - runs-on: macos-13 - needs: build-xcframework - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: ${{ github.sha }} - path: Carthage/ - - run: ./scripts/ci-select-xcode.sh 15.2 - - run: make build-xcframework-sample - shell: 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 Swift Package Manager - runs-on: macos-13 - needs: build-xcframework - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: ${{ github.sha }} - - name: Change path of the framework - run: | - sed -i '' 's/url.*//g' Package.swift - sed -i '' 's/checksum: ".*" \/\/Sentry-Static/path: "Sentry.xcframework.zip"/g' Package.swift - sed -i '' 's/checksum: ".*" \/\/Sentry-Dynamic/path: "Sentry-Dynamic.xcframework.zip"/g' Package.swift - shell: bash - - run: swift build - working-directory: Samples/macOS-SPM-CommandLine - shell: sh - - validate-spm-dynamic: - name: Validate Swift Package Manager Dynamic - runs-on: macos-13 - needs: build-xcframework - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: ${{ github.sha }} - - name: Change path of the framework - run: | - sed -i '' 's/url.*//g' Package.swift - sed -i '' 's/checksum: ".*" \/\/Sentry-Static/path: "Sentry.xcframework.zip"/g' Package.swift - sed -i '' 's/checksum: ".*" \/\/Sentry-Dynamic/path: "Sentry-Dynamic.xcframework.zip"/g' Package.swift - shell: bash - - run: swift build - working-directory: Samples/SPM-Dynamic - shell: sh - - swift-build: - name: Build with Swift - runs-on: macos-13 - needs: build-xcframework - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: ${{ github.sha }} - - name: Change path of the framework - run: | - sed -i '' 's/url.*//g' Package.swift - sed -i '' 's/checksum: ".*" \/\/Sentry-Static/path: "Sentry.xcframework.zip"/g' Package.swift - sed -i '' 's/checksum: ".*" \/\/Sentry-Dynamic/path: "Sentry-Dynamic.xcframework.zip"/g' Package.swift - shell: bash - - run: swift build - shell: sh - - check-debug-without-UIKit: - name: Check no UIKit linkage (DebugWithoutUIKit) - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - - name: Build for Debug - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform iOS \ - --os latest \ - --ref ${{ github.ref }} \ - --command build \ - --device "iPhone 14" \ - --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 - - check-release-without-UIKit: - name: Check no UIKit linkage (ReleaseWithoutUIKit) - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - - name: Build for Release - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform iOS \ - --os latest \ - --ref ${{ github.ref }} \ - --command build \ - --device "iPhone 14" \ - --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 - - check-debug-with-UIKit: - name: Check UIKit linkage (Debug) - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - - name: Build for Debug - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform iOS \ - --os latest \ - --ref ${{ github.ref }} \ - --command build \ - --device "iPhone 14" \ - --configuration Debug \ - --derived-data uikit-check-build - - name: Ensure UIKit is linked - run: ./scripts/check-uikit-linkage.sh Debug uikit-check-build linked Sentry - - check-release-with-UIKit: - name: Check UIKit linkage (Release) - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - - name: Build for Release - run: | - ./scripts/sentry-xcodebuild.sh \ - --platform iOS \ - --os latest \ - --ref ${{ github.ref }} \ - --command build \ - --device "iPhone 14" \ - --configuration Release \ - --derived-data uikit-check-build - - name: Ensure UIKit is linked - run: ./scripts/check-uikit-linkage.sh Release uikit-check-build linked Sentry 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 e4bdffbfd36..00000000000 --- a/.github/workflows/changes-in-high-risk-code.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Changes In High Risk Code -on: - pull_request: - -# 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: - files-changed: - name: Detect changed files - 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@v4 - - 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: - if: needs.files-changed.outputs.high_risk_code == 'true' - needs: files-changed - runs-on: ubuntu-latest - steps: - - name: Comment on PR to notify of changes in high risk files - uses: actions/github-script@v7 - 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/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index c60d73ccdd3..00000000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: "CodeQL" - -on: - push: - branches: [main] - pull_request: - branches: - - main - schedule: - - cron: "40 4 * * 6" - -# 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: - analyze: - name: Analyze - runs-on: macos-13 - - strategy: - fail-fast: false - matrix: - language: ["cpp"] - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - - - run: | - set -o pipefail && NSUnbufferedIO=YES xcodebuild \ - -workspace Sentry.xcworkspace \ - -scheme Sentry \ - -configuration Release \ - -destination platform="iOS Simulator,OS=latest,name=iPhone 14 Pro" \ - build 2>&1 | - tee raw-analyze-output.log | - xcbeautify - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml deleted file mode 100644 index 000b75ff3ee..00000000000 --- a/.github/workflows/danger.yml +++ /dev/null @@ -1,9 +0,0 @@ -name: Danger - -on: - pull_request: - types: [opened, synchronize, reopened, edited, ready_for_review] - -jobs: - danger: - uses: getsentry/github-workflows/.github/workflows/danger.yml@v2 diff --git a/.github/workflows/format-code.yml b/.github/workflows/format-code.yml deleted file mode 100644 index 2feaa1e09b8..00000000000 --- a/.github/workflows/format-code.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: format code -on: - pull_request: - paths: - - "Sources/**" - - "Tests/**" - - "test-server/**" - - "Samples/**" - - ".github/workflows/format-code.yml" - -jobs: - # Formats Swift, Objective-C, C++, and C code and commits the formatted code - # if necessary - format-code: - name: Format Code - runs-on: macos-15 - steps: - - uses: actions/checkout@v4 - - - name: Install tooling - run: make init-ci-format - - - run: swiftlint --version - - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - - run: corepack enable - - run: yarn install - - - name: Format Code - run: make format - - # actions/checkout fetches only a single commit in a detached HEAD state. Therefore - # we need to pass the current branch, otherwise we can't commit the changes. - # GITHUB_HEAD_REF is the name of the head branch. GitHub Actions only sets this for PRs. - - name: Commit Formatted Code - run: ./scripts/commit-formatted-code.sh $GITHUB_HEAD_REF diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml deleted file mode 100644 index 5b274bb4a2a..00000000000 --- a/.github/workflows/integration-test.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: CocoaPods Integration Tests -on: - push: - branches: - - main - - pull_request: - paths: - - ".github/workflows/integration-test.yml" - - "*.xcodeproj" - - "*.xcworkspace" - - "Samples/iOS-Cocoapods-*/**" - - "scripts/ci-select-xcode.sh" - - "Sources/**" - -# 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: - cocoapods: - name: Integration Test - runs-on: macos-15 - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Select Xcode - run: ./scripts/ci-select-xcode.sh 16.2 - - - 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 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index ac162bacd40..00000000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,100 +0,0 @@ -name: lint -on: - push: - branches: - - main - paths: - - "Sources/**" - - "Tests/**" - - "test-server/**" - - "Samples/**" - - ".github/workflows/lint.yml" - - "scripts/ci-select-xcode.sh" - - "*.json" - - "*.md" - - pull_request: - paths: - - "Sources/**" - - "Tests/**" - - "test-server/**" - - "Samples/**" - - ".github/workflows/lint.yml" - - "scripts/ci-select-xcode.sh" - - "Sentry.xcodeproj/**" - - "*.podspec" - - "Gemfile.lock" - - "*.json" - - "*.md" - -# 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: - swift-lint: - name: Swift Lint - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - - run: swiftlint --version - - name: Run SwiftLint - run: swiftlint --strict - - xcode-analyze: - name: Xcode Analyze - runs-on: macos-14 - steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 16.2 - - run: make analyze - - lint-podspec: - name: pod lint ${{ matrix.podspec}} ${{ matrix.library_type }} ${{ matrix.platform}} - 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@v4 - - 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}} - - lint-hybrid-sdk-podspec: - name: pod lint Sentry/HybridSDK - runs-on: macos-14 - - steps: - - uses: actions/checkout@v4 - - 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}" - - shellcheck: - name: Run Shellcheck - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - - run: brew install shellcheck - - run: shellcheck **/*.sh - - lint-prettier: - name: Run Prettier - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - - run: corepack enable - - run: yarn install - - run: yarn prettier --check --ignore-unknown --config .prettierrc "**/*.{md,json,yml,yaml}" diff --git a/.github/workflows/release-comment-issues.yml b/.github/workflows/release-comment-issues.yml deleted file mode 100644 index 49f023f9efe..00000000000 --- a/.github/workflows/release-comment-issues.yml +++ /dev/null @@ -1,31 +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-20.04 - name: Notify issues - steps: - - name: Get version - id: get_version - run: echo "version=${{ github.event.inputs.version || github.event.release.tag_name }}" >> $GITHUB_OUTPUT - - - 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.yml b/.github/workflows/release.yml deleted file mode 100644 index b1719386438..00000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Release -run-name: Release ${{ github.event.inputs.version }} - -on: - 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 - -jobs: - prepare_framework: - runs-on: macos-13-xlarge - name: "Create XCFramework" - steps: - - uses: actions/checkout@v4 - - - name: "Generate XCFramework" - run: | - ./scripts/ci-select-xcode.sh 15.2 - make bump-version TO=${{ github.event.inputs.version }} - # We need to build the framework during release to get it's SHA value - # the framework will be saved as an artefact and we will use the same - # binary for the entire release process to avoid the SHA to change - make build-xcframework - - - uses: actions/upload-artifact@v4 - with: - name: xcframeworks.zip - path: | - Carthage/Sentry.xcframework.zip - Carthage/Sentry-Dynamic.xcframework.zip - Carthage/SentrySwiftUI.xcframework.zip - Carthage/Sentry-WithoutUIKitOrAppKit.zip - overwrite: true - - job_release: - runs-on: ubuntu-latest - name: "Release a new version" - needs: prepare_framework - steps: - - name: Get auth token - id: token - uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 # v2.0.2 - 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@v4 - with: - token: ${{ steps.token.outputs.token }} - fetch-depth: 0 - - - uses: actions/download-artifact@v4 - with: - name: xcframeworks.zip - path: Carthage/ - - # 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 }} - - - 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 }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 909aa26fbd5..00000000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,313 +0,0 @@ -name: Test -on: - push: - branches: - - main - - release/** - - pull_request: - paths: - - "Sources/**" - - "Tests/**" - - "SentryTestUtils/**" - - "test-server/**" - - ".github/workflows/test.yml" - - "fastlane/**" - - "scripts/tests-with-thread-sanitizer.sh" - - "scripts/ci-select-xcode.sh" - - "scripts/sentry-xcodebuild.sh" - - ".codecov.yml" - - "Sentry.xcodeproj" - - "**/*.xctestplan" - -# 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: - build-test-server: - name: Build test server - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - - name: Cache for Test Server - id: cache_test_server - uses: actions/cache@v4 - with: - path: ./test-server/.build - key: test-server-${{ hashFiles('./test-server') }} - restore-keys: | - test-server-${{ hashFiles('./test-server') }} - test-server- - - - name: Build Test Server - if: steps.cache_test_server.outputs.cache-hit != 'true' - working-directory: test-server - run: >- - swift build -c release 2>&1 | tee test-server-build.log - - - name: Copy exec - working-directory: test-server - run: cp $(swift build --show-bin-path -c release)/Run test-server-exec - - - 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-${{matrix.platform}}-xcode-${{matrix.xcode}}-os-${{matrix.test-destination-os}} - path: | - raw-test-output.log - - unit-tests: - name: Unit ${{matrix.platform}} - Xcode ${{matrix.xcode}} - OS ${{matrix.test-destination-os}} ${{matrix.scheme}} - runs-on: ${{matrix.runs-on}} - timeout-minutes: 20 - needs: build-test-server - - 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 - - runs-on: macos-13 - platform: "iOS" - xcode: "14.3.1" - test-destination-os: "16.4" - device: "iPhone 14" - scheme: "Sentry" - - # iOS 17 - - runs-on: macos-14 - platform: "iOS" - xcode: "15.4" - test-destination-os: "17.2" - device: "iPhone 15" - scheme: "Sentry" - - # iOS 18 - - runs-on: macos-15 - platform: "iOS" - xcode: "16.2" - test-destination-os: "18.2" - device: "iPhone 16" - 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 - - runs-on: macos-14 - platform: "macOS" - xcode: "15.4" - test-destination-os: "latest" - scheme: "Sentry" - - # macOS 15 - - runs-on: macos-15 - platform: "macOS" - xcode: "16.2" - test-destination-os: "latest" - 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. - - runs-on: macos-14 - platform: "Catalyst" - xcode: "15.4" - test-destination-os: "latest" - scheme: "Sentry" - - - runs-on: macos-15 - platform: "Catalyst" - xcode: "16.2" - test-destination-os: "latest" - scheme: "Sentry" - - # 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 - - runs-on: macos-14 - platform: "tvOS" - xcode: "15.4" - test-destination-os: "17.5" - scheme: "Sentry" - - # iOS 17 - - runs-on: macos-14 - platform: "iOS" - xcode: "15.4" - test-destination-os: "17.2" - device: "iPhone 15" - scheme: "SentrySwiftUI" - - # tvOS 18 - - runs-on: macos-15 - platform: "tvOS" - xcode: "16.2" - test-destination-os: "18.1" - scheme: "Sentry" - - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: test-server - - - name: Print hardware info - run: system_profiler SPHardwareDataType - - - name: Allow test-server to run - run: chmod +x ./test-server-exec - - run: ./test-server-exec & - - - name: Check test-server runs - run: curl http://localhost:8080/echo-baggage-header - - - run: ./scripts/ci-select-xcode.sh ${{matrix.xcode}} - - - name: Install Slather - run: gem install slather - - # 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@cf701569b05ccdd861a76b8607a66d76f6fd4857 # v5.5.1 - if: always() - with: - report_paths: "build/reports/junit.xml" - fail_on_failure: true - fail_on_parse_error: true - detailed_summary: true - - - name: Slowest Tests - if: ${{ always() }} - run: ./scripts/xcode-slowest-tests.sh - - - 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 Test Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-test-output-${{matrix.platform}}-xcode-${{matrix.xcode}}-os-${{matrix.test-destination-os}} - path: | - 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/** - - # 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@ad3126e916f78f00edff4ed0317cf185271ccc2d # pin@v5.4.2 - 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@ad3126e916f78f00edff4ed0317cf185271ccc2d # pin@v5.4.2 - 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 - - # We don't run all unit tests with Thread Sanitizer enabled because - # that adds a significant overhead. - thread-sanitizer: - name: Unit iOS - Thread Sanitizer - runs-on: macos-14 - timeout-minutes: 20 - needs: [build-test-server] - - # There are several ways this test can flake. Sometimes threaded tests will just hang and the job will time out, other times waiting on expectations will take much longer than in a non-TSAN run and the test case will fail. We're making this nonfailable and will grep the logs to extract any actual thread sanitizer warnings to push to the PR, and ignore everything else. - continue-on-error: true - - steps: - - uses: actions/checkout@v4 - - - uses: actions/download-artifact@v4 - with: - name: test-server - - - name: Allow test-server to run - run: chmod +x ./test-server-exec - - - run: ./test-server-exec & - - - name: Check test-server runs - run: curl http://localhost:8080/echo-baggage-header - - - run: ./scripts/ci-select-xcode.sh 16.2 - - - name: Running tests with ThreadSanitizer - run: ./scripts/tests-with-thread-sanitizer.sh - - - name: Archiving Test Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: thread-sanitizer - path: thread-sanitizer.log diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml deleted file mode 100644 index 0ae0db44bb2..00000000000 --- a/.github/workflows/testflight.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: Upload to Testflight -on: - push: - branches: - - main - - release/** - - paths: - - "Sources/**" - - "Samples/iOS-Swift/**" - - ".github/workflows/testflight.yml" - - "fastlane/**" - - "scripts/ci-select-xcode.sh" - - pull_request: - paths: - - ".github/workflows/testflight.yml" - workflow_dispatch: - -jobs: - upload_to_testflight: - name: Build and Upload iOS-Swift to Testflight - runs-on: macos-15 - steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 16.2 - - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - # 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/ diff --git a/.github/workflows/ui-tests-critical.yml b/.github/workflows/ui-tests-critical.yml deleted file mode 100644 index 72674e04645..00000000000 --- a/.github/workflows/ui-tests-critical.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: UI Tests Critical -on: - push: - branches: - - main - - pull_request: - paths: - - "Sources/**" - - ".github/workflows/ui-tests-critical.yml" - - "fastlane/**" - - "TestSamples/**" - - "**/*.xctestplan" - # Explicitly list used scripts to avoid unnecessary runs - - "scripts/ci-boot-simulator.sh" - - "scripts/ci-select-xcode.sh" - -# 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: - build-sample: - name: Build SwiftUITestSample Sample - runs-on: macos-15 - steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh "16.2" - - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - run: bundle exec fastlane build_ios_swift_ui_test_sample - - uses: actions/upload-artifact@v4 - with: - name: SwiftUITestSample - path: TestSamples/SwiftUITestSample/DerivedData/Build/Products/Debug-iphonesimulator/SwiftUITestSample.app - - run-tests: - name: Test iOS on Xcode ${{matrix.xcode}} - V2 # Up the version with every change to keep track of flaky tests - needs: [build-sample] - runs-on: ${{matrix.runs-on}} - env: - APP_ARTIFACT_NAME: "SwiftUITestSample" - APP_PATH: "Sample.app" - - MAESTRO_FLOWS_PATH: "TestSamples/SwiftUITestSample/Maestro" - MAESTRO_LOGS_PATH: "MaestroLogs" - - # https://github.com/facebook/react-native/blob/24e7f7d25629a7af6d877a0b79fed2faaab96437/.github/actions/maestro-ios/action.yml#L57 - MAESTRO_DRIVER_STARTUP_TIMEOUT: 1500000 # 25 min, CI can be slow at times - - 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 - - runs-on: macos-13 - xcode: "14.3.1" - - # macos-14 iOS 17 not included due to the XCUIServerNotFound errors causing flaky tests - - # As of 25th March 2025, the preinstalled iOS simulator version is 18.2 for macOS 15 and Xcode 16.2; see - # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md#installed-sdks - - runs-on: macos-15 - xcode: "16.2" - - steps: - - uses: actions/checkout@v4 - - - name: Install tooling - run: make init-ci-test - - - uses: actions/download-artifact@v4 - with: - name: ${{env.APP_ARTIFACT_NAME}} - path: ${{env.APP_PATH}} - - - run: ./scripts/ci-boot-simulator.sh --xcode ${{matrix.xcode}} - - - name: Install App - run: xcrun simctl install booted ${{env.APP_PATH}} - - - name: Run Maestro Flows - run: | - maestro test ${{env.MAESTRO_FLOWS_PATH}} --format junit --debug-output ${{env.MAESTRO_LOGS_PATH}} - - - name: Store Maestro Logs - uses: actions/upload-artifact@v4 - if: failure() - with: - name: maestro-logs-${{matrix.xcode}} - path: ${{env.MAESTRO_LOGS_PATH}} - - - name: Archiving Crash Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: crash-logs-${{matrix.xcode}} - path: | - ~/Library/Logs/DiagnosticReports/** diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index 89cd995b0e2..dbce6916266 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -21,185 +21,9 @@ concurrency: cancel-in-progress: true jobs: - ui-tests: - name: UI Tests for ${{matrix.target}} - V3 # Up the version with every change to keep track of flaky tests + ui-tests-macos: + name: UI Tests for macOS-Swift runs-on: macos-14 - strategy: - matrix: - target: ["ios_objc", "tvos_swift"] - steps: - - uses: actions/checkout@v4 - - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - run: ./scripts/ci-select-xcode.sh 16.2 - - - name: Run Fastlane - run: bundle exec fastlane ui_tests_${{matrix.target}} - shell: sh - - - name: Publish Test Report - uses: mikepenz/action-junit-report@cf701569b05ccdd861a76b8607a66d76f6fd4857 # v5.5.1 - if: always() - with: - report_paths: "build/reports/junit.xml" - fail_on_failure: true - fail_on_parse_error: true - detailed_summary: true - - - name: Upload Result Bundle - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: ui-tests-${{matrix.target}}.xcresult - path: fastlane/test_results/ui-tests-${{matrix.target}}.xcresult - - - name: Archiving Raw Test Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: raw-uitest-output-${{matrix.target}} - path: | - ~/Library/Logs/scan/*.log - ./fastlane/test_output/** - - # SwiftUI only supports iOS 14+ so we run it in a separate matrix here - ui-tests-swift-ui: - name: UI Tests for SwiftUI - V3 # Up the version with every change to keep track of flaky tests - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - - run: ./scripts/ci-select-xcode.sh 14.3.1 - - - name: Run Fastlane - run: bundle exec fastlane ui_tests_ios_swiftui - shell: sh - - - name: Publish Test Report - uses: mikepenz/action-junit-report@cf701569b05ccdd861a76b8607a66d76f6fd4857 # v5.5.1 - if: always() - with: - report_paths: "build/reports/junit.xml" - fail_on_failure: true - fail_on_parse_error: true - detailed_summary: true - - - name: Upload Result Bundle - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: ui-tests-ios-swiftui.xcresult - path: fastlane/test_results/ui-tests-ios-swiftui.xcresult - - - name: Archiving Raw Test Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: ui-tests-ios-swiftui-raw-output - path: | - ~/Library/Logs/scan/*.log - ./fastlane/test_output/** - - ui-tests-swift: - name: UI Tests for iOS-Swift Xcode ${{matrix.xcode}} - V3 # Up the version with every change to keep track of flaky tests - runs-on: ${{matrix.runs-on}} - 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 - - runs-on: macos-13 - xcode: "14.3.1" - - # As of 25th March 2025, the default iOS simulator version is 17.5 for macOS 14 and Xcode 15.4; see - # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md#installed-sdks - - runs-on: macos-14 - xcode: "15.4" - - steps: - - uses: actions/checkout@v4 - - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - - run: ./scripts/ci-select-xcode.sh ${{matrix.xcode}} - - - name: Run Fastlane - run: bundle exec fastlane ui_tests_ios_swift - - - name: Publish Test Report - uses: mikepenz/action-junit-report@cf701569b05ccdd861a76b8607a66d76f6fd4857 # v5.5.1 - if: always() - with: - report_paths: "build/reports/junit.xml" - fail_on_failure: true - fail_on_parse_error: true - detailed_summary: true - - - name: Upload Result Bundle - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: ui-tests-ios-swift-${{matrix.xcode}}.xcresult - path: fastlane/test_results/ui-tests-ios-swift.xcresult - - - name: Archiving Raw Test Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: ui-tests-ios-swift-raw-logs-${{matrix.xcode}} - path: | - ~/Library/Logs/scan/*.log - ./fastlane/test_output/** - - ui-tests-swift6: - name: UI Tests for iOS-Swift6 - V3 # Up the version with every change to keep track of flaky tests - runs-on: macos-15 - steps: - - uses: actions/checkout@v4 - - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - - run: ./scripts/ci-select-xcode.sh "16.2" - - - name: Run Fastlane - run: bundle exec fastlane ui_tests_ios_swift6 - - - name: Publish Test Report - uses: mikepenz/action-junit-report@cf701569b05ccdd861a76b8607a66d76f6fd4857 # v5.5.1 - if: always() - with: - report_paths: "build/reports/junit.xml" - fail_on_failure: true - fail_on_parse_error: true - detailed_summary: true - - - name: Upload Result Bundle - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: ui-tests-ios-swift6.xcresult - path: fastlane/test_results/ui-tests-ios-swift6.xcresult - - - name: Archiving Raw Test Logs - uses: actions/upload-artifact@v4 - if: ${{ failure() || cancelled() }} - with: - name: ui-tests-ios-swift6-raw-output - path: | - ~/Library/Logs/scan/*.log - ./fastlane/test_output/** - - duplication-tests: - name: UI Tests for project with Sentry duplicated - V3 # Up the version with every change to keep track of flaky tests - runs-on: macos-15 - steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 @@ -208,10 +32,8 @@ jobs: - run: ./scripts/ci-select-xcode.sh "16.2" - - run: ./scripts/build-xcframework.sh gameOnly - - name: Run Fastlane - run: bundle exec fastlane duplication_test + run: bundle exec fastlane ui_tests_macos_swift - name: Publish Test Report uses: mikepenz/action-junit-report@cf701569b05ccdd861a76b8607a66d76f6fd4857 # v5.5.1 @@ -226,14 +48,14 @@ jobs: uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: duplication-test.xcresult - path: fastlane/test_results/duplication-test.xcresult + name: ui-tests-macos-swift.xcresult + path: fastlane/test_results/ui-tests-macos-swift.xcresult - name: Archiving Raw Test Logs uses: actions/upload-artifact@v4 if: ${{ failure() || cancelled() }} with: - name: duplication-test-raw-output + name: ui-tests-macos-swift-raw-output path: | ~/Library/Logs/scan/*.log ./fastlane/test_output/** diff --git a/CHANGELOG.md b/CHANGELOG.md index 46fc26417d1..2490fe9477c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Fixes + +- Non-sandboxed macOS app launch profile configuration are now respected (#5144) + ## 8.49.1 ### Fixes @@ -17,7 +23,7 @@ - New continuous profiling configuration API (#4952 and #5063) > [!Important] -> With the addition of the new profiling configuation API, the previous profiling API are deprecated and will be removed in the next major version of the SDK: +> With the addition of the new profiling configuration API, the previous profiling API are deprecated and will be removed in the next major version of the SDK: > > - `SentryOptions.enableProfiling` > - `SentryOptions.isProfilingEnabled` @@ -897,6 +903,9 @@ The following two features, disabled by default, were mistakenly added to the re ## 8.21.0 +> ![Important] +> This version introduced an issue for macOS apps that run without a sandbox (i.e. distributed outside the Mac App Store). We recommend upgrading to at least version 8.49.2. + ### Features - Add support for Sentry [Spotlight](https://spotlightjs.com/) (#3642), which is basically Sentry diff --git a/Plans/macOS-Swift_Base.xctestplan b/Plans/macOS-Swift_Base.xctestplan index 530901f9c88..6fc98f0a0e1 100644 --- a/Plans/macOS-Swift_Base.xctestplan +++ b/Plans/macOS-Swift_Base.xctestplan @@ -24,7 +24,13 @@ "uiTestingScreenshotsLifetime" : "keepAlways" }, "testTargets" : [ - + { + "target" : { + "containerPath" : "container:macOS-Swift.xcodeproj", + "identifier" : "84B5A90E2DBD1AA4003327C9", + "name" : "macOS-Swift-UITests" + } + } ], "version" : 1 } diff --git a/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift b/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift index 47f7dcde9a7..662c6cd0cde 100644 --- a/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift +++ b/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift @@ -8,6 +8,7 @@ class UserFeedbackUITests: BaseUITest { let fm = FileManager.default /// The Application Support directory is different between this UITest runner app and the target app under test. We have to retrieve the target app's app support directory using UI elements and store it here for usage. + /// - note: The SDK does not use application support for anything. We only use the app support directory for these tests to write marker files from the app indicating which feedback hooks have fired. var appSupportDirectory: String? override func setUp() { diff --git a/Samples/iOS-Swift/iOS-Swift/Profiling/NSObject+SentryAppSetup.m b/Samples/iOS-Swift/iOS-Swift/Profiling/NSObject+SentryAppSetup.m index 8de65966b14..e4ffb419d9e 100644 --- a/Samples/iOS-Swift/iOS-Swift/Profiling/NSObject+SentryAppSetup.m +++ b/Samples/iOS-Swift/iOS-Swift/Profiling/NSObject+SentryAppSetup.m @@ -5,13 +5,18 @@ + (void)load { NSLog(@"[iOS-Swift] Starting app launch work"); if ([NSProcessInfo.processInfo.arguments containsObject:@"--io.sentry.slow-load-method"]) { - NSMutableString *a = [NSMutableString string]; - // 1,000,000 iterations takes about 225 milliseconds in the iPhone 15 simulator on an - // M2 macbook pro; we might have to adapt this for CI - for (NSUInteger i = 0; i < 4000000; i++) { - [a appendFormat:@"%d", arc4random() % 12345]; - } + [self sentry_slowLoadWork]; } NSLog(@"[iOS-Swift] Finishing app launch work"); } + ++ (void)sentry_slowLoadWork +{ + NSMutableString *a = [NSMutableString string]; + // 1,000,000 iterations takes about 225 milliseconds in the iPhone 15 simulator on an + // M2 macbook pro; we might have to adapt this for CI + for (NSUInteger i = 0; i < 4000000; i++) { + [a appendFormat:@"%d", arc4random() % 12345]; + } +} @end diff --git a/Samples/macOS-Swift/macOS-Swift/AppDelegate.swift b/Samples/macOS-Swift/Shared/AppDelegate.swift similarity index 75% rename from Samples/macOS-Swift/macOS-Swift/AppDelegate.swift rename to Samples/macOS-Swift/Shared/AppDelegate.swift index c51cf5dead9..6abfd1893e4 100644 --- a/Samples/macOS-Swift/macOS-Swift/AppDelegate.swift +++ b/Samples/macOS-Swift/Shared/AppDelegate.swift @@ -5,6 +5,7 @@ import Sentry class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { + print("ProcessInfo.processInfo.arguments: \(ProcessInfo.processInfo.arguments)") // Insert code here to initialize your application SentrySDK.start { options in @@ -13,15 +14,23 @@ class AppDelegate: NSObject, NSApplicationDelegate { options.tracesSampleRate = 1.0 let args = ProcessInfo.processInfo.arguments - - if args.contains("--io.sentry.profiling.enable") { - options.profilesSampleRate = 1 + + options.configureProfiling = { + $0.profileAppStarts = ProcessInfo.processInfo.arguments.contains("--io.sentry.enable-profile-app-starts") + $0.sessionSampleRate = 1 + } + + options.enableUncaughtNSExceptionReporting = false + + if args.contains("--disable-auto-performance-tracing") { + options.enableAutoPerformanceTracing = false } + if #available(macOS 12.0, *), !args.contains("--disable-metrickit-integration") { options.enableMetricKit = true options.enableMetricKitRawPayload = true } - + options.initialScope = { scope in if let path = Bundle.main.path(forResource: "Tongariro", ofType: "jpg") { scope.addAttachment(Attachment(path: path, filename: "Tongariro.jpg", contentType: "image/jpeg")) diff --git a/Samples/macOS-Swift/macOS-Swift/Base.lproj/Main.storyboard b/Samples/macOS-Swift/Shared/Base.lproj/Main.storyboard similarity index 92% rename from Samples/macOS-Swift/macOS-Swift/Base.lproj/Main.storyboard rename to Samples/macOS-Swift/Shared/Base.lproj/Main.storyboard index fcded32c41f..7ca01f4173f 100644 --- a/Samples/macOS-Swift/macOS-Swift/Base.lproj/Main.storyboard +++ b/Samples/macOS-Swift/Shared/Base.lproj/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -706,14 +706,14 @@ - + - + + + + + + + + + + + + + @@ -879,6 +921,10 @@ + + + + @@ -896,6 +942,10 @@ + + + + @@ -906,6 +956,9 @@ + + + diff --git a/Samples/macOS-Swift/macOS-Swift/CppSample.cpp b/Samples/macOS-Swift/Shared/CppSample.cpp similarity index 100% rename from Samples/macOS-Swift/macOS-Swift/CppSample.cpp rename to Samples/macOS-Swift/Shared/CppSample.cpp diff --git a/Samples/macOS-Swift/macOS-Swift/CppSample.hpp b/Samples/macOS-Swift/Shared/CppSample.hpp similarity index 100% rename from Samples/macOS-Swift/macOS-Swift/CppSample.hpp rename to Samples/macOS-Swift/Shared/CppSample.hpp diff --git a/Samples/macOS-Swift/macOS-Swift/CppWrapper.h b/Samples/macOS-Swift/Shared/CppWrapper.h similarity index 100% rename from Samples/macOS-Swift/macOS-Swift/CppWrapper.h rename to Samples/macOS-Swift/Shared/CppWrapper.h diff --git a/Samples/macOS-Swift/macOS-Swift/CppWrapper.m b/Samples/macOS-Swift/Shared/CppWrapper.m similarity index 100% rename from Samples/macOS-Swift/macOS-Swift/CppWrapper.m rename to Samples/macOS-Swift/Shared/CppWrapper.m diff --git a/Samples/macOS-Swift/macOS-Swift/DiskWriteException.swift b/Samples/macOS-Swift/Shared/DiskWriteException.swift similarity index 100% rename from Samples/macOS-Swift/macOS-Swift/DiskWriteException.swift rename to Samples/macOS-Swift/Shared/DiskWriteException.swift diff --git a/Samples/macOS-Swift/macOS-Swift/Info.plist b/Samples/macOS-Swift/Shared/Info.plist similarity index 100% rename from Samples/macOS-Swift/macOS-Swift/Info.plist rename to Samples/macOS-Swift/Shared/Info.plist diff --git a/Samples/macOS-Swift/Shared/NSObject+SentryAppSetup.h b/Samples/macOS-Swift/Shared/NSObject+SentryAppSetup.h new file mode 100644 index 00000000000..32ca1249b38 --- /dev/null +++ b/Samples/macOS-Swift/Shared/NSObject+SentryAppSetup.h @@ -0,0 +1,15 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A category that overrides its `+[load]` method to deliberately take a long time to run, so we can + * see it show up in profile stack traces. Categories' `+[load]` methods are guaranteed to be called + * after all of a module's normal class' overrides, so we can be confident the ordering will always + * have started the launch profiler by the time this runs. This must be done in Objective-C because + * Swift does not allow implementation of `NSObject.load()`. + */ +@interface NSObject (SentryAppSetup) +@end + +NS_ASSUME_NONNULL_END diff --git a/Samples/macOS-Swift/Shared/NSObject+SentryAppSetup.m b/Samples/macOS-Swift/Shared/NSObject+SentryAppSetup.m new file mode 100644 index 00000000000..e4ffb419d9e --- /dev/null +++ b/Samples/macOS-Swift/Shared/NSObject+SentryAppSetup.m @@ -0,0 +1,22 @@ +#import "NSObject+SentryAppSetup.h" + +@implementation NSObject (SentryAppSetup) ++ (void)load +{ + NSLog(@"[iOS-Swift] Starting app launch work"); + if ([NSProcessInfo.processInfo.arguments containsObject:@"--io.sentry.slow-load-method"]) { + [self sentry_slowLoadWork]; + } + NSLog(@"[iOS-Swift] Finishing app launch work"); +} + ++ (void)sentry_slowLoadWork +{ + NSMutableString *a = [NSMutableString string]; + // 1,000,000 iterations takes about 225 milliseconds in the iPhone 15 simulator on an + // M2 macbook pro; we might have to adapt this for CI + for (NSUInteger i = 0; i < 4000000; i++) { + [a appendFormat:@"%d", arc4random() % 12345]; + } +} +@end diff --git a/Samples/macOS-Swift/macOS-Swift/SwiftUIView.swift b/Samples/macOS-Swift/Shared/SwiftUIView.swift similarity index 100% rename from Samples/macOS-Swift/macOS-Swift/SwiftUIView.swift rename to Samples/macOS-Swift/Shared/SwiftUIView.swift diff --git a/Samples/macOS-Swift/macOS-Swift/Tongariro.jpg b/Samples/macOS-Swift/Shared/Tongariro.jpg similarity index 100% rename from Samples/macOS-Swift/macOS-Swift/Tongariro.jpg rename to Samples/macOS-Swift/Shared/Tongariro.jpg diff --git a/Samples/macOS-Swift/macOS-Swift/ViewController.swift b/Samples/macOS-Swift/Shared/ViewController.swift similarity index 56% rename from Samples/macOS-Swift/macOS-Swift/ViewController.swift rename to Samples/macOS-Swift/Shared/ViewController.swift index 9692b9032ad..35a4abae7a3 100644 --- a/Samples/macOS-Swift/macOS-Swift/ViewController.swift +++ b/Samples/macOS-Swift/Shared/ViewController.swift @@ -5,42 +5,44 @@ import SwiftUI class ViewController: NSViewController { private let diskWriteException = DiskWriteException() - + + @IBOutlet weak var uiTestDataMarshalingField: NSTextField! + @IBAction func addBreadCrumb(_ sender: Any) { let crumb = Breadcrumb(level: SentryLevel.info, category: "Debug") crumb.message = "tapped addBreadcrumb" crumb.type = "user" SentrySDK.addBreadcrumb(crumb) } - - @IBAction func captureMessage(_ sender: Any) { + + @IBAction func captureMessage(_ sender: Any) { let eventId = SentrySDK.capture(message: "Yeah captured a message") // Returns eventId in case of successfull processed event // otherwise nil print("\(String(describing: eventId))") } - + @IBAction func captureError(_ sendder: Any) { let error = NSError(domain: "SampleErrorDomain", code: 1, userInfo: [NSLocalizedDescriptionKey: "Object does not exist"]) SentrySDK.capture(error: error) { (scope) in scope.setTag(value: "value", key: "myTag") } } - + @IBAction func captureException(_ sender: Any) { - let exception = NSException(name: NSExceptionName("My Custom exeption"), reason: "User clicked the button", userInfo: nil) + let exception = NSException(name: NSExceptionName("My Custom exception"), reason: "User clicked the button", userInfo: nil) let scope = Scope() scope.setLevel(.fatal) SentrySDK.capture(exception: exception, scope: scope) } - + @IBAction func captureUserFeedback(_ sender: Any) { let error = NSError(domain: "UserFeedbackErrorDomain", code: 0, userInfo: [NSLocalizedDescriptionKey: "This never happens."]) let eventId = SentrySDK.capture(error: error) { scope in scope.setLevel(.fatal) } - + let userFeedback = UserFeedback(eventId: eventId) userFeedback.comments = "It broke on macOS-Swift. I don't know why, but this happens." userFeedback.email = "john@me.com" @@ -53,50 +55,50 @@ class ViewController: NSViewController { let exception = NSException(name: NSExceptionName("NSException via NSException raise"), reason: "Raised NSException", userInfo: userInfo) exception.raise() } - + @IBAction func reportNSException(_ sender: Any) { let userInfo: [String: String] = ["user-info-key-1": "user-info-value-1", "user-info-key-2": "user-info-value-2"] let exception = NSException(name: NSExceptionName("NSException via NSApplication report"), reason: "It doesn't work", userInfo: userInfo) NSApplication.shared.reportException(exception) } - + @IBAction func throwNSRangeException(_ sender: Any) { CppWrapper().throwNSRangeException() } - + @IBAction func captureTransaction(_ sender: Any) { let transaction = SentrySDK.startTransaction(name: "Some Transaction", operation: "some operation") DispatchQueue.main.asyncAfter(deadline: .now() + Double.random(in: 0.4...0.6), execute: { transaction.finish() }) } - + @IBAction func sentryCrash(_ sender: Any) { SentrySDK.crash() } - + @IBAction func cppException(_ sender: Any) { let wrapper = CppWrapper() wrapper.throwCPPException() } - + @IBAction func rethrowNoActiveCppException(_ sender: Any) { let wrapper = CppWrapper() wrapper.rethrowNoActiveCPPException() } - + @IBAction func asyncCrash(_ sender: Any) { DispatchQueue.main.async { self.asyncCrash1() } } - + @IBAction func diskWriteException(_ sender: Any) { diskWriteException.continuouslyWriteToDisk() // As we are writing to disk continuously we would keep adding spans to this UIEventTransaction. SentrySDK.span?.finish() } - + @IBAction func showSwiftUIView(_ sender: Any) { let controller = NSHostingController(rootView: SwiftUIView()) let window = NSWindow(contentViewController: controller) @@ -104,13 +106,95 @@ class ViewController: NSViewController { let windowController = NSWindowController(window: window) windowController.showWindow(self) } - + + @IBAction func stopProfile(_ sender: Any) { + SentrySDK.stopProfiler() + } + + @IBAction func retrieveProfileChunk(_ sender: Any) { + uiTestDataMarshalingField.stringValue = "" + withProfile(continuous: true) { file in + handleContents(file: file) + } + } + + var sentryBasePath: String { + let cachesDirectory = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first! + let bundleIdentifier = Bundle.main.bundleIdentifier! + let sandboxedCachesDirectory: String + if cachesDirectory.contains(bundleIdentifier) { + sandboxedCachesDirectory = cachesDirectory + } else { + sandboxedCachesDirectory = (cachesDirectory as NSString).appendingPathComponent(bundleIdentifier) + } + return (sandboxedCachesDirectory as NSString).appendingPathComponent("io.sentry") + } + + func withProfile(continuous: Bool, block: (URL?) -> Void) { + let fm = FileManager.default + let dir = (sentryBasePath as NSString).appendingPathComponent(continuous ? "continuous-profiles" : "trace-profiles") + var isDirectory: ObjCBool = false + guard fm.fileExists(atPath: dir, isDirectory: &isDirectory), isDirectory.boolValue else { + block(nil) + return + } + + let count = try! fm.contentsOfDirectory(atPath: dir).count + //swiftlint:disable empty_count + guard continuous || count > 0 else { + //swiftlint:enable empty_count + uiTestDataMarshalingField.stringValue = "" + return + } + let fileName = "profile\(continuous ? 0 : count - 1)" + let fullPath = "\(dir)/\(fileName)" + + if fm.fileExists(atPath: fullPath) { + let url = NSURL.fileURL(withPath: fullPath) + block(url) + do { + try fm.removeItem(atPath: fullPath) + } catch { + SentrySDK.capture(error: error) + } + return + } + + block(nil) + } + + func handleContents(file: URL?) { + guard let file = file else { + uiTestDataMarshalingField.stringValue = "" + return + } + + do { + let data = try Data(contentsOf: file) + let contents = data.base64EncodedString() + print("[iOS-Swift] [debug] [ProfilingViewController] contents of file at \(file): \(String(describing: String(data: data, encoding: .utf8)))") + uiTestDataMarshalingField.stringValue = contents + } catch { + SentrySDK.capture(error: error) + uiTestDataMarshalingField.stringValue = "" + } + } + + @IBAction func checkProfileMarkerFileExistence(_ sender: Any) { + let launchProfileMarkerPath = (sentryBasePath as NSString).appendingPathComponent("profileLaunch") + if FileManager.default.fileExists(atPath: launchProfileMarkerPath) { + uiTestDataMarshalingField.stringValue = "" + } else { + uiTestDataMarshalingField.stringValue = "" + } + } + func asyncCrash1() { DispatchQueue.main.async { self.asyncCrash2() } } - + func asyncCrash2() { DispatchQueue.main.async { SentrySDK.crash() diff --git a/Samples/macOS-Swift/macOS-Swift/macOS-Swift-Bridging-Header.h b/Samples/macOS-Swift/Shared/macOS-Swift-Bridging-Header.h similarity index 100% rename from Samples/macOS-Swift/macOS-Swift/macOS-Swift-Bridging-Header.h rename to Samples/macOS-Swift/Shared/macOS-Swift-Bridging-Header.h diff --git a/Samples/macOS-Swift/macOS-Swift-Other.xcconfig b/Samples/macOS-Swift/macOS-Swift-Other.xcconfig new file mode 100644 index 00000000000..38b25c99a35 --- /dev/null +++ b/Samples/macOS-Swift/macOS-Swift-Other.xcconfig @@ -0,0 +1,3 @@ +//CODE_SIGN_IDENTITY = +//CODE_SIGN_STYLE = Automatic +//PROVISIONING_PROFILE_SPECIFIER = match Development io.sentry.macOS-Swift-Other diff --git a/Samples/macOS-Swift/macOS-Swift-Sandboxed-Other.xcconfig b/Samples/macOS-Swift/macOS-Swift-Sandboxed-Other.xcconfig new file mode 100644 index 00000000000..7d9890e40d4 --- /dev/null +++ b/Samples/macOS-Swift/macOS-Swift-Sandboxed-Other.xcconfig @@ -0,0 +1,3 @@ +//CODE_SIGN_IDENTITY = Apple Developer +//CODE_SIGN_STYLE = Manual +//PROVISIONING_PROFILE_SPECIFIER = match Development io.sentry.macOS-Swift-Sandboxed-Other diff --git a/Samples/macOS-Swift/macOS-Swift-Sandboxed.xcconfig b/Samples/macOS-Swift/macOS-Swift-Sandboxed.xcconfig new file mode 100644 index 00000000000..df9d40ee1d6 --- /dev/null +++ b/Samples/macOS-Swift/macOS-Swift-Sandboxed.xcconfig @@ -0,0 +1,3 @@ +//CODE_SIGN_IDENTITY = Apple Developer +//CODE_SIGN_STYLE = Manual +//PROVISIONING_PROFILE_SPECIFIER = match Development io.sentry.macOS-Swift-Sandboxed diff --git a/Samples/macOS-Swift/macOS-Swift-UITests.xcconfig b/Samples/macOS-Swift/macOS-Swift-UITests.xcconfig new file mode 100644 index 00000000000..68e9fcdb400 --- /dev/null +++ b/Samples/macOS-Swift/macOS-Swift-UITests.xcconfig @@ -0,0 +1,3 @@ +//CODE_SIGN_IDENTITY = Apple Developer +//CODE_SIGN_STYLE = Manual +//PROVISIONING_PROFILE_SPECIFIER = match Development io.sentry.macOS-Swift-UITests.xctrunner diff --git a/Samples/macOS-Swift/macOS-Swift-UITests/MacOSSwiftUITests.swift b/Samples/macOS-Swift/macOS-Swift-UITests/MacOSSwiftUITests.swift new file mode 100644 index 00000000000..1dba7ab5eef --- /dev/null +++ b/Samples/macOS-Swift/macOS-Swift-UITests/MacOSSwiftUITests.swift @@ -0,0 +1,188 @@ +import XCTest + +final class MacOSSwiftUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = true + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + @MainActor + func testMacAppsDontEnableLaunchProfilingForEachOther_Nonsandboxed() throws { + try performSequence(appBundleID: "io.sentry.macOS-Swift", shouldProfileLaunches: true, wipeData: true) + try performSequence(appBundleID: "io.sentry.macOS-Swift-Other", shouldProfileLaunches: false, wipeData: false) + } + + @MainActor + func testMacAppsDontEnableLaunchProfilingForEachOther_Sandboxed() throws { + try performSequence(appBundleID: "io.sentry.macOS-Swift-Sandboxed", shouldProfileLaunches: true, wipeData: true) + try performSequence(appBundleID: "io.sentry.macOS-Swift-Sandboxed-Other", shouldProfileLaunches: false, wipeData: false) + } +} + +private extension MacOSSwiftUITests { + func performSequence(appBundleID: String, shouldProfileLaunches: Bool, wipeData: Bool) throws { + // one launch to configure launch profiling for the next launch + let app = XCUIApplication(bundleIdentifier: appBundleID) + + if wipeData { + app.launchArguments.append("--io.sentry.wipe-data") + } + + try launchAndConfigureSubsequentLaunches(app: app, shouldProfileThisLaunch: false, shouldProfileNextLaunch: shouldProfileLaunches) + app.terminate() + + if wipeData { + app.launchArguments.removeAll { $0 == "--io.sentry.wipe-data" } + } + + // second launch to profile a launch if configured + try launchAndConfigureSubsequentLaunches(app: app, shouldProfileThisLaunch: shouldProfileLaunches, shouldProfileNextLaunch: shouldProfileLaunches) + app.terminate() + } + + /** + * Performs the various operations for the launch profiler test case: + * - terminates an existing app session + * - creates a new one + * - sets launch args and env vars to set the appropriate `SentryOption` values for the desired behavior + * - launches the new configured app session + * - asserts the expected outcomes of the config file and launch profiler + */ + func launchAndConfigureSubsequentLaunches( + app: XCUIApplication, + shouldProfileThisLaunch: Bool, + shouldProfileNextLaunch: Bool + ) throws { + app.launchArguments.append(contentsOf: [ + // these help avoid other profiles that'd be taken automatically, that interfere with the checking we do for the assertions later in the tests + "--disable-swizzling", + "--disable-auto-performance-tracing", + "--disable-uiviewcontroller-tracing", + + // sets a marker function to run in a load command that the launch profile should detect + "--io.sentry.slow-load-method", + + // override full chunk completion before stoppage introduced in https://github.com/getsentry/sentry-cocoa/pull/4214 + "--io.sentry.continuous-profiler-immediate-stop" + ]) + + app.launchEnvironment["--io.sentry.ui-test.test-name"] = name + + if shouldProfileNextLaunch { + app.launchArguments.append("--io.sentry.enable-profile-app-starts") + } + + app.launch() + + XCTAssertEqual(try checkLaunchProfileMarkerFileExistence(app: app), shouldProfileNextLaunch) + + stopContinuousProfiler(app: app) + retrieveFirstProfileChunkData(app: app) + + guard let lastProfile = try marshalJSONDictionaryFromApp(app: app, shouldProfile: shouldProfileThisLaunch) else { + XCTAssertFalse(shouldProfileThisLaunch) + return + } + + try assertProfileContents(profile: lastProfile) + } + + func assertProfileContents(profile: [String: Any]) throws { + let sampledProfile = try XCTUnwrap(profile["profile"] as? [String: Any]) + let stacks = try XCTUnwrap(sampledProfile["stacks"] as? [[Int]]) + let frames = try XCTUnwrap(sampledProfile["frames"] as? [[String: Any]]) + let stackFunctions = stacks.map({ stack in + stack.map { stackFrame in + frames[stackFrame]["function"] + } + }) + + // grab the first stack that contained frames from the fixture code that simulates a slow +[load] method + var stackID: Int? + let stack = try XCTUnwrap(stackFunctions.enumerated().first { nextStack in + let result = try nextStack.element.contains { frame in + let found = try XCTUnwrap(frame as? String).contains("+[NSObject(SentryAppSetup) load]") + if found { + stackID = nextStack.offset + } + return found + } + return result + }).element.map { any in + try XCTUnwrap(any as? String) + } + guard stackID != nil else { + XCTFail("Didn't find the ID of the stack containing the target function") + return + } + + // ensure that the stack doesn't contain any calls to main functions; this ensures we actually captured pre-main stacks + XCTAssertFalse(stack.contains("main")) + XCTAssertFalse(stack.contains("UIApplicationMain")) + XCTAssertFalse(stack.contains("-[UIApplication _run]")) + + // ensure that the stack happened on the main thread; this is a cross-check to make sure we didn't accidentally grab a stack from a different thread that wouldn't have had a call to main() anyways, thereby possibly missing the real stack that may have contained main() calls (but shouldn't for this test) + let samples = try XCTUnwrap(sampledProfile["samples"] as? [[String: Any]]) + let sample = try XCTUnwrap(samples.first { nextSample in + try XCTUnwrap(nextSample["stack_id"] as? NSNumber).intValue == stackID + }) + XCTAssert(try XCTUnwrap(sample["thread_id"] as? String) == "259") // the main thread is always ID 259 + } + + func retrieveFirstProfileChunkData(app: XCUIApplication) { + app.buttons["io.sentry.ui-tests.view-first-continuous-profile-chunk"].afterWaitingForExistence("Couldn't find button to view first profile chunk").tap() + } + + func stopContinuousProfiler(app: XCUIApplication) { + app.buttons["io.sentry.ios-swift.ui-test.button.stop-continuous-profiler"].afterWaitingForExistence("Couldn't find button to stop continuous profiler").tap() + } + + func checkLaunchProfileMarkerFileExistence(app: XCUIApplication) throws -> Bool { + app.buttons["io.sentry.ui-tests.app-launch-profile-marker-file-button"].afterWaitingForExistence("Couldn't find app launch profile marker file check button").tap() + let string = try XCTUnwrap(app.textFields["io.sentry.ui-tests.profile-marshaling-text-field"].afterWaitingForExistence("Couldn't find data marshaling text field.").value as? NSString) + return string == "" + } + + enum Error: Swift.Error { + case missingFile + case emptyFile + } + + func marshalJSONDictionaryFromApp(app: XCUIApplication, shouldProfile: Bool) throws -> [String: Any]? { + let string = try XCTUnwrap(app.textFields["io.sentry.ui-tests.profile-marshaling-text-field"].afterWaitingForExistence("Couldn't find data marshaling text field.").value as? NSString) + + if shouldProfile { + if string == "" { + throw Error.missingFile + } + if string == "" { + throw Error.emptyFile + } + let data = try XCTUnwrap(Data(base64Encoded: string as String)) + return try XCTUnwrap(try JSONSerialization.jsonObject(with: data) as? [String: Any]) + } else { + XCTAssertEqual("", string) + return nil + } + } +} + +extension XCUIElement { + func waitForExistence(_ message: String) { + XCTAssertTrue(self.waitForExistence(timeout: TimeInterval(10)), message) + } + + func afterWaitingForExistence(_ failureMessage: String) -> XCUIElement { + waitForExistence(failureMessage) + return self + } +} diff --git a/Samples/macOS-Swift/macOS-Swift.xcconfig b/Samples/macOS-Swift/macOS-Swift.xcconfig new file mode 100644 index 00000000000..23e7d7c5370 --- /dev/null +++ b/Samples/macOS-Swift/macOS-Swift.xcconfig @@ -0,0 +1,3 @@ +//CODE_SIGN_IDENTITY = Apple Developer +//CODE_SIGN_STYLE = Manual +//PROVISIONING_PROFILE_SPECIFIER = match Development io.sentry.macOS-Swift diff --git a/Samples/macOS-Swift/macOS-Swift.xcodeproj/project.pbxproj b/Samples/macOS-Swift/macOS-Swift.xcodeproj/project.pbxproj index bd93b6d8816..ed1be4b3e28 100644 --- a/Samples/macOS-Swift/macOS-Swift.xcodeproj/project.pbxproj +++ b/Samples/macOS-Swift/macOS-Swift.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 70; objects = { /* Begin PBXBuildFile section */ @@ -16,7 +16,58 @@ 7B3427FE25876DE700056519 /* Tongariro.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 7B3427FC25876DE700056519 /* Tongariro.jpg */; }; 7B948A06275E459C00F04173 /* CppSample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7B948A04275E459C00F04173 /* CppSample.cpp */; }; 7B948A0A275E4A9900F04173 /* CppWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B948A09275E4A9900F04173 /* CppWrapper.m */; }; + 84B5A91F2DBD2491003327C9 /* NSObject+SentryAppSetup.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B5A91E2DBD2491003327C9 /* NSObject+SentryAppSetup.m */; }; + 84B5A9202DBD4F85003327C9 /* Sentry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 630853442440C45A00DDE4CE /* Sentry.framework */; }; + 84B5A9212DBD4F85003327C9 /* Sentry.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 630853442440C45A00DDE4CE /* Sentry.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 84B5A9242DBD5082003327C9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637AFDEE243B04320034958B /* AppDelegate.swift */; }; + 84B5A9252DBD5082003327C9 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637AFDF0243B04320034958B /* ViewController.swift */; }; + 84B5A9262DBD5099003327C9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 637AFDF4243B04340034958B /* Main.storyboard */; }; + 84B5A9272DBD50B9003327C9 /* GitInjections.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BA72AC2C9369B80045B828 /* GitInjections.swift */; }; + 84B5A9282DBD50D0003327C9 /* DiskWriteException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924D21552C89FE2D00E0FEFD /* DiskWriteException.swift */; }; + 84B5A9292DBD50F5003327C9 /* CppSample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7B948A04275E459C00F04173 /* CppSample.cpp */; }; + 84B5A92A2DBD50F5003327C9 /* CppWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B948A09275E4A9900F04173 /* CppWrapper.m */; }; + 84B5A92B2DBD5125003327C9 /* SwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924D216A2C8A020C00E0FEFD /* SwiftUIView.swift */; }; + 84B5A92C2DBD51DD003327C9 /* NSObject+SentryAppSetup.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B5A91E2DBD2491003327C9 /* NSObject+SentryAppSetup.m */; }; + 84B5A9E82DBD7689003327C9 /* Tongariro.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 7B3427FC25876DE700056519 /* Tongariro.jpg */; }; + 84B5A9E92DBD76A5003327C9 /* SampleAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 62C97D9D2CC6997E00DDA204 /* SampleAssets.xcassets */; }; + 84B5A9F12DBD7CB4003327C9 /* SentrySwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 924D215D2C89FE2D00E0FEFD /* SentrySwiftUI.framework */; }; + 84B5A9F22DBD7CB4003327C9 /* SentrySwiftUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 924D215D2C89FE2D00E0FEFD /* SentrySwiftUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 84B5A9F92DBEB648003327C9 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637AFDF0243B04320034958B /* ViewController.swift */; }; + 84B5A9FA2DBEB648003327C9 /* DiskWriteException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924D21552C89FE2D00E0FEFD /* DiskWriteException.swift */; }; + 84B5A9FB2DBEB648003327C9 /* SwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924D216A2C8A020C00E0FEFD /* SwiftUIView.swift */; }; + 84B5A9FC2DBEB648003327C9 /* CppSample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7B948A04275E459C00F04173 /* CppSample.cpp */; }; + 84B5A9FD2DBEB648003327C9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637AFDEE243B04320034958B /* AppDelegate.swift */; }; + 84B5A9FE2DBEB648003327C9 /* GitInjections.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BA72AC2C9369B80045B828 /* GitInjections.swift */; }; + 84B5A9FF2DBEB648003327C9 /* NSObject+SentryAppSetup.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B5A91E2DBD2491003327C9 /* NSObject+SentryAppSetup.m */; }; + 84B5AA002DBEB648003327C9 /* CppWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B948A09275E4A9900F04173 /* CppWrapper.m */; }; + 84B5AA022DBEB648003327C9 /* Sentry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 630853442440C45A00DDE4CE /* Sentry.framework */; }; + 84B5AA032DBEB648003327C9 /* SentrySwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 924D215D2C89FE2D00E0FEFD /* SentrySwiftUI.framework */; }; + 84B5AA062DBEB648003327C9 /* SampleAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 62C97D9D2CC6997E00DDA204 /* SampleAssets.xcassets */; }; + 84B5AA072DBEB648003327C9 /* Tongariro.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 7B3427FC25876DE700056519 /* Tongariro.jpg */; }; + 84B5AA082DBEB648003327C9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 637AFDF4243B04340034958B /* Main.storyboard */; }; + 84B5AA0A2DBEB648003327C9 /* Sentry.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 630853442440C45A00DDE4CE /* Sentry.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 84B5AA0B2DBEB648003327C9 /* SentrySwiftUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 924D215D2C89FE2D00E0FEFD /* SentrySwiftUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 84B5AA1A2DBEB658003327C9 /* CppSample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7B948A04275E459C00F04173 /* CppSample.cpp */; }; + 84B5AA1B2DBEB658003327C9 /* SwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924D216A2C8A020C00E0FEFD /* SwiftUIView.swift */; }; + 84B5AA1C2DBEB658003327C9 /* CppWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B948A09275E4A9900F04173 /* CppWrapper.m */; }; + 84B5AA1D2DBEB658003327C9 /* DiskWriteException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924D21552C89FE2D00E0FEFD /* DiskWriteException.swift */; }; + 84B5AA1E2DBEB658003327C9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637AFDEE243B04320034958B /* AppDelegate.swift */; }; + 84B5AA1F2DBEB658003327C9 /* GitInjections.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BA72AC2C9369B80045B828 /* GitInjections.swift */; }; + 84B5AA202DBEB658003327C9 /* NSObject+SentryAppSetup.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B5A91E2DBD2491003327C9 /* NSObject+SentryAppSetup.m */; }; + 84B5AA212DBEB658003327C9 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637AFDF0243B04320034958B /* ViewController.swift */; }; + 84B5AA232DBEB658003327C9 /* Sentry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 630853442440C45A00DDE4CE /* Sentry.framework */; }; + 84B5AA242DBEB658003327C9 /* SentrySwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 924D215D2C89FE2D00E0FEFD /* SentrySwiftUI.framework */; }; + 84B5AA262DBEB658003327C9 /* SampleAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 62C97D9D2CC6997E00DDA204 /* SampleAssets.xcassets */; }; + 84B5AA272DBEB658003327C9 /* Tongariro.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 7B3427FC25876DE700056519 /* Tongariro.jpg */; }; + 84B5AA282DBEB658003327C9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 637AFDF4243B04340034958B /* Main.storyboard */; }; + 84B5AA2A2DBEB658003327C9 /* Sentry.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 630853442440C45A00DDE4CE /* Sentry.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 84B5AA2B2DBEB658003327C9 /* SentrySwiftUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 924D215D2C89FE2D00E0FEFD /* SentrySwiftUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 84BA72AE2C9369B80045B828 /* GitInjections.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BA72AC2C9369B80045B828 /* GitInjections.swift */; }; + 84DE3E132DC007F100F687E6 /* macOS-Swift.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 84DE3E122DC007F100F687E6 /* macOS-Swift.xcconfig */; }; + 84DE3E1A2DC0083700F687E6 /* macOS-Swift-UITests.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 84DE3E192DC0083700F687E6 /* macOS-Swift-UITests.xcconfig */; }; + 84DE3E1C2DC0083C00F687E6 /* macOS-Swift-Sandboxed-Other.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 84DE3E1B2DC0083C00F687E6 /* macOS-Swift-Sandboxed-Other.xcconfig */; }; + 84DE3E1E2DC0083D00F687E6 /* macOS-Swift-Sandboxed.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 84DE3E1D2DC0083D00F687E6 /* macOS-Swift-Sandboxed.xcconfig */; }; + 84DE3E202DC0083E00F687E6 /* macOS-Swift-Other.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 84DE3E1F2DC0083E00F687E6 /* macOS-Swift-Other.xcconfig */; }; 924D21562C89FE2D00E0FEFD /* DiskWriteException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924D21552C89FE2D00E0FEFD /* DiskWriteException.swift */; }; 924D21682C8A01F800E0FEFD /* SentrySwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 924D215D2C89FE2D00E0FEFD /* SentrySwiftUI.framework */; }; 924D21692C8A01F800E0FEFD /* SentrySwiftUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 924D215D2C89FE2D00E0FEFD /* SentrySwiftUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -45,6 +96,90 @@ remoteGlobalIDString = 63AA759A1EB8AEF500D153DE; remoteInfo = Sentry; }; + 84B5A9082DBD1A87003327C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6308533E2440C45A00DDE4CE /* Sentry.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D833D7342D1321C100961E7A; + remoteInfo = SentrySwiftUITests; + }; + 84B5A9152DBD1AA4003327C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 637AFDE3243B04320034958B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 637AFDEA243B04320034958B; + remoteInfo = "macOS-Swift"; + }; + 84B5A91A2DBD1C09003327C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6308533E2440C45A00DDE4CE /* Sentry.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 63AA759A1EB8AEF500D153DE; + remoteInfo = Sentry; + }; + 84B5A9EA2DBD794F003327C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 637AFDE3243B04320034958B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 84B5A8F32DBD1A86003327C9; + remoteInfo = "macOS-Swift-Other"; + }; + 84B5A9EC2DBD79E7003327C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6308533E2440C45A00DDE4CE /* Sentry.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = D8199DA929376E9B0074249E; + remoteInfo = SentrySwiftUI; + }; + 84B5A9EF2DBD79F1003327C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6308533E2440C45A00DDE4CE /* Sentry.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = D8199DA929376E9B0074249E; + remoteInfo = SentrySwiftUI; + }; + 84B5A9F52DBEB648003327C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6308533E2440C45A00DDE4CE /* Sentry.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = D8199DA929376E9B0074249E; + remoteInfo = SentrySwiftUI; + }; + 84B5A9F72DBEB648003327C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6308533E2440C45A00DDE4CE /* Sentry.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 63AA759A1EB8AEF500D153DE; + remoteInfo = Sentry; + }; + 84B5AA162DBEB658003327C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6308533E2440C45A00DDE4CE /* Sentry.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = D8199DA929376E9B0074249E; + remoteInfo = SentrySwiftUI; + }; + 84B5AA182DBEB658003327C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6308533E2440C45A00DDE4CE /* Sentry.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 63AA759A1EB8AEF500D153DE; + remoteInfo = Sentry; + }; + 84B5AA332DBEB7AD003327C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 637AFDE3243B04320034958B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 84B5A9F32DBEB648003327C9; + remoteInfo = "macOS-Swift-Sandboxed"; + }; + 84B5AA352DBEB7AF003327C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 637AFDE3243B04320034958B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 84B5AA142DBEB658003327C9; + remoteInfo = "macOS-Swift-Sandboxed-Other"; + }; 924D215C2C89FE2D00E0FEFD /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6308533E2440C45A00DDE4CE /* Sentry.xcodeproj */; @@ -88,6 +223,42 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; + 84B5A9222DBD4F85003327C9 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 84B5A9212DBD4F85003327C9 /* Sentry.framework in Embed Frameworks */, + 84B5A9F22DBD7CB4003327C9 /* SentrySwiftUI.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + 84B5AA092DBEB648003327C9 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 84B5AA0A2DBEB648003327C9 /* Sentry.framework in Embed Frameworks */, + 84B5AA0B2DBEB648003327C9 /* SentrySwiftUI.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + 84B5AA292DBEB658003327C9 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 84B5AA2A2DBEB658003327C9 /* Sentry.framework in Embed Frameworks */, + 84B5AA2B2DBEB658003327C9 /* SentrySwiftUI.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -98,7 +269,6 @@ 637AFDF0243B04320034958B /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 637AFDF5243B04340034958B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 637AFDF7243B04340034958B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 637AFDF8243B04340034958B /* macOS_Swift.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOS_Swift.entitlements; sourceTree = ""; }; 637AFDFF243B07420034958B /* Sentry.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Sentry.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7B3427FC25876DE700056519 /* Tongariro.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = Tongariro.jpg; sourceTree = ""; }; 7B948A03275E459C00F04173 /* macOS-Swift-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "macOS-Swift-Bridging-Header.h"; sourceTree = ""; }; @@ -106,11 +276,26 @@ 7B948A05275E459C00F04173 /* CppSample.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CppSample.hpp; sourceTree = ""; }; 7B948A08275E498E00F04173 /* CppWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CppWrapper.h; sourceTree = ""; }; 7B948A09275E4A9900F04173 /* CppWrapper.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = CppWrapper.m; sourceTree = ""; }; + 84B5A8F42DBD1A86003327C9 /* macOS-Swift-Other.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "macOS-Swift-Other.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 84B5A90F2DBD1AA4003327C9 /* macOS-Swift-UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "macOS-Swift-UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 84B5A91D2DBD2491003327C9 /* NSObject+SentryAppSetup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSObject+SentryAppSetup.h"; sourceTree = ""; }; + 84B5A91E2DBD2491003327C9 /* NSObject+SentryAppSetup.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSObject+SentryAppSetup.m"; sourceTree = ""; }; + 84B5AA122DBEB648003327C9 /* macOS-Swift-Sandboxed.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "macOS-Swift-Sandboxed.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 84B5AA312DBEB658003327C9 /* macOS-Swift-Sandboxed-Other.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "macOS-Swift-Sandboxed-Other.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 84BA72AC2C9369B80045B828 /* GitInjections.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GitInjections.swift; sourceTree = ""; }; + 84DE3E122DC007F100F687E6 /* macOS-Swift.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "macOS-Swift.xcconfig"; sourceTree = ""; }; + 84DE3E192DC0083700F687E6 /* macOS-Swift-UITests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "macOS-Swift-UITests.xcconfig"; sourceTree = ""; }; + 84DE3E1B2DC0083C00F687E6 /* macOS-Swift-Sandboxed-Other.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "macOS-Swift-Sandboxed-Other.xcconfig"; sourceTree = ""; }; + 84DE3E1D2DC0083D00F687E6 /* macOS-Swift-Sandboxed.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "macOS-Swift-Sandboxed.xcconfig"; sourceTree = ""; }; + 84DE3E1F2DC0083E00F687E6 /* macOS-Swift-Other.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "macOS-Swift-Other.xcconfig"; sourceTree = ""; }; 924D21552C89FE2D00E0FEFD /* DiskWriteException.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiskWriteException.swift; sourceTree = ""; }; 924D216A2C8A020C00E0FEFD /* SwiftUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIView.swift; sourceTree = ""; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 84B5A9102DBD1AA4003327C9 /* macOS-Swift-UITests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = "macOS-Swift-UITests"; sourceTree = ""; }; +/* End PBXFileSystemSynchronizedRootGroup section */ + /* Begin PBXFrameworksBuildPhase section */ 637AFDE8243B04320034958B /* Frameworks */ = { isa = PBXFrameworksBuildPhase; @@ -121,6 +306,40 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 84B5A8F12DBD1A86003327C9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B5A9202DBD4F85003327C9 /* Sentry.framework in Frameworks */, + 84B5A9F12DBD7CB4003327C9 /* SentrySwiftUI.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84B5A90C2DBD1AA4003327C9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84B5AA012DBEB648003327C9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B5AA022DBEB648003327C9 /* Sentry.framework in Frameworks */, + 84B5AA032DBEB648003327C9 /* SentrySwiftUI.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84B5AA222DBEB658003327C9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B5AA232DBEB658003327C9 /* Sentry.framework in Frameworks */, + 84B5AA242DBEB658003327C9 /* SentrySwiftUI.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -133,6 +352,7 @@ 924D215F2C89FE2D00E0FEFD /* SentryProfilerTests.xctest */, 924D21612C89FE2D00E0FEFD /* libSentryTestUtils.a */, 924D21632C89FE2D00E0FEFD /* SentryTestUtilsDynamic.framework */, + 84B5A9092DBD1A87003327C9 /* SentrySwiftUITests.xctest */, ); name = Products; sourceTree = ""; @@ -140,9 +360,15 @@ 637AFDE2243B04320034958B = { isa = PBXGroup; children = ( + 84DE3E122DC007F100F687E6 /* macOS-Swift.xcconfig */, + 84DE3E1F2DC0083E00F687E6 /* macOS-Swift-Other.xcconfig */, + 84DE3E1D2DC0083D00F687E6 /* macOS-Swift-Sandboxed.xcconfig */, + 84DE3E1B2DC0083C00F687E6 /* macOS-Swift-Sandboxed-Other.xcconfig */, + 84DE3E192DC0083700F687E6 /* macOS-Swift-UITests.xcconfig */, + 84B5A9232DBD5068003327C9 /* Shared */, 84BA72AD2C9369B80045B828 /* Shared */, 6308533E2440C45A00DDE4CE /* Sentry.xcodeproj */, - 637AFDED243B04320034958B /* macOS-Swift */, + 84B5A9102DBD1AA4003327C9 /* macOS-Swift-UITests */, 637AFDEC243B04320034958B /* Products */, 637AFDFE243B07420034958B /* Frameworks */, ); @@ -152,37 +378,42 @@ isa = PBXGroup; children = ( 637AFDEB243B04320034958B /* macOS-Swift.app */, + 84B5A8F42DBD1A86003327C9 /* macOS-Swift-Other.app */, + 84B5A90F2DBD1AA4003327C9 /* macOS-Swift-UITests.xctest */, + 84B5AA122DBEB648003327C9 /* macOS-Swift-Sandboxed.app */, + 84B5AA312DBEB658003327C9 /* macOS-Swift-Sandboxed-Other.app */, ); name = Products; sourceTree = ""; }; - 637AFDED243B04320034958B /* macOS-Swift */ = { + 637AFDFE243B07420034958B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 637AFDFF243B07420034958B /* Sentry.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 84B5A9232DBD5068003327C9 /* Shared */ = { isa = PBXGroup; children = ( + 637AFDF7243B04340034958B /* Info.plist */, + 62C97D9D2CC6997E00DDA204 /* SampleAssets.xcassets */, + 7B3427FC25876DE700056519 /* Tongariro.jpg */, + 7B948A03275E459C00F04173 /* macOS-Swift-Bridging-Header.h */, 924D216A2C8A020C00E0FEFD /* SwiftUIView.swift */, - 924D21552C89FE2D00E0FEFD /* DiskWriteException.swift */, - 637AFDEE243B04320034958B /* AppDelegate.swift */, - 637AFDF0243B04320034958B /* ViewController.swift */, 7B948A08275E498E00F04173 /* CppWrapper.h */, 7B948A09275E4A9900F04173 /* CppWrapper.m */, 7B948A05275E459C00F04173 /* CppSample.hpp */, 7B948A04275E459C00F04173 /* CppSample.cpp */, - 7B948A03275E459C00F04173 /* macOS-Swift-Bridging-Header.h */, - 7B3427FC25876DE700056519 /* Tongariro.jpg */, 637AFDF4243B04340034958B /* Main.storyboard */, - 62C97D9D2CC6997E00DDA204 /* SampleAssets.xcassets */, - 637AFDF7243B04340034958B /* Info.plist */, - 637AFDF8243B04340034958B /* macOS_Swift.entitlements */, - ); - path = "macOS-Swift"; - sourceTree = ""; - }; - 637AFDFE243B07420034958B /* Frameworks */ = { - isa = PBXGroup; - children = ( - 637AFDFF243B07420034958B /* Sentry.framework */, + 924D21552C89FE2D00E0FEFD /* DiskWriteException.swift */, + 637AFDEE243B04320034958B /* AppDelegate.swift */, + 637AFDF0243B04320034958B /* ViewController.swift */, + 84B5A91D2DBD2491003327C9 /* NSObject+SentryAppSetup.h */, + 84B5A91E2DBD2491003327C9 /* NSObject+SentryAppSetup.m */, ); - name = Frameworks; + path = Shared; sourceTree = ""; }; 84BA72AD2C9369B80045B828 /* Shared */ = { @@ -211,6 +442,7 @@ buildRules = ( ); dependencies = ( + 84B5A9ED2DBD79E7003327C9 /* PBXTargetDependency */, 6308534D2440C5F500DDE4CE /* PBXTargetDependency */, ); name = "macOS-Swift"; @@ -218,13 +450,105 @@ productReference = 637AFDEB243B04320034958B /* macOS-Swift.app */; productType = "com.apple.product-type.application"; }; + 84B5A8F32DBD1A86003327C9 /* macOS-Swift-Other */ = { + isa = PBXNativeTarget; + buildConfigurationList = 84B5A90A2DBD1A87003327C9 /* Build configuration list for PBXNativeTarget "macOS-Swift-Other" */; + buildPhases = ( + 84B5A8F02DBD1A86003327C9 /* Sources */, + 84B5A8F12DBD1A86003327C9 /* Frameworks */, + 84B5A8F22DBD1A86003327C9 /* Resources */, + 84B5A9222DBD4F85003327C9 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 84B5A9F02DBD79F1003327C9 /* PBXTargetDependency */, + 84B5A91B2DBD1C09003327C9 /* PBXTargetDependency */, + ); + name = "macOS-Swift-Other"; + packageProductDependencies = ( + ); + productName = "macOS-Swift-Other"; + productReference = 84B5A8F42DBD1A86003327C9 /* macOS-Swift-Other.app */; + productType = "com.apple.product-type.application"; + }; + 84B5A90E2DBD1AA4003327C9 /* macOS-Swift-UITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 84B5A9172DBD1AA4003327C9 /* Build configuration list for PBXNativeTarget "macOS-Swift-UITests" */; + buildPhases = ( + 84B5A90B2DBD1AA4003327C9 /* Sources */, + 84B5A90C2DBD1AA4003327C9 /* Frameworks */, + 84B5A90D2DBD1AA4003327C9 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 84B5AA362DBEB7AF003327C9 /* PBXTargetDependency */, + 84B5AA342DBEB7AD003327C9 /* PBXTargetDependency */, + 84B5A9EB2DBD794F003327C9 /* PBXTargetDependency */, + 84B5A9162DBD1AA4003327C9 /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 84B5A9102DBD1AA4003327C9 /* macOS-Swift-UITests */, + ); + name = "macOS-Swift-UITests"; + packageProductDependencies = ( + ); + productName = "macOS-Swift-UITests"; + productReference = 84B5A90F2DBD1AA4003327C9 /* macOS-Swift-UITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; + 84B5A9F32DBEB648003327C9 /* macOS-Swift-Sandboxed */ = { + isa = PBXNativeTarget; + buildConfigurationList = 84B5AA0D2DBEB648003327C9 /* Build configuration list for PBXNativeTarget "macOS-Swift-Sandboxed" */; + buildPhases = ( + 84B5A9F82DBEB648003327C9 /* Sources */, + 84B5AA012DBEB648003327C9 /* Frameworks */, + 84B5AA042DBEB648003327C9 /* Inject Git information into Info.plist */, + 84B5AA052DBEB648003327C9 /* Resources */, + 84B5AA092DBEB648003327C9 /* Embed Frameworks */, + 84B5AA0C2DBEB648003327C9 /* Reset Git fields in Info.plist */, + ); + buildRules = ( + ); + dependencies = ( + 84B5A9F42DBEB648003327C9 /* PBXTargetDependency */, + 84B5A9F62DBEB648003327C9 /* PBXTargetDependency */, + ); + name = "macOS-Swift-Sandboxed"; + productName = "macOS-Swift"; + productReference = 84B5AA122DBEB648003327C9 /* macOS-Swift-Sandboxed.app */; + productType = "com.apple.product-type.application"; + }; + 84B5AA142DBEB658003327C9 /* macOS-Swift-Sandboxed-Other */ = { + isa = PBXNativeTarget; + buildConfigurationList = 84B5AA2C2DBEB658003327C9 /* Build configuration list for PBXNativeTarget "macOS-Swift-Sandboxed-Other" */; + buildPhases = ( + 84B5AA192DBEB658003327C9 /* Sources */, + 84B5AA222DBEB658003327C9 /* Frameworks */, + 84B5AA252DBEB658003327C9 /* Resources */, + 84B5AA292DBEB658003327C9 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 84B5AA152DBEB658003327C9 /* PBXTargetDependency */, + 84B5AA172DBEB658003327C9 /* PBXTargetDependency */, + ); + name = "macOS-Swift-Sandboxed-Other"; + packageProductDependencies = ( + ); + productName = "macOS-Swift-Other"; + productReference = 84B5AA312DBEB658003327C9 /* macOS-Swift-Sandboxed-Other.app */; + productType = "com.apple.product-type.application"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 637AFDE3243B04320034958B /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1140; + LastSwiftUpdateCheck = 1620; LastUpgradeCheck = 1200; ORGANIZATIONNAME = Sentry; TargetAttributes = { @@ -232,6 +556,13 @@ CreatedOnToolsVersion = 11.4; LastSwiftMigration = 1310; }; + 84B5A8F32DBD1A86003327C9 = { + CreatedOnToolsVersion = 16.2; + }; + 84B5A90E2DBD1AA4003327C9 = { + CreatedOnToolsVersion = 16.2; + TestTargetID = 637AFDEA243B04320034958B; + }; }; }; buildConfigurationList = 637AFDE6243B04320034958B /* Build configuration list for PBXProject "macOS-Swift" */; @@ -254,6 +585,10 @@ projectRoot = ""; targets = ( 637AFDEA243B04320034958B /* macOS-Swift */, + 84B5A8F32DBD1A86003327C9 /* macOS-Swift-Other */, + 84B5A90E2DBD1AA4003327C9 /* macOS-Swift-UITests */, + 84B5A9F32DBEB648003327C9 /* macOS-Swift-Sandboxed */, + 84B5AA142DBEB658003327C9 /* macOS-Swift-Sandboxed-Other */, ); }; /* End PBXProject section */ @@ -273,6 +608,13 @@ remoteRef = 630853452440C45A00DDE4CE /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 84B5A9092DBD1A87003327C9 /* SentrySwiftUITests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = SentrySwiftUITests.xctest; + remoteRef = 84B5A9082DBD1A87003327C9 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 924D215D2C89FE2D00E0FEFD /* SentrySwiftUI.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; @@ -314,9 +656,87 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 84B5A8F22DBD1A86003327C9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B5A9E92DBD76A5003327C9 /* SampleAssets.xcassets in Resources */, + 84B5A9E82DBD7689003327C9 /* Tongariro.jpg in Resources */, + 84B5A9262DBD5099003327C9 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84B5A90D2DBD1AA4003327C9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84DE3E1C2DC0083C00F687E6 /* macOS-Swift-Sandboxed-Other.xcconfig in Resources */, + 84DE3E202DC0083E00F687E6 /* macOS-Swift-Other.xcconfig in Resources */, + 84DE3E1A2DC0083700F687E6 /* macOS-Swift-UITests.xcconfig in Resources */, + 84DE3E1E2DC0083D00F687E6 /* macOS-Swift-Sandboxed.xcconfig in Resources */, + 84DE3E132DC007F100F687E6 /* macOS-Swift.xcconfig in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84B5AA052DBEB648003327C9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B5AA062DBEB648003327C9 /* SampleAssets.xcassets in Resources */, + 84B5AA072DBEB648003327C9 /* Tongariro.jpg in Resources */, + 84B5AA082DBEB648003327C9 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84B5AA252DBEB658003327C9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B5AA262DBEB658003327C9 /* SampleAssets.xcassets in Resources */, + 84B5AA272DBEB658003327C9 /* Tongariro.jpg in Resources */, + 84B5AA282DBEB658003327C9 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 84B5AA042DBEB648003327C9 /* Inject Git information into Info.plist */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Inject Git information into Info.plist"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "../Shared/inject-git-info.sh\n"; + }; + 84B5AA0C2DBEB648003327C9 /* Reset Git fields in Info.plist */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Reset Git fields in Info.plist"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "../Shared/reset-git-info.sh\n"; + }; 84BA725E2C9367780045B828 /* Inject Git information into Info.plist */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -366,22 +786,130 @@ 7B948A06275E459C00F04173 /* CppSample.cpp in Sources */, 637AFDEF243B04320034958B /* AppDelegate.swift in Sources */, 84BA72AE2C9369B80045B828 /* GitInjections.swift in Sources */, + 84B5A91F2DBD2491003327C9 /* NSObject+SentryAppSetup.m in Sources */, 7B948A0A275E4A9900F04173 /* CppWrapper.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 6308534D2440C5F500DDE4CE /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Sentry; - targetProxy = 6308534C2440C5F500DDE4CE /* PBXContainerItemProxy */; + 84B5A8F02DBD1A86003327C9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B5A9292DBD50F5003327C9 /* CppSample.cpp in Sources */, + 84B5A92B2DBD5125003327C9 /* SwiftUIView.swift in Sources */, + 84B5A92A2DBD50F5003327C9 /* CppWrapper.m in Sources */, + 84B5A9282DBD50D0003327C9 /* DiskWriteException.swift in Sources */, + 84B5A9242DBD5082003327C9 /* AppDelegate.swift in Sources */, + 84B5A9272DBD50B9003327C9 /* GitInjections.swift in Sources */, + 84B5A92C2DBD51DD003327C9 /* NSObject+SentryAppSetup.m in Sources */, + 84B5A9252DBD5082003327C9 /* ViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 637AFDF4243B04340034958B /* Main.storyboard */ = { + 84B5A90B2DBD1AA4003327C9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84B5A9F82DBEB648003327C9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B5A9F92DBEB648003327C9 /* ViewController.swift in Sources */, + 84B5A9FA2DBEB648003327C9 /* DiskWriteException.swift in Sources */, + 84B5A9FB2DBEB648003327C9 /* SwiftUIView.swift in Sources */, + 84B5A9FC2DBEB648003327C9 /* CppSample.cpp in Sources */, + 84B5A9FD2DBEB648003327C9 /* AppDelegate.swift in Sources */, + 84B5A9FE2DBEB648003327C9 /* GitInjections.swift in Sources */, + 84B5A9FF2DBEB648003327C9 /* NSObject+SentryAppSetup.m in Sources */, + 84B5AA002DBEB648003327C9 /* CppWrapper.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84B5AA192DBEB658003327C9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B5AA1A2DBEB658003327C9 /* CppSample.cpp in Sources */, + 84B5AA1B2DBEB658003327C9 /* SwiftUIView.swift in Sources */, + 84B5AA1C2DBEB658003327C9 /* CppWrapper.m in Sources */, + 84B5AA1D2DBEB658003327C9 /* DiskWriteException.swift in Sources */, + 84B5AA1E2DBEB658003327C9 /* AppDelegate.swift in Sources */, + 84B5AA1F2DBEB658003327C9 /* GitInjections.swift in Sources */, + 84B5AA202DBEB658003327C9 /* NSObject+SentryAppSetup.m in Sources */, + 84B5AA212DBEB658003327C9 /* ViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 6308534D2440C5F500DDE4CE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Sentry; + targetProxy = 6308534C2440C5F500DDE4CE /* PBXContainerItemProxy */; + }; + 84B5A9162DBD1AA4003327C9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 637AFDEA243B04320034958B /* macOS-Swift */; + targetProxy = 84B5A9152DBD1AA4003327C9 /* PBXContainerItemProxy */; + }; + 84B5A91B2DBD1C09003327C9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Sentry; + targetProxy = 84B5A91A2DBD1C09003327C9 /* PBXContainerItemProxy */; + }; + 84B5A9EB2DBD794F003327C9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 84B5A8F32DBD1A86003327C9 /* macOS-Swift-Other */; + targetProxy = 84B5A9EA2DBD794F003327C9 /* PBXContainerItemProxy */; + }; + 84B5A9ED2DBD79E7003327C9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SentrySwiftUI; + targetProxy = 84B5A9EC2DBD79E7003327C9 /* PBXContainerItemProxy */; + }; + 84B5A9F02DBD79F1003327C9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SentrySwiftUI; + targetProxy = 84B5A9EF2DBD79F1003327C9 /* PBXContainerItemProxy */; + }; + 84B5A9F42DBEB648003327C9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SentrySwiftUI; + targetProxy = 84B5A9F52DBEB648003327C9 /* PBXContainerItemProxy */; + }; + 84B5A9F62DBEB648003327C9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Sentry; + targetProxy = 84B5A9F72DBEB648003327C9 /* PBXContainerItemProxy */; + }; + 84B5AA152DBEB658003327C9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SentrySwiftUI; + targetProxy = 84B5AA162DBEB658003327C9 /* PBXContainerItemProxy */; + }; + 84B5AA172DBEB658003327C9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Sentry; + targetProxy = 84B5AA182DBEB658003327C9 /* PBXContainerItemProxy */; + }; + 84B5AA342DBEB7AD003327C9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 84B5A9F32DBEB648003327C9 /* macOS-Swift-Sandboxed */; + targetProxy = 84B5AA332DBEB7AD003327C9 /* PBXContainerItemProxy */; + }; + 84B5AA362DBEB7AF003327C9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 84B5AA142DBEB658003327C9 /* macOS-Swift-Sandboxed-Other */; + targetProxy = 84B5AA352DBEB7AF003327C9 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 637AFDF4243B04340034958B /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 637AFDF5243B04340034958B /* Base */, @@ -512,20 +1040,15 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = "macOS-Swift/macOS_Swift.entitlements"; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 97JCY7859U; - ENABLE_HARDENED_RUNTIME = YES; - INFOPLIST_FILE = "macOS-Swift/Info.plist"; + INFOPLIST_FILE = Shared/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "macOS-Swift/macOS-Swift-Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; @@ -536,24 +1059,546 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = "macOS-Swift/macOS_Swift.entitlements"; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 97JCY7859U; - ENABLE_HARDENED_RUNTIME = YES; - INFOPLIST_FILE = "macOS-Swift/Info.plist"; + INFOPLIST_FILE = Shared/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "macOS-Swift/macOS-Swift-Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = Release; }; + 84B5A9002DBD1A87003327C9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + GCC_C_LANGUAGE_STANDARD = gnu17; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-Other"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 84B5A9012DBD1A87003327C9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + GCC_C_LANGUAGE_STANDARD = gnu17; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-Other"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 84B5A9182DBD1AA4003327C9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CURRENT_PROJECT_VERSION = 1; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-UITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_TARGET_NAME = "macOS-Swift"; + }; + name = Debug; + }; + 84B5A9192DBD1AA4003327C9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CURRENT_PROJECT_VERSION = 1; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-UITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_TARGET_NAME = "macOS-Swift"; + }; + name = Release; + }; + 84B5A92D2DBD6B24003327C9 /* TestCI */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "c++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = TestCI; + }; + 84B5A92E2DBD6B24003327C9 /* TestCI */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 84DE3E122DC007F100F687E6 /* macOS-Swift.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = TestCI; + }; + 84B5A92F2DBD6B24003327C9 /* TestCI */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 84DE3E1F2DC0083E00F687E6 /* macOS-Swift-Other.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + GCC_C_LANGUAGE_STANDARD = gnu17; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-Other"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = TestCI; + }; + 84B5A9302DBD6B24003327C9 /* TestCI */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 84DE3E192DC0083700F687E6 /* macOS-Swift-UITests.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CURRENT_PROJECT_VERSION = 1; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-UITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_TARGET_NAME = "macOS-Swift"; + }; + name = TestCI; + }; + 84B5A9312DBD6B26003327C9 /* Test */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "c++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Test; + }; + 84B5A9322DBD6B26003327C9 /* Test */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + GCC_OPTIMIZATION_LEVEL = 0; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Test; + }; + 84B5A9332DBD6B26003327C9 /* Test */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_OPTIMIZATION_LEVEL = 0; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-Other"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Test; + }; + 84B5A9342DBD6B26003327C9 /* Test */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CURRENT_PROJECT_VERSION = 1; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = "TEST=1"; + GENERATE_INFOPLIST_FILE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-UITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_TARGET_NAME = "macOS-Swift"; + }; + name = Test; + }; + 84B5AA0E2DBEB648003327C9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + ENABLE_APP_SANDBOX = YES; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-Sandboxed"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 84B5AA0F2DBEB648003327C9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + ENABLE_APP_SANDBOX = YES; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-Sandboxed"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 84B5AA102DBEB648003327C9 /* Test */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + ENABLE_APP_SANDBOX = YES; + GCC_OPTIMIZATION_LEVEL = 0; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-Sandboxed"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Test; + }; + 84B5AA112DBEB648003327C9 /* TestCI */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 84DE3E1D2DC0083D00F687E6 /* macOS-Swift-Sandboxed.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + ENABLE_APP_SANDBOX = YES; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-Sandboxed"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = TestCI; + }; + 84B5AA2D2DBEB658003327C9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_APP_SANDBOX = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-Sandboxed-Other"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 84B5AA2E2DBEB658003327C9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_APP_SANDBOX = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-Sandboxed-Other"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 84B5AA2F2DBEB658003327C9 /* Test */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_APP_SANDBOX = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_OPTIMIZATION_LEVEL = 0; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-Sandboxed-Other"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Test; + }; + 84B5AA302DBEB658003327C9 /* TestCI */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 84DE3E1B2DC0083C00F687E6 /* macOS-Swift-Sandboxed-Other.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_APP_SANDBOX = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + INFOPLIST_FILE = Shared/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.macOS-Swift-Sandboxed-Other"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Shared/macOS-Swift-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = TestCI; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -562,6 +1607,8 @@ buildConfigurations = ( 637AFDF9243B04340034958B /* Debug */, 637AFDFA243B04340034958B /* Release */, + 84B5A9312DBD6B26003327C9 /* Test */, + 84B5A92D2DBD6B24003327C9 /* TestCI */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -571,6 +1618,52 @@ buildConfigurations = ( 637AFDFC243B04340034958B /* Debug */, 637AFDFD243B04340034958B /* Release */, + 84B5A9322DBD6B26003327C9 /* Test */, + 84B5A92E2DBD6B24003327C9 /* TestCI */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 84B5A90A2DBD1A87003327C9 /* Build configuration list for PBXNativeTarget "macOS-Swift-Other" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84B5A9002DBD1A87003327C9 /* Debug */, + 84B5A9012DBD1A87003327C9 /* Release */, + 84B5A9332DBD6B26003327C9 /* Test */, + 84B5A92F2DBD6B24003327C9 /* TestCI */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 84B5A9172DBD1AA4003327C9 /* Build configuration list for PBXNativeTarget "macOS-Swift-UITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84B5A9182DBD1AA4003327C9 /* Debug */, + 84B5A9192DBD1AA4003327C9 /* Release */, + 84B5A9342DBD6B26003327C9 /* Test */, + 84B5A9302DBD6B24003327C9 /* TestCI */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 84B5AA0D2DBEB648003327C9 /* Build configuration list for PBXNativeTarget "macOS-Swift-Sandboxed" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84B5AA0E2DBEB648003327C9 /* Debug */, + 84B5AA0F2DBEB648003327C9 /* Release */, + 84B5AA102DBEB648003327C9 /* Test */, + 84B5AA112DBEB648003327C9 /* TestCI */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 84B5AA2C2DBEB658003327C9 /* Build configuration list for PBXNativeTarget "macOS-Swift-Sandboxed-Other" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84B5AA2D2DBEB658003327C9 /* Debug */, + 84B5AA2E2DBEB658003327C9 /* Release */, + 84B5AA2F2DBEB658003327C9 /* Test */, + 84B5AA302DBEB658003327C9 /* TestCI */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Samples/macOS-Swift/macOS-Swift.xcodeproj/xcshareddata/xcschemes/macOS-Swift.xcscheme b/Samples/macOS-Swift/macOS-Swift.xcodeproj/xcshareddata/xcschemes/macOS-Swift.xcscheme index d6f7f2ad178..3c77b6cf71c 100644 --- a/Samples/macOS-Swift/macOS-Swift.xcodeproj/xcshareddata/xcschemes/macOS-Swift.xcscheme +++ b/Samples/macOS-Swift/macOS-Swift.xcodeproj/xcshareddata/xcschemes/macOS-Swift.xcscheme @@ -23,7 +23,7 @@ @@ -33,11 +33,24 @@ default = "YES"> + + + + + + - - - - com.apple.security.app-sandbox - - com.apple.security.files.user-selected.read-only - - com.apple.security.network.client - - - diff --git a/SentryTestUtils/SentryFileManager+Test.h b/SentryTestUtils/SentryFileManager+Test.h index eb977082161..152314d86c6 100644 --- a/SentryTestUtils/SentryFileManager+Test.h +++ b/SentryTestUtils/SentryFileManager+Test.h @@ -4,6 +4,9 @@ NS_ASSUME_NONNULL_BEGIN BOOL isErrorPathTooLong(NSError *error); BOOL createDirectoryIfNotExists(NSString *path, NSError **error); +NSString *_Nullable sentryGetScopedCachesDirectory(NSString *cachesDirectory); +NSString *_Nullable sentryBuildScopedCachesDirectoryPath(NSString *cachesDirectory, + BOOL isSandboxed, NSString *_Nullable bundleIdentifier, NSString *_Nullable lastPathComponent); SENTRY_EXTERN NSURL *launchProfileConfigFileURL(void); SENTRY_EXTERN NSURL *_Nullable sentryLaunchConfigFileURL; diff --git a/Sources/Sentry/Profiling/SentryProfilerTestHelpers.m b/Sources/Sentry/Profiling/SentryProfilerTestHelpers.m index a06da63d3a6..6ba57d70d60 100644 --- a/Sources/Sentry/Profiling/SentryProfilerTestHelpers.m +++ b/Sources/Sentry/Profiling/SentryProfilerTestHelpers.m @@ -27,7 +27,7 @@ sentry_writeProfileFile(NSData *JSONData, BOOL continuous) { NSFileManager *fm = [NSFileManager defaultManager]; - NSString *testProfileDirPath = [sentryStaticCachesPath() + NSString *testProfileDirPath = [sentryStaticBasePath() stringByAppendingPathComponent:continuous ? @"continuous-profiles" : @"trace-profiles"]; if (![fm fileExistsAtPath:testProfileDirPath]) { diff --git a/Sources/Sentry/SentryFileManager.m b/Sources/Sentry/SentryFileManager.m index 64088c847e1..27da7f1e84f 100644 --- a/Sources/Sentry/SentryFileManager.m +++ b/Sources/Sentry/SentryFileManager.m @@ -634,23 +634,155 @@ - (BOOL)isDirectory:(NSString *)path return [NSFileManager.defaultManager fileExistsAtPath:path isDirectory:&isDir] && isDir; } +/** + * @note This method must be statically accessible because it will be called during app launch, + * before any instance of ``SentryFileManager`` exists, and so wouldn't be able to access this path + * from an objc property on it like the other paths. + */ NSString *_Nullable sentryStaticCachesPath(void) { static NSString *_Nullable sentryStaticCachesPath = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - NSString *cachesDirectory + // We request the users cache directory from Foundation. + // For iOS apps and macOS apps with sandboxing, this path will be scoped for the current + // app. For macOS apps without sandboxing, this path is not scoped and will be shared + // between all apps. + NSString *_Nullable cachesDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) .firstObject; if (cachesDirectory == nil) { SENTRY_LOG_WARN(@"No caches directory location reported."); return; } - sentryStaticCachesPath = [cachesDirectory stringByAppendingPathComponent:@"io.sentry"]; + + // We need to ensure our own sandbox so that this path is not shared between other apps on + // the same system. + NSString *_Nullable sandboxedCachesDirectory + = sentryGetScopedCachesDirectory(cachesDirectory); + if (!sandboxedCachesDirectory) { + SENTRY_LOG_WARN(@"Failed to get scoped static caches directory."); + return; + } + sentryStaticCachesPath = sandboxedCachesDirectory; + SENTRY_LOG_DEBUG(@"Using static cache directory: %@", sentryStaticCachesPath); }); return sentryStaticCachesPath; } +NSString *_Nullable sentryGetScopedCachesDirectory(NSString *cachesDirectory) +{ +#if !TARGET_OS_OSX + // iOS apps are always sandboxed, therefore we can just early-return with the provided caches + // directory. + return cachesDirectory; +#else + + // For macOS apps, we need to ensure our own sandbox so that this path is not shared between + // all apps that ship the SDK. + + // We can not use the SentryNSProcessInfoWrapper here because this method is called before + // the SentryDependencyContainer is initialized. + NSProcessInfo *processInfo = [NSProcessInfo processInfo]; + + // Only apps running in a sandboxed environment have the `APP_SANDBOX_CONTAINER_ID` set as a + // process environment variable. Reference implementation: + // https://github.com/realm/realm-js/blob/a03127726939f08f608edbdb2341605938f25708/packages/realm/binding/apple/platform.mm#L58-L74 + BOOL isSandboxed = processInfo.environment[@"APP_SANDBOX_CONTAINER_ID"] != nil; + + // The bundle identifier is used to create a unique cache directory for the app. + // If the bundle identifier is not available, we use the name of the executable. + // Note: `SentryCrash.getBundleName` is using `CFBundleName` to create a scoped directory. + // That value can be absent, therefore we use a more stable approach here. + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + NSString *lastPathComponent = [[[NSBundle mainBundle] executablePath] lastPathComponent]; + + // Due to `NSProcessInfo` and `NSBundle` not being mockable in unit tests, we extract only the + // logic to a separate function. + return sentryBuildScopedCachesDirectoryPath( + cachesDirectory, isSandboxed, bundleIdentifier, lastPathComponent); +#endif +} + +NSString *_Nullable sentryBuildScopedCachesDirectoryPath(NSString *cachesDirectory, + BOOL isSandboxed, NSString *_Nullable bundleIdentifier, NSString *_Nullable lastPathComponent) +{ + // If the app is sandboxed, we can just use the provided caches directory. + if (isSandboxed) { + return cachesDirectory; + } + + // If the macOS app is not sandboxed, we need to manually create a scoped cache + // directory. The cache path must be unique an stable over app launches, therefore we + // can not use any changing identifier. + SENTRY_LOG_DEBUG( + @"App is not sandboxed, extending default cache directory with bundle identifier."); + + if (lastPathComponent.length > 0) { + // If we've already used a scoped cache directory path with the executable name in the past + // due to a nil or zero-length bundle identifier, we'll stick with that regardless of what + // is in the app identifier now. + NSString *executableNameBasedPath = + [cachesDirectory stringByAppendingPathComponent:lastPathComponent]; + BOOL isDirectory = NO; + if ([NSFileManager.defaultManager fileExistsAtPath:executableNameBasedPath + isDirectory:&isDirectory] + && isDirectory) { + return executableNameBasedPath; + } + } + + NSString *_Nullable identifier = bundleIdentifier; + if (identifier == nil) { + SENTRY_LOG_WARN(@"No bundle identifier found, using main bundle executable name."); + identifier = lastPathComponent; + } else if (identifier.length == 0) { + SENTRY_LOG_WARN(@"Bundle identifier exists but is zero length, using main bundle " + @"executable name."); + identifier = lastPathComponent; + } + + // If neither the bundle identifier nor the executable name are available, we can't + // create a unique and stable cache directory. + // We do not fall back to any default path, because it could be shared with other apps + // and cause leaks impacting other apps. + if (identifier == nil) { + SENTRY_LOG_ERROR(@"No bundle identifier found, cannot create cache directory."); + return nil; + } + + // It's unlikely that the executable name will be zero length, but we'll cover this case anyways + if (identifier.length == 0) { + SENTRY_LOG_ERROR(@"Executable name was zero length."); + return nil; + } + + return [cachesDirectory stringByAppendingPathComponent:identifier]; +} + +NSString *_Nullable sentryStaticBasePath(void) +{ + static NSString *_Nullable sentryStaticBasePath = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *cachesDirectory = sentryStaticCachesPath(); + if (cachesDirectory == nil) { + SENTRY_LOG_WARN(@"No caches directory location reported."); + return; + } + sentryStaticBasePath = [cachesDirectory stringByAppendingPathComponent:@"io.sentry"]; + }); + return sentryStaticBasePath; +} + +#if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) +void +removeBasePath(void) +{ + _non_thread_safe_removeFileAtPath(sentryStaticBasePath()); +} +#endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) + #pragma mark - Profiling #if SENTRY_TARGET_PROFILING_SUPPORTED @@ -661,13 +793,20 @@ - (BOOL)isDirectory:(NSString *)path { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - NSString *cachesPath = sentryStaticCachesPath(); - if (cachesPath == nil) { + NSString *basePath = sentryStaticBasePath(); + if (basePath == nil) { SENTRY_LOG_WARN(@"No location available to write a launch profiling config."); return; } + NSError *error; + if (!createDirectoryIfNotExists(basePath, &error)) { + SENTRY_LOG_ERROR( + @"Can't create base path to store launch profile config file: %@", error); + return; + } sentryLaunchConfigFileURL = - [NSURL fileURLWithPath:[cachesPath stringByAppendingPathComponent:@"profileLaunch"]]; + [NSURL fileURLWithPath:[basePath stringByAppendingPathComponent:@"profileLaunch"]]; + SENTRY_LOG_DEBUG(@"Launch profile config file URL: %@", sentryLaunchConfigFileURL); }); return sentryLaunchConfigFileURL; } diff --git a/Sources/Sentry/SentryProfiler.mm b/Sources/Sentry/SentryProfiler.mm index 14abb4aea2e..61306da48e5 100644 --- a/Sources/Sentry/SentryProfiler.mm +++ b/Sources/Sentry/SentryProfiler.mm @@ -151,13 +151,7 @@ + (void)load // to remove stale versions of the file before it gets used to potentially start a launch // profile that shouldn't have started, so we check here for this if ([NSProcessInfo.processInfo.arguments containsObject:@"--io.sentry.wipe-data"]) { - const auto caches = [NSSearchPathForDirectoriesInDomains( - NSCachesDirectory, NSUserDomainMask, YES) firstObject]; - if ([NSFileManager.defaultManager fileExistsAtPath:caches]) { - NSError *error; - SENTRY_ASSERT([NSFileManager.defaultManager removeItemAtPath:caches error:&error], - @"Failed to wipe application support: %@", error); - } + removeBasePath(); } # endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) sentry_startLaunchProfile(); diff --git a/Sources/Sentry/include/SentryFileManager.h b/Sources/Sentry/include/SentryFileManager.h index 24ce0e42db1..19b99a60de8 100644 --- a/Sources/Sentry/include/SentryFileManager.h +++ b/Sources/Sentry/include/SentryFileManager.h @@ -120,7 +120,8 @@ BOOL createDirectoryIfNotExists(NSString *path, NSError **error); /** * Path for a default directory Sentry can use in the app sandbox' caches directory. * @note This method must be statically accessible because it will be called during app launch, - * before any instance of @c SentryFileManager exists, and so wouldn't be able to access this path + * before any instance of @c SentryFileManager exists, and so wouldn't be able to access this path. + * @note For unsandboxed macOS apps, the path has the form @c ~/Library/Caches/ . * from an objc property on it like the other paths. It also cannot use * @c SentryOptions.cacheDirectoryPath since this can be called before * @c SentrySDK.startWithOptions . @@ -161,6 +162,12 @@ SENTRY_EXTERN void writeAppLaunchProfilingConfigFile( */ SENTRY_EXTERN void removeAppLaunchProfilingConfigFile(void); +SENTRY_EXTERN NSString *_Nullable sentryStaticBasePath(void); + +# if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) +SENTRY_EXTERN void removeBasePath(void); +# endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) + #endif // SENTRY_TARGET_PROFILING_SUPPORTED @end diff --git a/Tests/SentryTests/Helper/SentryFileManagerTests.swift b/Tests/SentryTests/Helper/SentryFileManagerTests.swift index 4900a191ed0..5d43452acbc 100644 --- a/Tests/SentryTests/Helper/SentryFileManagerTests.swift +++ b/Tests/SentryTests/Helper/SentryFileManagerTests.swift @@ -1209,6 +1209,120 @@ extension SentryFileManagerTests { // set the original value back so other tests don't crash sentryLaunchConfigFileURL = (originalURL as NSURL) } + + func testSentryGetScopedCachesDirectory_targetIsNotMacOS_shouldReturnSamePath() throws { + guard #unavailable(macOS 10.15) else { + throw XCTSkip("Test is disabled for this OS version") + } + + // -- Arrange -- + let cachesDirectoryPath = "some/path/to/caches" + + // -- Act -- + let result = sentryGetScopedCachesDirectory(cachesDirectoryPath) + + // -- Assert + XCTAssertEqual(result, cachesDirectoryPath) + } + + func testSentryGetScopedCachesDirectory_targetIsMacOS_shouldReturnPath() throws { + guard #available(macOS 10.15, *) else { + throw XCTSkip("Test is disabled for this OS version") + } + + // -- Arrange -- + let cachesDirectoryPath = "some/path/to/caches" + + // -- Act -- + let result = sentryGetScopedCachesDirectory(cachesDirectoryPath) + + // -- Assert + // Xcode unit tests are not sandboxed, therefore we expect it to use the bundle identifier to unique the path + // The bundle identifier will then be the xctest bundle identifier + XCTAssertEqual(result, "some/path/to/caches/com.apple.dt.xctest.tool") + } + + func testSentryBuildScopedCachesDirectoryPath_isSandboxed_shouldReturnInputPath() { + // -- Arrange -- + let cachesDirectoryPath = "some/path/to/caches" + let isSandboxed = true + let bundleIdentifier: String? = nil + let lastPathComponent: String? = nil + + // -- Act -- + let result = sentryBuildScopedCachesDirectoryPath( + cachesDirectoryPath, + isSandboxed, + bundleIdentifier, + lastPathComponent + ) + + // -- Assert -- + XCTAssertEqual(result, cachesDirectoryPath) + } + + func test_sentryBuildScopedCachesDirectoryPath_inputCombinations() { + // -- Arrange -- + for testCase: (isSandboxed: Bool, bundleIdentifier: String?, lastPathComponent: String?, expected: String?) in [ + // bundleIdentifier defined + (isSandboxed: false, bundleIdentifier: "com.example.app", lastPathComponent: "AppBinaryName", expected: "some/path/to/caches/com.example.app"), + (isSandboxed: false, bundleIdentifier: "com.example.app", lastPathComponent: "", expected: "some/path/to/caches/com.example.app"), + (isSandboxed: false, bundleIdentifier: "com.example.app", lastPathComponent: nil, expected: "some/path/to/caches/com.example.app"), + + // bundleIdentifier zero length string + (isSandboxed: false, bundleIdentifier: "", lastPathComponent: "AppBinaryName", expected: "some/path/to/caches/AppBinaryName"), + (isSandboxed: false, bundleIdentifier: "", lastPathComponent: "", expected: nil), + (isSandboxed: false, bundleIdentifier: "", lastPathComponent: nil, expected: nil), + + // bundleIdentifier nil + (isSandboxed: false, bundleIdentifier: nil, lastPathComponent: "AppBinaryName", expected: "some/path/to/caches/AppBinaryName"), + (isSandboxed: false, bundleIdentifier: nil, lastPathComponent: "", expected: nil), + (isSandboxed: false, bundleIdentifier: nil, lastPathComponent: nil, expected: nil), + + // for sandboxed scenarios, always return the original path + (isSandboxed: true, bundleIdentifier: "com.example.app", lastPathComponent: "AppBinaryName", expected: "some/path/to/caches"), + (isSandboxed: true, bundleIdentifier: "", lastPathComponent: "AppBinaryName", expected: "some/path/to/caches"), + (isSandboxed: true, bundleIdentifier: nil, lastPathComponent: "AppBinaryName", expected: "some/path/to/caches"), + (isSandboxed: true, bundleIdentifier: "com.example.app", lastPathComponent: "", expected: "some/path/to/caches"), + (isSandboxed: true, bundleIdentifier: "", lastPathComponent: "", expected: "some/path/to/caches"), + (isSandboxed: true, bundleIdentifier: nil, lastPathComponent: "", expected: "some/path/to/caches"), + (isSandboxed: true, bundleIdentifier: "com.example.app", lastPathComponent: nil, expected: "some/path/to/caches"), + (isSandboxed: true, bundleIdentifier: "", lastPathComponent: nil, expected: "some/path/to/caches"), + (isSandboxed: true, bundleIdentifier: nil, lastPathComponent: nil, expected: "some/path/to/caches") + ] { + // -- Act -- + let result = sentryBuildScopedCachesDirectoryPath( + "some/path/to/caches", + testCase.isSandboxed, + testCase.bundleIdentifier, + testCase.lastPathComponent + ) + + // -- Assert -- + XCTAssertEqual(result, testCase.expected, "Inputs: (isSandboxed: \(testCase.isSandboxed), bundleIdentifier: \(String(describing: testCase.bundleIdentifier)), lastPathComponent: \(String(describing: testCase.lastPathComponent)), expected: \(String(describing: testCase.expected))); Output: \(String(describing: result))") + } + } + + func test_sentryBuildScopedCachesDirectoryPath_afterAlreadyUsingExecutableName() throws { + // -- Arrange -- + let executableName = "MyAppBinary" + let bundleId = "com.my.app" + try FileManager.default.createDirectory(atPath: "~/some/path/to/caches/MyAppBinary", withIntermediateDirectories: true) + + // -- Act -- + let result = sentryBuildScopedCachesDirectoryPath( + "~/some/path/to/caches", + false, + bundleId, + executableName + ) + + // -- Assert -- + XCTAssertEqual(result, "~/some/path/to/caches/MyAppBinary") + + // -- Cleanup -- + try FileManager.default.removeItem(atPath: "~/some/path/to/caches/MyAppBinary") + } } // MARK: Private profiling tests diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 37b34742e8a..b10cdfeb27e 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -59,8 +59,14 @@ platform :ios do "io.sentry.cocoa.perf-test-app-plain", "io.sentry.*", "io.sentry.iOS-Benchmarking.xctrunner", - "io.sentry.cocoa.perf-test-app-sentry"], - readonly: true + "io.sentry.cocoa.perf-test-app-sentry", +# "io.sentry.macOS-Swift", +# "io.sentry.macOS-Swift-Other", +# "io.sentry.macOS-Swift-Sandboxed", +# "io.sentry.macOS-Swift-Sandboxed-Other", +# "io.sentry.macOS-Swift-UITests.xctrunner", + ], + readonly: true ) match( type: "appstore", @@ -250,6 +256,42 @@ platform :ios do result_bundle_path: "fastlane/#{result_bundle_path}" ) end + + lane :ui_tests_macos_swift do |options| + # FileUtils resolves relative paths to the `fastlane` directory, while lanes resolve relative to root. + result_bundle_path = "test_results/ui-tests-macos-swift.xcresult" + FileUtils.rm_r(result_bundle_path) if File.exist?(result_bundle_path) + + setup_ci( + force: true + ) + +# sync_code_signing( +# type: "development", +# readonly: true, +# app_identifier: [ +# "io.sentry.sample.macOS-Swift", +# "io.sentry.sample.macOS-Swift-Other", +# "io.sentry.sample.macOS-Swift-Sandboxed", +# "io.sentry.sample.macOS-Swift-Sandboxed-Other", +# "io.sentry.sample.macOS-Swift-UITests.xctrunner", +# ], +# +# # Directly cloning the branch instead of using a shallow clone fixes the rare error: +# # fatal: a branch named 'master' already exists in GitHub Action workflows. +# git_branch: "master", +# clone_branch_directly: true +# ) + + run_tests( + workspace: "Sentry.xcworkspace", + scheme: "macOS-Swift", + configuration: configuration, + xcodebuild_formatter: "xcbeautify --report junit", + result_bundle: true, + result_bundle_path: "fastlane/#{result_bundle_path}" + ) + end lane :ui_tests_ios_objc do # FileUtils resolves relative paths to the `fastlane` directory, while lanes resolve relative to root.