From cebf90d3f57c384a6725a58a421dc2ee5e374d44 Mon Sep 17 00:00:00 2001 From: Christopher Fuller Date: Wed, 18 Feb 2026 08:40:45 -0800 Subject: [PATCH 1/7] Apply standard Swift package configuration --- .github/workflows/docc.yml | 6 ++++-- .github/workflows/swift.yml | 11 +++++++---- .swiftlint-rules.yml | 8 +++++--- Package.resolved | 23 ++++++++++++----------- Package.swift | 19 ++++++++++++------- 5 files changed, 40 insertions(+), 27 deletions(-) diff --git a/.github/workflows/docc.yml b/.github/workflows/docc.yml index 09b5c56..c1cc6ac 100644 --- a/.github/workflows/docc.yml +++ b/.github/workflows/docc.yml @@ -7,14 +7,16 @@ on: branches: [ main ] env: - DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_26.3.app/Contents/Developer jobs: docc: name: DocC runs-on: macos-latest + permissions: + contents: read steps: - name: Checkout source - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Build run: make docs open="no" DERIVED_DATA_PATH="$(mktemp -d)" diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 1fcadce..eb8b105 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -7,22 +7,24 @@ on: branches: [ main ] env: - DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_26.3.app/Contents/Developer jobs: swift: name: Swift runs-on: macos-latest + permissions: + contents: read env: - SIMULATOR: iPhone 15 + SIMULATOR: iPhone 17 steps: - name: Checkout source - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Download swiftlint binary run: swift package resolve - name: Lint run: > - "$(find ".build/artifacts/swiftlint" -type f -name swiftlint -perm +111 -print -quit)" + "$(find ".build/artifacts/swiftlint" -path "*macos*" -type f -name swiftlint -perm +111 -print -quit)" lint --strict --reporter github-actions-logging - name: Resolve package dependencies run: xcodebuild -resolvePackageDependencies @@ -33,6 +35,7 @@ jobs: -scheme "CombineUI" -destination "name=$SIMULATOR,OS=latest" -skipPackagePluginValidation + SWIFT_TREAT_WARNINGS_AS_ERRORS=YES - name: Test run: > xcodebuild diff --git a/.swiftlint-rules.yml b/.swiftlint-rules.yml index 58fa60d..2ab21c9 100644 --- a/.swiftlint-rules.yml +++ b/.swiftlint-rules.yml @@ -9,8 +9,9 @@ only_rules: - accessibility_label_for_image - accessibility_trait_for_button - anonymous_argument_in_multiline_closure -- anyobject_protocol - array_init +- async_without_await +- attribute_name_spacing # - attributes - balanced_xctest_lifecycle - blanket_disable_command @@ -94,7 +95,6 @@ only_rules: - implicitly_unwrapped_optional - inclusive_language # - indentation_width -- inert_defer - invalid_swiftlint_command - is_disjoint - joined_default_parameter @@ -145,6 +145,7 @@ only_rules: - opening_brace - operator_usage_whitespace - operator_whitespace +- optional_data_string_conversion - optional_enum_case_matching - orphaned_doc_comment - overridden_super_call @@ -155,6 +156,7 @@ only_rules: - prefer_nimble - prefer_self_in_static_references - prefer_self_type_over_type_of_self +- prefer_type_checking - prefer_zero_over_explicit_init # - prefixed_toplevel_constant - private_action @@ -177,6 +179,7 @@ only_rules: - redundant_objc_attribute - redundant_optional_initialization - redundant_self_in_closure +- redundant_sendable - redundant_set_access_control # - redundant_string_enum_value - redundant_type_annotation @@ -224,7 +227,6 @@ only_rules: - unneeded_synthesized_initializer - unowned_variable_capture - untyped_error_in_catch -- unused_capture_list - unused_closure_parameter - unused_control_flow_label - unused_enumerated diff --git a/Package.resolved b/Package.resolved index c6f2c5a..ae61d4d 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,4 +1,5 @@ { + "originHash" : "81ae40d6906e658da10602e875360b31f6a3b0f943e8e855a7f87a356d5db60a", "pins" : [ { "identity" : "collectionconcurrencykit", @@ -41,8 +42,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/Quick/Nimble.git", "state" : { - "revision" : "54b4e52183f16fe806014cbfd63718a84f8ba072", - "version" : "13.4.0" + "revision" : "035b88ad6ae8035f5ce2b50b0a6d69c3b16d2120", + "version" : "14.0.0" } }, { @@ -50,8 +51,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/jpsim/SourceKitten.git", "state" : { - "revision" : "fd4df99170f5e9d7cf9aa8312aa8506e0e7a44e7", - "version" : "0.35.0" + "revision" : "453f75b8a3bb2c3596c0d2dd422c289788233a22", + "version" : "0.37.1" } }, { @@ -68,8 +69,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/swiftlang/swift-syntax.git", "state" : { - "revision" : "515f79b522918f83483068d99c68daeb5116342d", - "version" : "600.0.0-prerelease-2024-08-14" + "revision" : "1103c45ece4f7fe160b8f75b4ea1ee2e5fac1841", + "version" : "601.0.0" } }, { @@ -77,8 +78,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/realm/SwiftLint.git", "state" : { - "revision" : "a24488f26e60247d8fff7bbb03d51910af3dc91c", - "version" : "0.56.2" + "revision" : "625792423014cc49b0a1e5a1a5c0d6b8b3de10f9", + "version" : "0.59.1" } }, { @@ -104,10 +105,10 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/jpsim/Yams.git", "state" : { - "revision" : "3036ba9d69cf1fd04d433527bc339dc0dc75433d", - "version" : "5.1.3" + "revision" : "3d6871d5b4a5cd519adf233fbb576e0a2af71c17", + "version" : "5.4.0" } } ], - "version" : 2 + "version" : 3 } diff --git a/Package.swift b/Package.swift index 7ddadba..04089c0 100644 --- a/Package.swift +++ b/Package.swift @@ -1,7 +1,10 @@ -// swift-tools-version:5.8 +// swift-tools-version:5.10 +import Foundation import PackageDescription +let enableSwiftLintBuildToolPlugin = ProcessInfo.processInfo.environment["CODEQL_DIST"] == nil + let package = Package( name: "CombineUI", platforms: [ @@ -16,10 +19,10 @@ let package = Package( dependencies: [ .package( url: "https://github.com/realm/SwiftLint.git", - exact: "0.56.2"), + exact: "0.59.1"), .package( url: "https://github.com/Quick/Nimble.git", - exact: "13.4.0"), + exact: "14.0.0"), ], targets: [ .target( @@ -30,7 +33,7 @@ let package = Package( "CombineUI", "Nimble", ]), - ] + ], ) package.targets.forEach { target in @@ -39,7 +42,9 @@ package.targets.forEach { target in .enableExperimentalFeature("StrictConcurrency"), ] - target.plugins = [ - .plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLint"), - ] + if enableSwiftLintBuildToolPlugin { + target.plugins = [ + .plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLint"), + ] + } } From bf9703bab0ea033a1da38fc80daf9a0242ba9848 Mon Sep 17 00:00:00 2001 From: Christopher Fuller Date: Wed, 18 Feb 2026 09:01:13 -0800 Subject: [PATCH 2/7] Treat warnings as errors in release --- .github/workflows/swift.yml | 3 ++- Package.swift | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index eb8b105..8c8d9d6 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -33,12 +33,13 @@ jobs: xcodebuild build-for-testing -scheme "CombineUI" + -configuration Release -destination "name=$SIMULATOR,OS=latest" -skipPackagePluginValidation - SWIFT_TREAT_WARNINGS_AS_ERRORS=YES - name: Test run: > xcodebuild test-without-building -scheme "CombineUI" + -configuration Release -destination "name=$SIMULATOR,OS=latest" diff --git a/Package.swift b/Package.swift index 04089c0..f3195b8 100644 --- a/Package.swift +++ b/Package.swift @@ -26,7 +26,10 @@ let package = Package( ], targets: [ .target( - name: "CombineUI"), + name: "CombineUI", + swiftSettings: [ + .unsafeFlags(["-warnings-as-errors"], .when(configuration: .release)), + ]), .testTarget( name: "CombineUITests", dependencies: [ From 3a0ec967c5098a37b465eddde636b0252b4b46e6 Mon Sep 17 00:00:00 2001 From: Christopher Fuller Date: Wed, 18 Feb 2026 09:06:29 -0800 Subject: [PATCH 3/7] Do not set configuration in test step --- .github/workflows/swift.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 8c8d9d6..40ebc00 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -41,5 +41,4 @@ jobs: xcodebuild test-without-building -scheme "CombineUI" - -configuration Release -destination "name=$SIMULATOR,OS=latest" From 269d31f5df4c8f9339217a29f9ba9de824fd0463 Mon Sep 17 00:00:00 2001 From: Christopher Fuller Date: Thu, 19 Feb 2026 13:43:17 -0800 Subject: [PATCH 4/7] Do not set configuration in build step --- .github/workflows/swift.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 40ebc00..24bfd25 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -33,7 +33,6 @@ jobs: xcodebuild build-for-testing -scheme "CombineUI" - -configuration Release -destination "name=$SIMULATOR,OS=latest" -skipPackagePluginValidation - name: Test From 631284f24702eaa50ed8df1440df06b566691f28 Mon Sep 17 00:00:00 2001 From: Christopher Fuller Date: Thu, 19 Feb 2026 13:43:38 -0800 Subject: [PATCH 5/7] Apply standard Swift package configuration --- Package.swift | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/Package.swift b/Package.swift index f3195b8..b47d3ea 100644 --- a/Package.swift +++ b/Package.swift @@ -3,7 +3,10 @@ import Foundation import PackageDescription -let enableSwiftLintBuildToolPlugin = ProcessInfo.processInfo.environment["CODEQL_DIST"] == nil +let environment = ProcessInfo.processInfo.environment + +let treatWarningsAsErrors = environment["CI"] == "true" +let enableSwiftLintBuildToolPlugin = environment["CODEQL_DIST"] == nil let package = Package( name: "CombineUI", @@ -26,10 +29,7 @@ let package = Package( ], targets: [ .target( - name: "CombineUI", - swiftSettings: [ - .unsafeFlags(["-warnings-as-errors"], .when(configuration: .release)), - ]), + name: "CombineUI"), .testTarget( name: "CombineUITests", dependencies: [ @@ -41,12 +41,20 @@ let package = Package( package.targets.forEach { target in - target.swiftSettings = [ - .enableExperimentalFeature("StrictConcurrency"), - ] + // TODO: Remove upon enabling Swift 6 language mode: + target.swiftSettings = (target.swiftSettings ?? []) + [.enableExperimentalFeature("StrictConcurrency")] + + if treatWarningsAsErrors { + target.swiftSettings = (target.swiftSettings ?? []) + [ + // TODO: Remove unsafe flag upon upgrading to Swift tools v6.2 and uncomment subsequent settings: + .unsafeFlags(["-warnings-as-errors"]), +// .treatAllWarnings(as: .error), +// .treatWarning("DeprecatedDeclaration", as: .warning) + ] + } if enableSwiftLintBuildToolPlugin { - target.plugins = [ + target.plugins = (target.plugins ?? []) + [ .plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLint"), ] } From 924eace282745fc1aef50cfcd6dd0572afc63088 Mon Sep 17 00:00:00 2001 From: Christopher Fuller Date: Thu, 19 Feb 2026 14:04:48 -0800 Subject: [PATCH 6/7] Add missing comma --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index b47d3ea..2af804c 100644 --- a/Package.swift +++ b/Package.swift @@ -49,7 +49,7 @@ package.targets.forEach { target in // TODO: Remove unsafe flag upon upgrading to Swift tools v6.2 and uncomment subsequent settings: .unsafeFlags(["-warnings-as-errors"]), // .treatAllWarnings(as: .error), -// .treatWarning("DeprecatedDeclaration", as: .warning) +// .treatWarning("DeprecatedDeclaration", as: .warning), ] } From c35134a32b978b879dd70cbf01a8c3f5f4298958 Mon Sep 17 00:00:00 2001 From: Christopher Fuller Date: Thu, 19 Feb 2026 14:05:24 -0800 Subject: [PATCH 7/7] Assign separately to avoid build issue --- Tests/CombineUITests/BindingTests.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/CombineUITests/BindingTests.swift b/Tests/CombineUITests/BindingTests.swift index a0eb237..6c0e50e 100644 --- a/Tests/CombineUITests/BindingTests.swift +++ b/Tests/CombineUITests/BindingTests.swift @@ -35,7 +35,8 @@ final class BindingTests: XCTestCase { func testBinding() { let subject: PassthroughSubject = .init() var object: TestObject? = .init() - weak var weakObject: TestObject? = object + weak var weakObject: TestObject? + weakObject = object expect(weakObject) != nil if let object: TestObject { subject