diff --git a/.github/workflows/test-3rd-party-integrations.yml b/.github/workflows/test-3rd-party-integrations.yml index b821bfb8591..fdab8b2f117 100644 --- a/.github/workflows/test-3rd-party-integrations.yml +++ b/.github/workflows/test-3rd-party-integrations.yml @@ -78,7 +78,7 @@ jobs: # SPM tests for all 3rd-party integrations test-integrations-spm: - name: SPM Tests | ${{matrix.integration_dir}} + name: SPM Tests (${{matrix.trait}}) | ${{matrix.integration_dir}} needs: [files-changed, build-xcframeworks] if: startsWith(github.ref, 'refs/heads/release/') == false && (github.event_name != 'pull_request' || needs.files-changed.outputs.run_3rd_party_integrations_tests_for_prs == 'true') runs-on: ["bitrise_pool_name:sequoia"] @@ -92,6 +92,7 @@ jobs: "SentryCocoaLumberjack", "SentryPulse", ] + trait: ["SentryFromBinary", "SentryFromSource"] steps: - name: Warm CoreSimulator run: xcrun simctl list runtimes -j > /dev/null 2>&1 & @@ -115,12 +116,12 @@ jobs: sed -i '' 's|\.package(url: "https://github\.com/getsentry/sentry-cocoa", from: "[^"]*")|.package(name: "sentry-cocoa", path: "../..")|g' Package.swift - name: Run SPM Tests working-directory: 3rd-party-integrations/${{matrix.integration_dir}} - run: swift test + run: swift test --traits ${{ matrix.trait }} - name: Archiving Raw Logs uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 if: ${{ failure() || cancelled() }} with: - name: raw-output-${{matrix.integration_dir}}-integration + name: raw-output-${{matrix.integration_dir}}-${{matrix.trait}}-integration path: | 3rd-party-integrations/${{matrix.integration_dir}}/.build/**/*.log - name: Run CI Diagnostics diff --git a/3rd-party-integrations/SentryCocoaLumberjack/Package.swift b/3rd-party-integrations/SentryCocoaLumberjack/Package.swift index 9bffcaa0ba6..f170ad05ffd 100644 --- a/3rd-party-integrations/SentryCocoaLumberjack/Package.swift +++ b/3rd-party-integrations/SentryCocoaLumberjack/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:6.0 +// swift-tools-version:6.1 import PackageDescription let package = Package( @@ -10,6 +10,11 @@ let package = Package( targets: ["SentryCocoaLumberjack"] ) ], + traits: [ + .default(enabledTraits: ["SentryFromBinary"]), + .init(name: "SentryFromBinary", description: "Use precompiled Sentry binary xcframeworks."), + .init(name: "SentryFromSource", description: "Build Sentry from source instead of using precompiled binaries.") + ], dependencies: [ .package(url: "https://github.com/CocoaLumberjack/CocoaLumberjack", from: "3.8.0"), .package(url: "https://github.com/getsentry/sentry-cocoa", from: "9.25.0") @@ -19,7 +24,12 @@ let package = Package( name: "SentryCocoaLumberjack", dependencies: [ .product(name: "CocoaLumberjackSwift", package: "CocoaLumberjack"), - .product(name: "Sentry", package: "sentry-cocoa") + .product(name: "Sentry", package: "sentry-cocoa", condition: .when(traits: ["SentryFromBinary"])), + .product(name: "SentrySPM", package: "sentry-cocoa", condition: .when(traits: ["SentryFromSource"])) + ], + swiftSettings: [ + .define("SENTRY_FROM_BINARY", .when(traits: ["SentryFromBinary"])), + .define("SENTRY_FROM_SOURCE", .when(traits: ["SentryFromSource"])) ] ), .testTarget( @@ -27,7 +37,12 @@ let package = Package( dependencies: [ "SentryCocoaLumberjack", .product(name: "CocoaLumberjackSwift", package: "CocoaLumberjack"), - .product(name: "Sentry", package: "sentry-cocoa") + .product(name: "Sentry", package: "sentry-cocoa", condition: .when(traits: ["SentryFromBinary"])), + .product(name: "SentrySPM", package: "sentry-cocoa", condition: .when(traits: ["SentryFromSource"])) + ], + swiftSettings: [ + .define("SENTRY_FROM_BINARY", .when(traits: ["SentryFromBinary"])), + .define("SENTRY_FROM_SOURCE", .when(traits: ["SentryFromSource"])) ] ) ] diff --git a/3rd-party-integrations/SentryCocoaLumberjack/Sources/SentryCocoaLumberjackLogger.swift b/3rd-party-integrations/SentryCocoaLumberjack/Sources/SentryCocoaLumberjackLogger.swift index 37ee42ae0ea..530fc644ca7 100644 --- a/3rd-party-integrations/SentryCocoaLumberjack/Sources/SentryCocoaLumberjackLogger.swift +++ b/3rd-party-integrations/SentryCocoaLumberjack/Sources/SentryCocoaLumberjackLogger.swift @@ -1,5 +1,9 @@ import CocoaLumberjackSwift +#if SENTRY_FROM_SOURCE +import SentrySwift +#else import Sentry +#endif /// A CocoaLumberjack logger that forwards log entries to Sentry's structured logging system. /// diff --git a/3rd-party-integrations/SentryCocoaLumberjack/Sources/SentryTraitValidation.swift b/3rd-party-integrations/SentryCocoaLumberjack/Sources/SentryTraitValidation.swift new file mode 100644 index 00000000000..98793042256 --- /dev/null +++ b/3rd-party-integrations/SentryCocoaLumberjack/Sources/SentryTraitValidation.swift @@ -0,0 +1,3 @@ +#if SENTRY_FROM_BINARY && SENTRY_FROM_SOURCE +#error("SentryFromBinary and SentryFromSource are mutually exclusive. Enable only one.") +#endif diff --git a/3rd-party-integrations/SentryCocoaLumberjack/Tests/SentryCocoaLumberjackLoggerTests.swift b/3rd-party-integrations/SentryCocoaLumberjack/Tests/SentryCocoaLumberjackLoggerTests.swift index 18a6faff399..1017bd164b2 100644 --- a/3rd-party-integrations/SentryCocoaLumberjack/Tests/SentryCocoaLumberjackLoggerTests.swift +++ b/3rd-party-integrations/SentryCocoaLumberjack/Tests/SentryCocoaLumberjackLoggerTests.swift @@ -1,6 +1,10 @@ @_spi(Private) @testable import SentryCocoaLumberjack import CocoaLumberjackSwift +#if SENTRY_FROM_SOURCE +import SentrySwift +#else import Sentry +#endif import XCTest // swiftlint:disable cyclomatic_complexity file_length type_body_length diff --git a/3rd-party-integrations/SentryPulse/Package.swift b/3rd-party-integrations/SentryPulse/Package.swift index bf2097a643c..ab4566881c8 100644 --- a/3rd-party-integrations/SentryPulse/Package.swift +++ b/3rd-party-integrations/SentryPulse/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:6.0 +// swift-tools-version:6.1 import PackageDescription let package = Package( @@ -10,6 +10,11 @@ let package = Package( targets: ["SentryPulse"] ) ], + traits: [ + .default(enabledTraits: ["SentryFromBinary"]), + .init(name: "SentryFromBinary", description: "Use precompiled Sentry binary xcframeworks."), + .init(name: "SentryFromSource", description: "Build Sentry from source instead of using precompiled binaries.") + ], dependencies: [ .package(url: "https://github.com/kean/Pulse", from: "5.0.0"), .package(url: "https://github.com/getsentry/sentry-cocoa", from: "9.25.0") @@ -19,7 +24,12 @@ let package = Package( name: "SentryPulse", dependencies: [ .product(name: "Pulse", package: "Pulse"), - .product(name: "Sentry", package: "sentry-cocoa") + .product(name: "Sentry", package: "sentry-cocoa", condition: .when(traits: ["SentryFromBinary"])), + .product(name: "SentrySPM", package: "sentry-cocoa", condition: .when(traits: ["SentryFromSource"])) + ], + swiftSettings: [ + .define("SENTRY_FROM_BINARY", .when(traits: ["SentryFromBinary"])), + .define("SENTRY_FROM_SOURCE", .when(traits: ["SentryFromSource"])) ] ), .testTarget( @@ -27,8 +37,13 @@ let package = Package( dependencies: [ "SentryPulse", .product(name: "Pulse", package: "Pulse"), - .product(name: "Sentry", package: "sentry-cocoa") + .product(name: "Sentry", package: "sentry-cocoa", condition: .when(traits: ["SentryFromBinary"])), + .product(name: "SentrySPM", package: "sentry-cocoa", condition: .when(traits: ["SentryFromSource"])) + ], + swiftSettings: [ + .define("SENTRY_FROM_BINARY", .when(traits: ["SentryFromBinary"])), + .define("SENTRY_FROM_SOURCE", .when(traits: ["SentryFromSource"])) ] - ) + ) ] ) diff --git a/3rd-party-integrations/SentryPulse/Sources/SentryPulse.swift b/3rd-party-integrations/SentryPulse/Sources/SentryPulse.swift index 7d48889fa8b..e9f80a7041d 100644 --- a/3rd-party-integrations/SentryPulse/Sources/SentryPulse.swift +++ b/3rd-party-integrations/SentryPulse/Sources/SentryPulse.swift @@ -1,6 +1,10 @@ import Combine import Pulse +#if SENTRY_FROM_SOURCE +import SentrySwift +#else import Sentry +#endif /// Automatically forwards Pulse log messages to Sentry's structured logging system. /// diff --git a/3rd-party-integrations/SentryPulse/Sources/SentryTraitValidation.swift b/3rd-party-integrations/SentryPulse/Sources/SentryTraitValidation.swift new file mode 100644 index 00000000000..98793042256 --- /dev/null +++ b/3rd-party-integrations/SentryPulse/Sources/SentryTraitValidation.swift @@ -0,0 +1,3 @@ +#if SENTRY_FROM_BINARY && SENTRY_FROM_SOURCE +#error("SentryFromBinary and SentryFromSource are mutually exclusive. Enable only one.") +#endif diff --git a/3rd-party-integrations/SentryPulse/Tests/SentryPulseTests.swift b/3rd-party-integrations/SentryPulse/Tests/SentryPulseTests.swift index 39e57e22a48..e0782fb77f4 100644 --- a/3rd-party-integrations/SentryPulse/Tests/SentryPulseTests.swift +++ b/3rd-party-integrations/SentryPulse/Tests/SentryPulseTests.swift @@ -1,6 +1,10 @@ @testable import SentryPulse import Pulse +#if SENTRY_FROM_SOURCE +import SentrySwift +#else import Sentry +#endif import XCTest // swiftlint:disable cyclomatic_complexity diff --git a/3rd-party-integrations/SentrySwiftLog/Package.swift b/3rd-party-integrations/SentrySwiftLog/Package.swift index e67d2ba1972..d025257366f 100644 --- a/3rd-party-integrations/SentrySwiftLog/Package.swift +++ b/3rd-party-integrations/SentrySwiftLog/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:6.0 +// swift-tools-version:6.1 import PackageDescription let package = Package( @@ -10,6 +10,11 @@ let package = Package( targets: ["SentrySwiftLog"] ) ], + traits: [ + .default(enabledTraits: ["SentryFromBinary"]), + .init(name: "SentryFromBinary", description: "Use precompiled Sentry binary xcframeworks."), + .init(name: "SentryFromSource", description: "Build Sentry from source instead of using precompiled binaries.") + ], dependencies: [ .package(url: "https://github.com/apple/swift-log", from: "1.5.0"), .package(url: "https://github.com/getsentry/sentry-cocoa", from: "9.25.0") @@ -19,7 +24,12 @@ let package = Package( name: "SentrySwiftLog", dependencies: [ .product(name: "Logging", package: "swift-log"), - .product(name: "Sentry", package: "sentry-cocoa") + .product(name: "Sentry", package: "sentry-cocoa", condition: .when(traits: ["SentryFromBinary"])), + .product(name: "SentrySPM", package: "sentry-cocoa", condition: .when(traits: ["SentryFromSource"])) + ], + swiftSettings: [ + .define("SENTRY_FROM_BINARY", .when(traits: ["SentryFromBinary"])), + .define("SENTRY_FROM_SOURCE", .when(traits: ["SentryFromSource"])) ] ), .testTarget( @@ -27,7 +37,12 @@ let package = Package( dependencies: [ "SentrySwiftLog", .product(name: "Logging", package: "swift-log"), - .product(name: "Sentry", package: "sentry-cocoa") + .product(name: "Sentry", package: "sentry-cocoa", condition: .when(traits: ["SentryFromBinary"])), + .product(name: "SentrySPM", package: "sentry-cocoa", condition: .when(traits: ["SentryFromSource"])) + ], + swiftSettings: [ + .define("SENTRY_FROM_BINARY", .when(traits: ["SentryFromBinary"])), + .define("SENTRY_FROM_SOURCE", .when(traits: ["SentryFromSource"])) ] ) ] diff --git a/3rd-party-integrations/SentrySwiftLog/Sources/SentryLogHandler.swift b/3rd-party-integrations/SentrySwiftLog/Sources/SentryLogHandler.swift index d1a41524efc..daffc680168 100644 --- a/3rd-party-integrations/SentrySwiftLog/Sources/SentryLogHandler.swift +++ b/3rd-party-integrations/SentrySwiftLog/Sources/SentryLogHandler.swift @@ -1,5 +1,9 @@ import Logging +#if SENTRY_FROM_SOURCE +import SentrySwift +#else import Sentry +#endif /// A `swift-log` handler that forwards log entries to Sentry's structured logging system. /// diff --git a/3rd-party-integrations/SentrySwiftLog/Sources/SentryTraitValidation.swift b/3rd-party-integrations/SentrySwiftLog/Sources/SentryTraitValidation.swift new file mode 100644 index 00000000000..98793042256 --- /dev/null +++ b/3rd-party-integrations/SentrySwiftLog/Sources/SentryTraitValidation.swift @@ -0,0 +1,3 @@ +#if SENTRY_FROM_BINARY && SENTRY_FROM_SOURCE +#error("SentryFromBinary and SentryFromSource are mutually exclusive. Enable only one.") +#endif diff --git a/3rd-party-integrations/SentrySwiftLog/Tests/SentryLogHandlerTests.swift b/3rd-party-integrations/SentrySwiftLog/Tests/SentryLogHandlerTests.swift index 2f30e23d863..09a76973218 100644 --- a/3rd-party-integrations/SentrySwiftLog/Tests/SentryLogHandlerTests.swift +++ b/3rd-party-integrations/SentrySwiftLog/Tests/SentryLogHandlerTests.swift @@ -1,6 +1,10 @@ @testable import SentrySwiftLog import Logging +#if SENTRY_FROM_SOURCE +import SentrySwift +#else import Sentry +#endif import XCTest final class SentryLogHandlerTests: XCTestCase { diff --git a/3rd-party-integrations/SentrySwiftyBeaver/Package.swift b/3rd-party-integrations/SentrySwiftyBeaver/Package.swift index ae3bdc31eac..89137f6f29d 100644 --- a/3rd-party-integrations/SentrySwiftyBeaver/Package.swift +++ b/3rd-party-integrations/SentrySwiftyBeaver/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:6.0 +// swift-tools-version:6.1 import PackageDescription let package = Package( @@ -10,6 +10,11 @@ let package = Package( targets: ["SentrySwiftyBeaver"] ) ], + traits: [ + .default(enabledTraits: ["SentryFromBinary"]), + .init(name: "SentryFromBinary", description: "Use precompiled Sentry binary xcframeworks."), + .init(name: "SentryFromSource", description: "Build Sentry from source instead of using precompiled binaries.") + ], dependencies: [ .package(url: "https://github.com/getsentry/sentry-cocoa", from: "9.25.0"), .package(url: "https://github.com/SwiftyBeaver/SwiftyBeaver.git", from: "2.0.0") @@ -18,16 +23,26 @@ let package = Package( .target( name: "SentrySwiftyBeaver", dependencies: [ - .product(name: "Sentry", package: "sentry-cocoa"), + .product(name: "Sentry", package: "sentry-cocoa", condition: .when(traits: ["SentryFromBinary"])), + .product(name: "SentrySPM", package: "sentry-cocoa", condition: .when(traits: ["SentryFromSource"])), .product(name: "SwiftyBeaver", package: "SwiftyBeaver") + ], + swiftSettings: [ + .define("SENTRY_FROM_BINARY", .when(traits: ["SentryFromBinary"])), + .define("SENTRY_FROM_SOURCE", .when(traits: ["SentryFromSource"])) ] ), .testTarget( name: "SentrySwiftyBeaverTests", dependencies: [ "SentrySwiftyBeaver", - .product(name: "Sentry", package: "sentry-cocoa"), + .product(name: "Sentry", package: "sentry-cocoa", condition: .when(traits: ["SentryFromBinary"])), + .product(name: "SentrySPM", package: "sentry-cocoa", condition: .when(traits: ["SentryFromSource"])), .product(name: "SwiftyBeaver", package: "SwiftyBeaver") + ], + swiftSettings: [ + .define("SENTRY_FROM_BINARY", .when(traits: ["SentryFromBinary"])), + .define("SENTRY_FROM_SOURCE", .when(traits: ["SentryFromSource"])) ] ) ] diff --git a/3rd-party-integrations/SentrySwiftyBeaver/Sources/SentryDestination.swift b/3rd-party-integrations/SentrySwiftyBeaver/Sources/SentryDestination.swift index a78c2c260e3..d7733816d9b 100644 --- a/3rd-party-integrations/SentrySwiftyBeaver/Sources/SentryDestination.swift +++ b/3rd-party-integrations/SentrySwiftyBeaver/Sources/SentryDestination.swift @@ -1,4 +1,8 @@ +#if SENTRY_FROM_SOURCE +import SentrySwift +#else import Sentry +#endif import SwiftyBeaver /// A SwiftyBeaver destination that forwards log entries to Sentry's structured logging system. diff --git a/3rd-party-integrations/SentrySwiftyBeaver/Sources/SentryTraitValidation.swift b/3rd-party-integrations/SentrySwiftyBeaver/Sources/SentryTraitValidation.swift new file mode 100644 index 00000000000..98793042256 --- /dev/null +++ b/3rd-party-integrations/SentrySwiftyBeaver/Sources/SentryTraitValidation.swift @@ -0,0 +1,3 @@ +#if SENTRY_FROM_BINARY && SENTRY_FROM_SOURCE +#error("SentryFromBinary and SentryFromSource are mutually exclusive. Enable only one.") +#endif diff --git a/3rd-party-integrations/SentrySwiftyBeaver/Tests/SentryDestinationTests.swift b/3rd-party-integrations/SentrySwiftyBeaver/Tests/SentryDestinationTests.swift index 4f1f1f6afbf..7ca0b8d4267 100644 --- a/3rd-party-integrations/SentrySwiftyBeaver/Tests/SentryDestinationTests.swift +++ b/3rd-party-integrations/SentrySwiftyBeaver/Tests/SentryDestinationTests.swift @@ -1,5 +1,9 @@ @testable import SentrySwiftyBeaver +#if SENTRY_FROM_SOURCE +import SentrySwift +#else import Sentry +#endif import SwiftyBeaver import XCTest diff --git a/CHANGELOG.md b/CHANGELOG.md index 6544d330355..985adc387ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,13 @@ ## Unreleased +> [!WARNING] +> The 3rd-party integration packages (SentryCocoaLumberjack, SentryPulse, SentrySwiftLog, SentrySwiftyBeaver) now require Swift 6.1+ to support SPM package traits. Users on older Swift toolchains should pin to an earlier release of these packages. + ### Features - Promote `enableStandaloneAppStartTracing` from `options.experimental` to a top-level option on `Options` (#8715) +- Add `SentryFromBinary` (default) and `SentryFromSource` SPM package traits to 3rd-party integrations, allowing users to choose between precompiled xcframeworks and building from source. Requires Swift 6.1+ (#8795) - Add experimental option `enableUIViewControllerInitSwizzling` that defers `UIViewController` swizzling to first instantiation instead of eagerly discovering and swizzling all subclasses at SDK start. This avoids realizing `@available`-gated `UIViewController` subclasses on OS versions below their gate, which crashes apps on start (#8687). - Add screenshot picker to feedback (#8655) - Enable it with `form.enableScreenshot = true` in the `configureForm` callback.