diff --git a/.github/workflows/docc.yml b/.github/workflows/docc.yml index 09b5c56ba..c1cc6aca2 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/genesis.yml b/.github/workflows/genesis.yml index df3884141..37f3734a4 100644 --- a/.github/workflows/genesis.yml +++ b/.github/workflows/genesis.yml @@ -7,21 +7,23 @@ on: branches: [ main ] env: - DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_26.3.app/Contents/Developer jobs: genesis: name: Genesis runs-on: macos-latest + permissions: + contents: read env: - SIMULATOR: iPhone 15 + SIMULATOR: iPhone 17 steps: - name: Install dependencies run: | brew install mint xcodegen needle mockolo mint install yonaskolb/genesis - name: Checkout source - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Create temporary directory id: mktemp run: echo "directory=$(mktemp -d)" >> "$GITHUB_OUTPUT" @@ -33,16 +35,13 @@ jobs: - name: Generate Xcode project working-directory: ${{ steps.mktemp.outputs.directory }} run: xcodegen - - name: Remove @MainActor - working-directory: ${{ steps.mktemp.outputs.directory }} - run: find "Tinder/Sources" -type f -name "*.swift" -exec sed -i '' '/@MainActor/,+0d' {} \; - name: Download swiftlint binary working-directory: ${{ steps.mktemp.outputs.directory }} run: swift package resolve - name: Lint working-directory: ${{ steps.mktemp.outputs.directory }} 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 working-directory: ${{ steps.mktemp.outputs.directory }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 41c031aa2..59b68b3a6 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -7,18 +7,20 @@ on: branches: [ main ] env: - DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_26.3.app/Contents/Developer jobs: lint: name: Lint runs-on: macos-latest + permissions: + contents: read 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 diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 047a032dc..c575b468f 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -5,12 +5,7 @@ on: tags: ['[0-9]+.[0-9]+.[0-9]+'] env: - DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer - -permissions: - contents: read - pages: write - id-token: write + DEVELOPER_DIR: /Applications/Xcode_26.3.app/Contents/Developer concurrency: group: "pages" @@ -23,9 +18,13 @@ jobs: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: macos-latest + permissions: + contents: read + pages: write + id-token: write steps: - name: Checkout source - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Configure pages uses: actions/configure-pages@v5 - name: Build documentation diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 8d3abf983..c6d0e36bc 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -7,15 +7,17 @@ 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 steps: - name: Checkout source - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Build run: swift build -v - name: Test diff --git a/.github/workflows/xcode.yml b/.github/workflows/xcode.yml index 171c6416c..319313bf8 100644 --- a/.github/workflows/xcode.yml +++ b/.github/workflows/xcode.yml @@ -7,17 +7,19 @@ on: branches: [ main ] env: - DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_26.3.app/Contents/Developer jobs: xcode: name: Xcode 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: Resolve package dependencies run: xcodebuild -resolvePackageDependencies - name: Build diff --git a/.swiftlint-rules.yml b/.swiftlint-rules.yml index 58fa60d93..2ab21c993 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/Makefile b/Makefile index bf2b94d5d..8157c45b1 100644 --- a/Makefile +++ b/Makefile @@ -1,23 +1,3 @@ -.PHONY: release -release: override library = Nodes -release: override platforms = macos catalyst ios tvos watchos -release: override bitcode = DISABLED -release: - @make xcframework library="$(library)" platforms="$(platforms)" bitcode="$(bitcode)" version="$(version)" - -.PHONY: xcframework -xcframework: library ?= $(shell make get-libraries | head -1) -xcframework: platforms ?= $(shell make get-platforms) -xcframework: -ifndef version - $(error required variable: "version") -endif -ifeq ($(strip $(bitcode)),ENABLED) - @./bin/create-xcframework "$(library)" "$(platforms)" BITCODE_ENABLED "$(version)" -else - @./bin/create-xcframework "$(library)" "$(platforms)" BITCODE_DISABLED "$(version)" -endif - .PHONY: open open: fix open: @@ -81,19 +61,13 @@ docs: -scheme "$(target)" \ -destination "$(destination)" \ -derivedDataPath "$(DERIVED_DATA_PATH)" \ - -skipPackagePluginValidation \ - OTHER_DOCC_FLAGS="--warnings-as-errors" + -skipPackagePluginValidation @find "$(DERIVED_DATA_PATH)" \ -type d \ -name "$(target).doccarchive" \ -exec cp -R {} "$(ARCHIVE_PATH)/" \; $(if $(filter $(open),OPEN),@open "$(ARCHIVE_PATH)/$(target).doccarchive",) -.PHONY: preview -preview: target ?= Nodes -preview: - swift package --disable-sandbox preview-documentation --target "$(target)" - .PHONY: site site: target ?= Nodes site: prefix ?= $(shell pwd) @@ -108,18 +82,3 @@ site: --output-path "$(prefix)/_site" cp docs.html "$(prefix)/_site/index.html" cp docs.html "$(prefix)/_site/documentation/index.html" - -.PHONY: get-libraries -get-libraries: - @./bin/get-libraries - -.PHONY: get-platforms -get-platforms: - @./bin/get-platforms - -.PHONY: get-deployment-target -get-deployment-target: -ifndef platform - $(error required variable: "platform") -endif - @./bin/get-deployment-target "$(platform)" diff --git a/Package.resolved b/Package.resolved index d30e78f12..907e83e7b 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,4 +1,5 @@ { + "originHash" : "a5e45172dde18587c57a5dfac3f79aa0d3b0e6522df24d050273b5c59c983838", "pins" : [ { "identity" : "codextended", @@ -23,8 +24,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/krzyzanowskim/CryptoSwift.git", "state" : { - "revision" : "678d442c6f7828def400a70ae15968aef67ef52d", - "version" : "1.8.3" + "revision" : "e45a26384239e028ec87fbcc788f513b67e10d8f", + "version" : "1.9.0" } }, { @@ -59,8 +60,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/Quick/Nimble.git", "state" : { - "revision" : "54b4e52183f16fe806014cbfd63718a84f8ba072", - "version" : "13.4.0" + "revision" : "035b88ad6ae8035f5ce2b50b0a6d69c3b16d2120", + "version" : "14.0.0" } }, { @@ -77,8 +78,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/jpsim/SourceKitten.git", "state" : { - "revision" : "fd4df99170f5e9d7cf9aa8312aa8506e0e7a44e7", - "version" : "0.35.0" + "revision" : "453f75b8a3bb2c3596c0d2dd422c289788233a22", + "version" : "0.37.1" } }, { @@ -104,8 +105,17 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-argument-parser.git", "state" : { - "revision" : "41982a3656a71c768319979febd796c6fd111d5c", - "version" : "1.5.0" + "revision" : "c5d11a805e765f52ba34ec7284bd4fcd6ba68615", + "version" : "1.7.0" + } + }, + { + "identity" : "swift-custom-dump", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-custom-dump", + "state" : { + "revision" : "2a2a938798236b8fa0bc57c453ee9de9f9ec3ab0", + "version" : "1.4.1" } }, { @@ -113,8 +123,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-docc-plugin.git", "state" : { - "revision" : "2eb22993b3dfd0c0d32729b357c8dabb6cd44680", - "version" : "1.4.2" + "revision" : "3e4f133a77e644a5812911a0513aeb7288b07d06", + "version" : "1.4.5" } }, { @@ -131,8 +141,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-snapshot-testing.git", "state" : { - "revision" : "6d932a79e7173b275b96c600c86c603cf84f153c", - "version" : "1.17.4" + "revision" : "bf8d8c27f0f0c6d5e77bff0db76ab68f2050d15d", + "version" : "1.18.9" } }, { @@ -140,8 +150,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/swiftlang/swift-syntax", "state" : { - "revision" : "515f79b522918f83483068d99c68daeb5116342d", - "version" : "600.0.0-prerelease-2024-08-14" + "revision" : "1103c45ece4f7fe160b8f75b4ea1ee2e5fac1841", + "version" : "601.0.0" } }, { @@ -149,8 +159,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/realm/SwiftLint.git", "state" : { - "revision" : "a24488f26e60247d8fff7bbb03d51910af3dc91c", - "version" : "0.56.2" + "revision" : "625792423014cc49b0a1e5a1a5c0d6b8b3de10f9", + "version" : "0.59.1" } }, { @@ -171,15 +181,24 @@ "version" : "7.0.2" } }, + { + "identity" : "xctest-dynamic-overlay", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", + "state" : { + "revision" : "dfd70507def84cb5fb821278448a262c6ff2bbad", + "version" : "1.9.0" + } + }, { "identity" : "yams", "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 f9e7de406..29ced769d 100644 --- a/Package.swift +++ b/Package.swift @@ -1,7 +1,13 @@ -// swift-tools-version:5.8 +// swift-tools-version:5.10 +import Foundation import PackageDescription +let environment = ProcessInfo.processInfo.environment + +let treatWarningsAsErrors = environment["CI"] == "true" +let enableSwiftLintBuildToolPlugin = environment["CODEQL_DIST"] == nil + let package = Package( name: "Nodes", platforms: [ @@ -30,16 +36,16 @@ let package = Package( dependencies: [ .package( url: "https://github.com/apple/swift-argument-parser.git", - exact: "1.5.0"), + exact: "1.7.0"), .package( url: "https://github.com/apple/swift-docc-plugin.git", - exact: "1.4.2"), + exact: "1.4.5"), .package( url: "https://github.com/JohnSundell/Codextended.git", exact: "0.3.0"), .package( url: "https://github.com/jpsim/Yams.git", - exact: "5.1.3"), + exact: "5.4.0"), .package( url: "https://github.com/stencilproject/Stencil.git", exact: "0.15.1"), @@ -48,13 +54,13 @@ let package = Package( exact: "0.25.1"), .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"), .package( url: "https://github.com/pointfreeco/swift-snapshot-testing.git", - exact: "1.17.4"), + exact: "1.18.9"), ], targets: [ .executableTarget( @@ -117,11 +123,21 @@ 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")] - target.plugins = [ - .plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLint"), - ] + 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 ?? []) + [ + .plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLint"), + ] + } } diff --git a/README.md b/README.md index dc883038f..849ef3ad5 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ To install Nodes' Xcode templates manually, first add Nodes as a dependency to a > Replace `` in the command with the latest Nodes version. ``` -.package(url: "git@github.com:Tinder/Nodes.git", from: "") +.package(url: "https://github.com/Tinder/Nodes.git", from: "") ``` Then run the following shell command: @@ -98,10 +98,6 @@ Documentation is available online at: [https://Tinder.github.io/Nodes](https://T Following these steps will create a new iOS Xcode project set up with Nodes, Needle and Mockolo. -### Requirements - -- Xcode version `13.3` or greater - ### Install Dependencies ``` @@ -116,7 +112,7 @@ This step may be skipped if the Nodes repository was previously cloned. > Replace `` in the command with the latest Nodes version. ``` -git clone -b git@github.com:Tinder/Nodes.git +git clone -b https://github.com/Tinder/Nodes.git ``` ### Create Project Directory diff --git a/Sources/Executables/NodesCodeGenerator/NodesCodeGeneratorCommand.swift b/Sources/Executables/NodesCodeGenerator/NodesCodeGeneratorCommand.swift index ee65b62f7..115f5147b 100644 --- a/Sources/Executables/NodesCodeGenerator/NodesCodeGeneratorCommand.swift +++ b/Sources/Executables/NodesCodeGenerator/NodesCodeGeneratorCommand.swift @@ -14,17 +14,10 @@ import NodesGenerator @main internal struct NodesCodeGeneratorCommand: ParsableCommand { - #if swift(>=5.10) - nonisolated(unsafe) internal static let configuration: CommandConfiguration = .init( - commandName: "nodes-code-gen", - abstract: "Nodes Code Generator" - ) - #else internal static let configuration: CommandConfiguration = .init( commandName: "nodes-code-gen", abstract: "Nodes Code Generator" ) - #endif @Option(help: "The name of the preset. (App|Scene|Window|Root)") private var preset: Preset diff --git a/Sources/Executables/NodesXcodeTemplatesGenerator/NodesXcodeTemplatesGeneratorCommand.swift b/Sources/Executables/NodesXcodeTemplatesGenerator/NodesXcodeTemplatesGeneratorCommand.swift index c6fa3d19d..7b0a54bed 100644 --- a/Sources/Executables/NodesXcodeTemplatesGenerator/NodesXcodeTemplatesGeneratorCommand.swift +++ b/Sources/Executables/NodesXcodeTemplatesGenerator/NodesXcodeTemplatesGeneratorCommand.swift @@ -13,17 +13,10 @@ import NodesGenerator @main internal struct NodesXcodeTemplatesGeneratorCommand: ParsableCommand { - #if swift(>=5.10) - nonisolated(unsafe) internal static let configuration: CommandConfiguration = .init( - commandName: "nodes-xcode-templates-gen", - abstract: "Nodes Xcode Templates Generator" - ) - #else internal static let configuration: CommandConfiguration = .init( commandName: "nodes-xcode-templates-gen", abstract: "Nodes Xcode Templates Generator" ) - #endif @Option(name: .customLong("id"), help: "The Xcode templates identifier.") private var identifier: String diff --git a/Sources/Nodes/Debugging/DebugInformation.swift b/Sources/Nodes/Debugging/DebugInformation.swift index 2be3c85fe..e763a9b54 100644 --- a/Sources/Nodes/Debugging/DebugInformation.swift +++ b/Sources/Nodes/Debugging/DebugInformation.swift @@ -96,6 +96,17 @@ public enum DebugInformation { private static let name: Notification.Name = .init("Nodes.\(DebugInformation.self).\(FlowWillStartNotification.self)") + internal let notification: Notification + + internal init(flow: Flow, viewController: AnyObject) { + let userInfo: UserInfo = [ + .flowIdentifier: ObjectIdentifier(flow), + .flowType: type(of: flow), + .factory: Factory(viewController) + ] + notification = Notification(name: Self.name, userInfo: userInfo) + } + @available(iOS 13.0, OSX 10.15, *) // swiftlint:disable:next strict_fileprivate fileprivate static func publisher() -> AnyPublisher { NotificationCenter.default.publisher(for: name) @@ -111,23 +122,22 @@ public enum DebugInformation { } .eraseToAnyPublisher() } + } + + internal final class FlowDidEndNotification: NotificationPosting { + + private static let name: Notification.Name = + .init("Nodes.\(DebugInformation.self).\(FlowDidEndNotification.self)") internal let notification: Notification - internal init(flow: Flow, viewController: AnyObject) { + internal init(flow: Flow) { let userInfo: UserInfo = [ .flowIdentifier: ObjectIdentifier(flow), - .flowType: type(of: flow), - .factory: Factory(viewController) + .flowType: type(of: flow) ] notification = Notification(name: Self.name, userInfo: userInfo) } - } - - internal final class FlowDidEndNotification: NotificationPosting { - - private static let name: Notification.Name = - .init("Nodes.\(DebugInformation.self).\(FlowDidEndNotification.self)") @available(iOS 13.0, OSX 10.15, *) // swiftlint:disable:next strict_fileprivate fileprivate static func publisher() -> AnyPublisher { @@ -142,22 +152,24 @@ public enum DebugInformation { } .eraseToAnyPublisher() } + } + + internal final class FlowWillAttachNotification: NotificationPosting { + + private static let name: Notification.Name = + .init("Nodes.\(DebugInformation.self).\(FlowWillAttachNotification.self)") internal let notification: Notification - internal init(flow: Flow) { + internal init(flow: Flow, subFlow: Flow) { let userInfo: UserInfo = [ .flowIdentifier: ObjectIdentifier(flow), - .flowType: type(of: flow) + .flowType: type(of: flow), + .subFlowIdentifier: ObjectIdentifier(subFlow), + .subFlowType: type(of: subFlow) ] notification = Notification(name: Self.name, userInfo: userInfo) } - } - - internal final class FlowWillAttachNotification: NotificationPosting { - - private static let name: Notification.Name = - .init("Nodes.\(DebugInformation.self).\(FlowWillAttachNotification.self)") @available(iOS 13.0, OSX 10.15, *) // swiftlint:disable:next strict_fileprivate fileprivate static func publisher() -> AnyPublisher { @@ -176,6 +188,12 @@ public enum DebugInformation { } .eraseToAnyPublisher() } + } + + internal final class FlowDidDetachNotification: NotificationPosting { + + private static let name: Notification.Name = + .init("Nodes.\(DebugInformation.self).\(FlowDidDetachNotification.self)") internal let notification: Notification @@ -188,12 +206,6 @@ public enum DebugInformation { ] notification = Notification(name: Self.name, userInfo: userInfo) } - } - - internal final class FlowDidDetachNotification: NotificationPosting { - - private static let name: Notification.Name = - .init("Nodes.\(DebugInformation.self).\(FlowDidDetachNotification.self)") @available(iOS 13.0, OSX 10.15, *) // swiftlint:disable:next strict_fileprivate fileprivate static func publisher() -> AnyPublisher { @@ -212,24 +224,23 @@ public enum DebugInformation { } .eraseToAnyPublisher() } + } + + internal final class FlowControllerWillAttachNotification: NotificationPosting { + + private static let name: Notification.Name = + .init("Nodes.\(DebugInformation.self).\(FlowControllerWillAttachNotification.self)") internal let notification: Notification - internal init(flow: Flow, subFlow: Flow) { + internal init(flowController: FlowController, flow: Flow) { let userInfo: UserInfo = [ + .flowControllerIdentifier: ObjectIdentifier(flowController), .flowIdentifier: ObjectIdentifier(flow), - .flowType: type(of: flow), - .subFlowIdentifier: ObjectIdentifier(subFlow), - .subFlowType: type(of: subFlow) + .flowType: type(of: flow) ] notification = Notification(name: Self.name, userInfo: userInfo) } - } - - internal final class FlowControllerWillAttachNotification: NotificationPosting { - - private static let name: Notification.Name = - .init("Nodes.\(DebugInformation.self).\(FlowControllerWillAttachNotification.self)") @available(iOS 13.0, OSX 10.15, *) // swiftlint:disable:next strict_fileprivate fileprivate static func publisher() -> AnyPublisher { @@ -246,6 +257,12 @@ public enum DebugInformation { } .eraseToAnyPublisher() } + } + + internal final class FlowControllerDidDetachNotification: NotificationPosting { + + private static let name: Notification.Name = + .init("Nodes.\(DebugInformation.self).\(FlowControllerDidDetachNotification.self)") internal let notification: Notification @@ -257,12 +274,6 @@ public enum DebugInformation { ] notification = Notification(name: Self.name, userInfo: userInfo) } - } - - internal final class FlowControllerDidDetachNotification: NotificationPosting { - - private static let name: Notification.Name = - .init("Nodes.\(DebugInformation.self).\(FlowControllerDidDetachNotification.self)") @available(iOS 13.0, OSX 10.15, *) // swiftlint:disable:next strict_fileprivate fileprivate static func publisher() -> AnyPublisher { @@ -279,17 +290,6 @@ public enum DebugInformation { } .eraseToAnyPublisher() } - - internal let notification: Notification - - internal init(flowController: FlowController, flow: Flow) { - let userInfo: UserInfo = [ - .flowControllerIdentifier: ObjectIdentifier(flowController), - .flowIdentifier: ObjectIdentifier(flow), - .flowType: type(of: flow) - ] - notification = Notification(name: Self.name, userInfo: userInfo) - } } private enum UserInfoKey { diff --git a/Sources/NodesGenerator/StencilContexts/NodeStencilContext.swift b/Sources/NodesGenerator/StencilContexts/NodeStencilContext.swift index f08916464..9f04587c6 100644 --- a/Sources/NodesGenerator/StencilContexts/NodeStencilContext.swift +++ b/Sources/NodesGenerator/StencilContexts/NodeStencilContext.swift @@ -115,7 +115,7 @@ public struct NodeStencilContext: StencilContext { ] } - // swiftlint:disable:next function_default_parameter_at_end function_body_length + // swiftlint:disable:next function_body_length public init( fileHeader: String, nodeName: String, @@ -139,7 +139,7 @@ public struct NodeStencilContext: StencilContext { viewStateImports: Set, viewStateFactoryTestsImports: Set, dependencies: [Config.Variable], - componentDependencies: String = "", + componentDependencies: String = "", // swiftlint:disable:this function_default_parameter_at_end analyticsProperties: [Config.Variable], flowProperties: [Config.Variable], viewControllableFlowType: String, diff --git a/Sources/NodesGenerator/StencilContexts/NodeViewInjectedStencilContext.swift b/Sources/NodesGenerator/StencilContexts/NodeViewInjectedStencilContext.swift index 52ba73026..967308459 100644 --- a/Sources/NodesGenerator/StencilContexts/NodeViewInjectedStencilContext.swift +++ b/Sources/NodesGenerator/StencilContexts/NodeViewInjectedStencilContext.swift @@ -70,7 +70,6 @@ public struct NodeViewInjectedStencilContext: StencilContext { ] } - // swiftlint:disable:next function_default_parameter_at_end public init( fileHeader: String, nodeName: String, @@ -89,7 +88,7 @@ public struct NodeViewInjectedStencilContext: StencilContext { pluginTestsImports: Set, stateImports: Set, dependencies: [Config.Variable], - componentDependencies: String = "", + componentDependencies: String = "", // swiftlint:disable:this function_default_parameter_at_end analyticsProperties: [Config.Variable], flowProperties: [Config.Variable], viewControllableFlowType: String, diff --git a/Sources/NodesGenerator/XcodeTemplatePropertyList.swift b/Sources/NodesGenerator/XcodeTemplatePropertyList.swift index 4477020dd..952e544fa 100644 --- a/Sources/NodesGenerator/XcodeTemplatePropertyList.swift +++ b/Sources/NodesGenerator/XcodeTemplatePropertyList.swift @@ -83,7 +83,7 @@ internal struct XcodeTemplatePropertyList: Codable, Equatable { } internal static func buildBlock(_ components: Component...) -> Component { - components.flatMap { $0 } + components.flatMap(\.self) } internal static func buildOptional(_ component: Component?) -> Component { @@ -99,7 +99,7 @@ internal struct XcodeTemplatePropertyList: Codable, Equatable { } internal static func buildArray(_ components: [Component]) -> Component { - components.flatMap { $0 } + components.flatMap(\.self) } internal static func buildLimitedAvailability(_ component: Component) -> Component { diff --git a/Sources/NodesGenerator/YAMLDecoder.swift b/Sources/NodesGenerator/YAMLDecoder.swift index c9c0ac485..1da94779f 100644 --- a/Sources/NodesGenerator/YAMLDecoder.swift +++ b/Sources/NodesGenerator/YAMLDecoder.swift @@ -11,4 +11,4 @@ import Codextended import Yams // Enables Codextended with YAMLDecoder [https://github.com/JohnSundell/Codextended] -extension YAMLDecoder: AnyDecoder {} +extension YAMLDecoder: @retroactive AnyDecoder {} diff --git a/Sources/NodesTesting/Mocks/ObservableViewStateStoreMock.swift b/Sources/NodesTesting/Mocks/ObservableViewStateStoreMock.swift index 94bbf9f07..5ab13d901 100644 --- a/Sources/NodesTesting/Mocks/ObservableViewStateStoreMock.swift +++ b/Sources/NodesTesting/Mocks/ObservableViewStateStoreMock.swift @@ -7,10 +7,10 @@ // See https://github.com/Tinder/Nodes/blob/main/LICENSE for license information. // -#if canImport(SwiftUI) +#if canImport(Combine) +import Combine import Nodes -import SwiftUI @preconcurrency @MainActor diff --git a/Tests/NodesGeneratorTests/UIFramework-FrameworkTests.swift b/Tests/NodesGeneratorTests/UIFramework-FrameworkTests.swift index e4d44fe02..4ad13122e 100644 --- a/Tests/NodesGeneratorTests/UIFramework-FrameworkTests.swift +++ b/Tests/NodesGeneratorTests/UIFramework-FrameworkTests.swift @@ -170,24 +170,247 @@ final class UIFrameworkFrameworkTests: XCTestCase { }) } - func testDecodingThrowsTypeMismatchForExpectedOnlyOneKey() throws { + // swiftlint:disable line_length closure_body_length + + func testDecodingThrowsDataCorruptedForExpectedAllKeysToBeUnique() throws { let data: Data = .init("custom:\ncustom:\n".utf8) expect(try data.decoded(as: UIFramework.Framework.self, using: YAMLDecoder())) .to(throwError(errorType: DecodingError.self) { error in assertInlineSnapshot(of: error, as: .dump) { """ ▿ DecodingError - ▿ typeMismatch: (2 elements) - - .0: Framework - ▿ .1: Context - - codingPath: 0 elements - - debugDescription: "Expected only one key." - - underlyingError: Optional.none + ▿ dataCorrupted: Context + - codingPath: 0 elements + - debugDescription: "The given data was not valid YAML." + ▿ underlyingError: Optional + ▿ some: error: parser: expected all keys to be unique but found the following duplicated key(s): + custom ([1:1, 2:1]): + custom: + ^ + custom: + ^ + ▿ duplicatedKeysInMapping: (2 elements) + ▿ duplicates: 1 key/value pair + ▿ (2 elements) + ▿ key: Node + ▿ scalar: Scalar + - anchor: Optional.none + ▿ mark: Optional + ▿ some: 1:1 + - line: 1 + - column: 1 + - string: "custom" + - style: Style.plain + ▿ tag: tag:yaml.org,2002:str + ▿ constructor: Constructor + ▿ mappingMap: 2 key/value pairs + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:map" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:set" + - value: (Function) + ▿ scalarMap: 7 key/value pairs + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:binary" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:bool" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:float" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:int" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:null" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:str" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:timestamp" + - value: (Function) + ▿ sequenceMap: 3 key/value pairs + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:omap" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:pairs" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:seq" + - value: (Function) + ▿ name: Name + - rawValue: "tag:yaml.org,2002:str" + ▿ resolver: Resolver + ▿ rules: 1 element + ▿ Rule + - regexp: ^(?:<<)$ + ▿ tag: Name + - rawValue: "tag:yaml.org,2002:merge" + ▿ value: 2 elements + ▿ Node + ▿ scalar: Scalar + - anchor: Optional.none + ▿ mark: Optional + ▿ some: 1:1 + - line: 1 + - column: 1 + - string: "custom" + - style: Style.plain + ▿ tag: tag:yaml.org,2002:str + ▿ constructor: Constructor + ▿ mappingMap: 2 key/value pairs + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:map" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:set" + - value: (Function) + ▿ scalarMap: 7 key/value pairs + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:binary" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:bool" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:float" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:int" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:null" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:str" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:timestamp" + - value: (Function) + ▿ sequenceMap: 3 key/value pairs + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:omap" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:pairs" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:seq" + - value: (Function) + ▿ name: Name + - rawValue: "tag:yaml.org,2002:str" + ▿ resolver: Resolver + ▿ rules: 1 element + ▿ Rule + - regexp: ^(?:<<)$ + ▿ tag: Name + - rawValue: "tag:yaml.org,2002:merge" + ▿ Node + ▿ scalar: Scalar + - anchor: Optional.none + ▿ mark: Optional + ▿ some: 2:1 + - line: 2 + - column: 1 + - string: "custom" + - style: Style.plain + ▿ tag: tag:yaml.org,2002:str + ▿ constructor: Constructor + ▿ mappingMap: 2 key/value pairs + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:map" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:set" + - value: (Function) + ▿ scalarMap: 7 key/value pairs + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:binary" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:bool" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:float" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:int" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:null" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:str" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:timestamp" + - value: (Function) + ▿ sequenceMap: 3 key/value pairs + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:omap" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:pairs" + - value: (Function) + ▿ (2 elements) + ▿ key: Name + - rawValue: "tag:yaml.org,2002:seq" + - value: (Function) + ▿ name: Name + - rawValue: "tag:yaml.org,2002:str" + ▿ resolver: Resolver + ▿ rules: 1 element + ▿ Rule + - regexp: ^(?:<<)$ + ▿ tag: Name + - rawValue: "tag:yaml.org,2002:merge" + - yaml: "custom:\\ncustom:\\n" """ + "\n" } }) } + // swiftlint:enable line_length closure_body_length + func testDecodingThrowsTypeMismatchForExpectedToDecodeMapping() throws { let data: Data = .init("[]".utf8) expect(try data.decoded(as: UIFramework.Framework.self, using: YAMLDecoder())) diff --git a/Tests/NodesTestingTests/XCTestCaseTests.swift b/Tests/NodesTestingTests/XCTestCaseTests.swift index 80188a336..8a8487b22 100644 --- a/Tests/NodesTestingTests/XCTestCaseTests.swift +++ b/Tests/NodesTestingTests/XCTestCaseTests.swift @@ -27,17 +27,17 @@ final class XCTestCaseTests: XCTestCase { private static let childPath: String = "^->BootstrapComponent->ParentComponent->ChildComponent" @MainActor - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() expect(Self.registry.dependencyProviderFactory(for: Self.parentPath)) == nil expect(Self.registry.dependencyProviderFactory(for: Self.childPath)) == nil } @MainActor - override func tearDown() { + override func tearDown() async throws { expect(Self.registry.dependencyProviderFactory(for: Self.parentPath)) == nil expect(Self.registry.dependencyProviderFactory(for: Self.childPath)) == nil - super.tearDown() + try await super.tearDown() } @MainActor diff --git a/Tests/NodesTests/CoreTests/AbstractContextTests.swift b/Tests/NodesTests/CoreTests/AbstractContextTests.swift index 2171dd848..71ac3c3e4 100644 --- a/Tests/NodesTests/CoreTests/AbstractContextTests.swift +++ b/Tests/NodesTests/CoreTests/AbstractContextTests.swift @@ -35,15 +35,15 @@ final class AbstractContextTests: XCTestCase, TestCaseHelpers { private var mockCancellables: [CancellableMock]! @MainActor - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() tearDown(keyPath: \.mockWorkers, initialValue: [WorkerMock(), WorkerMock(), WorkerMock()]) tearDown(keyPath: \.mockCancellables, initialValue: [CancellableMock(), CancellableMock(), CancellableMock()]) } @MainActor - override func tearDown() { - super.tearDown() + override func tearDown() async throws { + try await super.tearDown() } @MainActor diff --git a/Tests/NodesTests/CoreTests/AbstractFlowTests.swift b/Tests/NodesTests/CoreTests/AbstractFlowTests.swift index 92fccc40d..0ac4e8c3e 100644 --- a/Tests/NodesTests/CoreTests/AbstractFlowTests.swift +++ b/Tests/NodesTests/CoreTests/AbstractFlowTests.swift @@ -28,14 +28,14 @@ final class AbstractFlowTests: XCTestCase, TestCaseHelpers { private var mockFlows: [FlowMock]! @MainActor - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() tearDown(keyPath: \.mockFlows, initialValue: [FlowMock(), FlowMock(), FlowMock()]) } @MainActor - override func tearDown() { - super.tearDown() + override func tearDown() async throws { + try await super.tearDown() } @MainActor diff --git a/Tests/NodesTests/CoreTests/AbstractWorkerTests.swift b/Tests/NodesTests/CoreTests/AbstractWorkerTests.swift index e9cc01695..f5e1b64c6 100644 --- a/Tests/NodesTests/CoreTests/AbstractWorkerTests.swift +++ b/Tests/NodesTests/CoreTests/AbstractWorkerTests.swift @@ -32,14 +32,14 @@ final class AbstractWorkerTests: XCTestCase, TestCaseHelpers { private var mockCancellables: [CancellableMock]! @MainActor - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() tearDown(keyPath: \.mockCancellables, initialValue: [CancellableMock(), CancellableMock(), CancellableMock()]) } @MainActor - override func tearDown() { - super.tearDown() + override func tearDown() async throws { + try await super.tearDown() } @MainActor diff --git a/Tests/NodesTests/InternalTests/FlowControllerTests.swift b/Tests/NodesTests/InternalTests/FlowControllerTests.swift index ad435f8e0..2b4263066 100644 --- a/Tests/NodesTests/InternalTests/FlowControllerTests.swift +++ b/Tests/NodesTests/InternalTests/FlowControllerTests.swift @@ -16,14 +16,14 @@ final class FlowControllerTests: XCTestCase, TestCaseHelpers { private var mockFlows: [FlowMock]! @MainActor - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() tearDown(keyPath: \.mockFlows, initialValue: [FlowMock(), FlowMock(), FlowMock()]) } @MainActor - override func tearDown() { - super.tearDown() + override func tearDown() async throws { + try await super.tearDown() } @MainActor diff --git a/Tests/NodesTests/InternalTests/WorkerControllerTests.swift b/Tests/NodesTests/InternalTests/WorkerControllerTests.swift index 46a8ccc00..3dfaeda32 100644 --- a/Tests/NodesTests/InternalTests/WorkerControllerTests.swift +++ b/Tests/NodesTests/InternalTests/WorkerControllerTests.swift @@ -16,14 +16,14 @@ final class WorkerControllerTests: XCTestCase, TestCaseHelpers { private var mockWorkers: [WorkerMock]! @MainActor - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() tearDown(keyPath: \.mockWorkers, initialValue: [WorkerMock(), WorkerMock(), WorkerMock()]) } @MainActor - override func tearDown() { - super.tearDown() + override func tearDown() async throws { + try await super.tearDown() } @MainActor diff --git a/Tests/NodesTests/UIKitTests/ExtensionsTests/UIViewController+ViewControllableTests.swift b/Tests/NodesTests/UIKitTests/ExtensionsTests/UIViewController+ViewControllableTests.swift index 4133dfe8f..0d2b21ab4 100644 --- a/Tests/NodesTests/UIKitTests/ExtensionsTests/UIViewController+ViewControllableTests.swift +++ b/Tests/NodesTests/UIKitTests/ExtensionsTests/UIViewController+ViewControllableTests.swift @@ -29,6 +29,16 @@ final class UIViewControllerViewControllableTests: XCTestCase { private(set) var willMoveCallCount: Int = 0 private(set) var didMoveCallCount: Int = 0 + override func willMove(toParent parent: UIViewController?) { + super.willMove(toParent: parent) + willMoveCallCount += 1 + } + + override func didMove(toParent parent: UIViewController?) { + super.didMove(toParent: parent) + didMoveCallCount += 1 + } + // swiftlint:disable unused_parameter override func present( @@ -47,16 +57,6 @@ final class UIViewControllerViewControllableTests: XCTestCase { } // swiftlint:enable unused_parameter - - override func willMove(toParent parent: UIViewController?) { - super.willMove(toParent: parent) - willMoveCallCount += 1 - } - - override func didMove(toParent parent: UIViewController?) { - super.didMove(toParent: parent) - didMoveCallCount += 1 - } } @MainActor diff --git a/bin/create-xcframework b/bin/create-xcframework deleted file mode 100755 index 2cc77a6ae..000000000 --- a/bin/create-xcframework +++ /dev/null @@ -1,368 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -BUILD_PATH="${PWD}/.build/xcframework" -LOG_PATH="${BUILD_PATH}/xcodebuild.log" - -LIBRARY_NAME="${1}" -PLATFORMS="${2}" -BITCODE="${3}" -RELEASE_VERSION="${4}" - -libraries() -{ - echo "$(make get-libraries)" -} - -deployment_target() -{ - local PLATFORM="${1}" - - echo "$(make get-deployment-target platform="${PLATFORM}")" -} - -includes_platform() -{ - local PLATFORM="${1}" - local PLATFORMS="${2}" - - grep -q "[[:space:]]${PLATFORM}[[:space:]]" <<< " ${PLATFORMS} " && echo "YES" || echo "NO" -} - -regex_replace() -{ - local FILE_PATH="${1}" - local PATTERN="${2}" - local REPLACE="${3}" - - perl -0777 -i\~ -pe "s/${PATTERN}/${REPLACE}/" "${FILE_PATH}" -} - -restore_package_manifest() -{ - rm -f Package.swift - mv Package.swift\~ Package.swift - echo "restored package manifest" -} - -archive_path() -{ - local BUILD_PATH="${1}" - local LIBRARY_NAME="${2}" - local DESTINATION="${3}" - - echo "${BUILD_PATH}/${LIBRARY_NAME}-${DESTINATION//[,= ]/-}.xcarchive" -} - -framework_path() -{ - local BUILD_PATH="${1}" - local LIBRARY_NAME="${2}" - local DESTINATION="${3}" - - local ARCHIVE_PATH="$(archive_path "${BUILD_PATH}" "${LIBRARY_NAME}" "${DESTINATION}")" - - echo "${ARCHIVE_PATH}/Products/usr/local/lib/${LIBRARY_NAME}.framework" -} - -copy_swift_module() -{ - local DERIVED_DATA_PATH="${1}" - local BUILD_PATH="${2}" - local LIBRARY_NAME="${3}" - local DESTINATION="${4}" - - local FRAMEWORK_PATH="$(framework_path "${BUILD_PATH}" "${LIBRARY_NAME}" "${DESTINATION}")" - local SWIFT_MODULE_PATH="$(find "${DERIVED_DATA_PATH}" -type d -name "${LIBRARY_NAME}.swiftmodule" | head -1)" - - mkdir "${FRAMEWORK_PATH}/Modules" - - cp -a "${SWIFT_MODULE_PATH}" "${FRAMEWORK_PATH}/Modules" -} - -archive_framework() -{ - local DERIVED_DATA_PATH=$(mktemp -d) - - local BUILD_PATH="${1}" - local LOG_PATH="${2}" - local LIBRARY_NAME="${3}" - local BITCODE_ENABLED="${4}" - local RELEASE_VERSION="${5}" - local DEPLOYMENT_TARGETS="${6}" - local DESTINATION="${7}" - - local ARCHIVE_PATH="$(archive_path "${BUILD_PATH}" "${LIBRARY_NAME}" "${DESTINATION}")" - local FRAMEWORK_PATH="$(framework_path "${BUILD_PATH}" "${LIBRARY_NAME}" "${DESTINATION}")" - - local OPTIONS="" - - if [[ "${BITCODE_ENABLED}" == "YES" ]] - then - OPTIONS="ENABLE_BITCODE=YES BITCODE_GENERATION_MODE=bitcode OTHER_C_FLAGS=-fembed-bitcode" - fi - - echo "=> ${DESTINATION}" - - set -x - xcodebuild \ - -scheme "${LIBRARY_NAME}" \ - -destination "generic/platform=${DESTINATION}" \ - -derivedDataPath "${DERIVED_DATA_PATH}" \ - -archivePath "${ARCHIVE_PATH}" \ - archive \ - ${DEPLOYMENT_TARGETS} \ - ${OPTIONS} \ - SWIFT_TREAT_WARNINGS_AS_ERRORS=YES \ - BUILD_LIBRARY_FOR_DISTRIBUTION=YES \ - SKIP_INSTALL=NO \ - >> "${LOG_PATH}" - set +x - - copy_swift_module "${DERIVED_DATA_PATH}" "${BUILD_PATH}" "${LIBRARY_NAME}" "${DESTINATION}" - - rm -rf "${DERIVED_DATA_PATH}" - - /usr/libexec/PlistBuddy \ - -c "Set :CFBundleVersion ${RELEASE_VERSION}" \ - -c "Set :CFBundleShortVersionString ${RELEASE_VERSION}" \ - "$(find "${FRAMEWORK_PATH}" -type f -name "Info.plist" | head -1)" -} - -xcframework_options() -{ - local BUILD_PATH="${1}" - local LIBRARY_NAME="${2}" - local BITCODE_ENABLED="${3}" - local DESTINATION="${4}" - - local ARCHIVE_PATH="$(archive_path "${BUILD_PATH}" "${LIBRARY_NAME}" "${DESTINATION}")" - local FRAMEWORK_PATH="$(framework_path "${BUILD_PATH}" "${LIBRARY_NAME}" "${DESTINATION}")" - local DEBUG_SYMBOLS="${ARCHIVE_PATH}/dSYMs/${LIBRARY_NAME}.framework.dSYM" - - local OPTIONS="-framework ${FRAMEWORK_PATH} -debug-symbols ${DEBUG_SYMBOLS}" - - if [[ "${BITCODE_ENABLED}" == "YES" ]] - then - OPTIONS+=" -debug-symbols $(find "${ARCHIVE_PATH}/BCSymbolMaps" -type f -name "*.bcsymbolmap" | head -1)" - fi - - echo "${OPTIONS}" -} - -if ! grep -q "^${LIBRARY_NAME}$" <<< "$(libraries)" -then - echo "invalid library: \"${LIBRARY_NAME}\"" - exit 1 -fi - -echo "BUILD_PATH=${BUILD_PATH/${PWD}\//}" -echo "LOG_PATH=${LOG_PATH/${PWD}\//}" - -echo "LIBRARY_NAME=${LIBRARY_NAME}" - -MACOS=$(includes_platform "macos" "${PLATFORMS}") -CATALYST=$(includes_platform "catalyst" "${PLATFORMS}") -IOS=$(includes_platform "ios" "${PLATFORMS}") -TVOS=$(includes_platform "tvos" "${PLATFORMS}") -WATCHOS=$(includes_platform "watchos" "${PLATFORMS}") - -echo "MACOS=${MACOS}" -echo "CATALYST=${CATALYST}" -echo "IOS=${IOS}" -echo "TVOS=${TVOS}" -echo "WATCHOS=${WATCHOS}" - -unset PLATFORMS - -if [[ "${BITCODE}" == "BITCODE_ENABLED" ]] -then - BITCODE_ENABLED="YES" -else - BITCODE_ENABLED="NO" -fi - -unset BITCODE - -echo "BITCODE_ENABLED=${BITCODE_ENABLED}" -echo "RELEASE_VERSION=${RELEASE_VERSION}" - -MACOS_CONFIG="MACOSX_DEPLOYMENT_TARGET=$(deployment_target "macos")" -IOS_CONFIG="IPHONEOS_DEPLOYMENT_TARGET=$(deployment_target "ios")" -TVOS_CONFIG="TVOS_DEPLOYMENT_TARGET=$(deployment_target "tvos")" -WATCHOS_CONFIG="WATCHOS_DEPLOYMENT_TARGET=$(deployment_target "watchos")" - -echo "${MACOS_CONFIG}" -echo "${IOS_CONFIG}" -echo "${TVOS_CONFIG}" -echo "${WATCHOS_CONFIG}" - -DEPLOYMENT_TARGETS="${MACOS_CONFIG} ${IOS_CONFIG} ${TVOS_CONFIG} ${WATCHOS_CONFIG}" - -unset MACOS_CONFIG IOS_CONFIG TVOS_CONFIG WATCHOS_CONFIG - -MACOS_DESTINATION="macOS" -MAC_CATALYST_DESTINATION="macOS,variant=Mac Catalyst" - -IOS_DESTINATION="iOS" -IOS_SIMULATOR_DESTINATION="iOS Simulator" - -TVOS_DESTINATION="tvOS" -TVOS_SIMULATOR_DESTINATION="tvOS Simulator" - -WATCHOS_DESTINATION="watchOS" -WATCHOS_SIMULATOR_DESTINATION="watchOS Simulator" - -ZIP_FILE_NAME="${LIBRARY_NAME}.xcframework-${RELEASE_VERSION}.zip" -ZIP_FILE_PATH="${BUILD_PATH}/${ZIP_FILE_NAME}" - -regex_replace \ - Package.swift \ - '(\.library\(\s*name: "'"${LIBRARY_NAME}"'",)(\s+)(type: \.\w+,\s+)?([a-z])' \ - '$1$2type: \.dynamic,$2$4' - -echo "modified package manifest" - -trap "restore_package_manifest;" EXIT - -rm -rf "${BUILD_PATH}" - -mkdir -p "${BUILD_PATH}" - -if [[ "${MACOS}" == "YES" ]] -then - archive_framework \ - "${BUILD_PATH}" \ - "${LOG_PATH}" \ - "${LIBRARY_NAME}" \ - "${BITCODE_ENABLED}" \ - "${RELEASE_VERSION}" \ - "${DEPLOYMENT_TARGETS}" \ - "${MACOS_DESTINATION}" -fi - -if [[ "${CATALYST}" == "YES" ]] -then - archive_framework \ - "${BUILD_PATH}" \ - "${LOG_PATH}" \ - "${LIBRARY_NAME}" \ - "${BITCODE_ENABLED}" \ - "${RELEASE_VERSION}" \ - "${DEPLOYMENT_TARGETS}" \ - "${MAC_CATALYST_DESTINATION}" -fi - -if [[ "${IOS}" == "YES" ]] -then - archive_framework \ - "${BUILD_PATH}" \ - "${LOG_PATH}" \ - "${LIBRARY_NAME}" \ - "${BITCODE_ENABLED}" \ - "${RELEASE_VERSION}" \ - "${DEPLOYMENT_TARGETS}" \ - "${IOS_DESTINATION}" - archive_framework \ - "${BUILD_PATH}" \ - "${LOG_PATH}" \ - "${LIBRARY_NAME}" \ - "${BITCODE_ENABLED}" \ - "${RELEASE_VERSION}" \ - "${DEPLOYMENT_TARGETS}" \ - "${IOS_SIMULATOR_DESTINATION}" -fi - -if [[ "${TVOS}" == "YES" ]] -then\ - archive_framework \ - "${BUILD_PATH}" \ - "${LOG_PATH}" \ - "${LIBRARY_NAME}" \ - "${BITCODE_ENABLED}" \ - "${RELEASE_VERSION}" \ - "${DEPLOYMENT_TARGETS}" \ - "${TVOS_DESTINATION}" - archive_framework \ - "${BUILD_PATH}" \ - "${LOG_PATH}" \ - "${LIBRARY_NAME}" \ - "${BITCODE_ENABLED}" \ - "${RELEASE_VERSION}" \ - "${DEPLOYMENT_TARGETS}" \ - "${TVOS_SIMULATOR_DESTINATION}" -fi - -if [[ "${WATCHOS}" == "YES" ]] -then - archive_framework \ - "${BUILD_PATH}" \ - "${LOG_PATH}" \ - "${LIBRARY_NAME}" \ - "${BITCODE_ENABLED}" \ - "${RELEASE_VERSION}" \ - "${DEPLOYMENT_TARGETS}" \ - "${WATCHOS_DESTINATION}" - archive_framework \ - "${BUILD_PATH}" \ - "${LOG_PATH}" \ - "${LIBRARY_NAME}" \ - "${BITCODE_ENABLED}" \ - "${RELEASE_VERSION}" \ - "${DEPLOYMENT_TARGETS}" \ - "${WATCHOS_SIMULATOR_DESTINATION}" -fi - -OPTIONS=() - -if [[ "${MACOS}" == "YES" ]] -then - OPTIONS+=($(xcframework_options "${BUILD_PATH}" "${LIBRARY_NAME}" "${BITCODE_ENABLED}" "${MACOS_DESTINATION}")) -fi - -if [[ "${CATALYST}" == "YES" ]] -then - OPTIONS+=($(xcframework_options "${BUILD_PATH}" "${LIBRARY_NAME}" "${BITCODE_ENABLED}" "${MAC_CATALYST_DESTINATION}")) -fi - -if [[ "${IOS}" == "YES" ]] -then - OPTIONS+=($(xcframework_options "${BUILD_PATH}" "${LIBRARY_NAME}" "${BITCODE_ENABLED}" "${IOS_DESTINATION}")) - OPTIONS+=($(xcframework_options "${BUILD_PATH}" "${LIBRARY_NAME}" "${BITCODE_ENABLED}" "${IOS_SIMULATOR_DESTINATION}")) -fi - -if [[ "${TVOS}" == "YES" ]] -then - OPTIONS+=($(xcframework_options "${BUILD_PATH}" "${LIBRARY_NAME}" "${BITCODE_ENABLED}" "${TVOS_DESTINATION}")) - OPTIONS+=($(xcframework_options "${BUILD_PATH}" "${LIBRARY_NAME}" "${BITCODE_ENABLED}" "${TVOS_SIMULATOR_DESTINATION}")) -fi - -if [[ "${WATCHOS}" == "YES" ]] -then - OPTIONS+=($(xcframework_options "${BUILD_PATH}" "${LIBRARY_NAME}" "${BITCODE_ENABLED}" "${WATCHOS_DESTINATION}")) - OPTIONS+=($(xcframework_options "${BUILD_PATH}" "${LIBRARY_NAME}" "${BITCODE_ENABLED}" "${WATCHOS_SIMULATOR_DESTINATION}")) -fi - -set -x -xcodebuild \ - -create-xcframework \ - "${OPTIONS[@]}" \ - -output "${BUILD_PATH}/${LIBRARY_NAME}.xcframework" \ - >> "${LOG_PATH}" -set +x - -unset OPTIONS - -if ! grep -q "xcframework successfully written out to: ${BUILD_PATH}/${LIBRARY_NAME}.xcframework" "${LOG_PATH}" -then - echo "failed to create xcframework" - exit 1 -fi - -(cd "${BUILD_PATH}" && zip -qry "${ZIP_FILE_NAME}" "${LIBRARY_NAME}.xcframework") - -echo "$(swift package compute-checksum "${ZIP_FILE_PATH}")" > "${ZIP_FILE_PATH}.checksum" - -echo "artifact: ${ZIP_FILE_PATH/${PWD}\//}" -echo "checksum: ${ZIP_FILE_PATH/${PWD}\//}.checksum" diff --git a/bin/get-deployment-target b/bin/get-deployment-target deleted file mode 100755 index 98327a4d5..000000000 --- a/bin/get-deployment-target +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env swift - -import Foundation - -let args: [String] = Array(CommandLine.arguments.dropFirst()) - -guard let platformName: String = args.first -else { exit(EXIT_FAILURE) } - -let task: Process = .init() -let pipe: Pipe = .init() - -task.standardOutput = pipe -task.launchPath = "/usr/bin/env" -task.arguments = ["swift", "package", "dump-package"] -task.launch() -task.waitUntilExit() - -let data: Data = pipe.fileHandleForReading.readDataToEndOfFile() - -guard let object: Any = try? JSONSerialization.jsonObject(with: data), - let json: [String: Any] = object as? [String: Any], - let platforms: [[String: Any]] = json["platforms"] as? [[String: Any]], - let platform: [String: Any] = platforms.first(where: { $0["platformName"] as? String == platformName }), - let version: String = platform["version"] as? String -else { exit(EXIT_FAILURE) } - -print(version) diff --git a/bin/get-libraries b/bin/get-libraries deleted file mode 100755 index f75dac4b7..000000000 --- a/bin/get-libraries +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env swift - -import Foundation - -let task: Process = .init() -let pipe: Pipe = .init() - -task.standardOutput = pipe -task.launchPath = "/usr/bin/env" -task.arguments = ["swift", "package", "dump-package"] -task.launch() -task.waitUntilExit() - -let data: Data = pipe.fileHandleForReading.readDataToEndOfFile() - -guard let object: Any = try? JSONSerialization.jsonObject(with: data), - let json: [String: Any] = object as? [String: Any], - let products: [[String: Any]] = json["products"] as? [[String: Any]] -else { exit(EXIT_FAILURE) } - -products - .compactMap { - guard let name: String = $0["name"] as? String, - let type: [String: Any] = $0["type"] as? [String: Any], - type["library"] != nil - else { return nil} - return name - } - .forEach { print($0) } diff --git a/bin/get-platforms b/bin/get-platforms deleted file mode 100755 index e58a47512..000000000 --- a/bin/get-platforms +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env swift - -import Foundation - -let task: Process = .init() -let pipe: Pipe = .init() - -task.standardOutput = pipe -task.launchPath = "/usr/bin/env" -task.arguments = ["swift", "package", "dump-package"] -task.launch() -task.waitUntilExit() - -let data: Data = pipe.fileHandleForReading.readDataToEndOfFile() - -guard let object: Any = try? JSONSerialization.jsonObject(with: data), - let json: [String: Any] = object as? [String: Any], - let platforms: [[String: Any]] = json["platforms"] as? [[String: Any]] -else { exit(EXIT_FAILURE) } - -platforms - .compactMap { $0["platformName"] as? String } - .forEach { print($0) } diff --git a/genesis.yml b/genesis.yml index ffa65fcca..efa89428a 100644 --- a/genesis.yml +++ b/genesis.yml @@ -59,8 +59,9 @@ files: - 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 @@ -144,7 +145,6 @@ files: - implicitly_unwrapped_optional - inclusive_language # - indentation_width - - inert_defer - invalid_swiftlint_command - is_disjoint - joined_default_parameter @@ -195,6 +195,7 @@ files: - opening_brace - operator_usage_whitespace - operator_whitespace + - optional_data_string_conversion - optional_enum_case_matching - orphaned_doc_comment - overridden_super_call @@ -205,6 +206,7 @@ files: - 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 @@ -227,6 +229,7 @@ files: - redundant_objc_attribute - redundant_optional_initialization - redundant_self_in_closure + - redundant_sendable - redundant_set_access_control # - redundant_string_enum_value - redundant_type_annotation @@ -274,7 +277,6 @@ files: - unneeded_synthesized_initializer - unowned_variable_capture - untyped_error_in_catch - - unused_capture_list - unused_closure_parameter - unused_control_flow_label - unused_enumerated @@ -891,12 +893,12 @@ files: {% if path|replace:' ','' %} path: "{{ path }}"), {% else %} - url: "git@github.com:Tinder/Nodes.git", + url: "https://github.com/Tinder/Nodes.git", exact: "{{ nodes }}"), {% endif %} .package( url: "https://github.com/realm/SwiftLint.git", - exact: "0.56.2"), + exact: "0.59.1"), ] ) @@ -966,8 +968,8 @@ files: create "{{ project|replace:' ','_' }}/Sources/Bootstrap/Scene" create "{{ project|replace:' ','_' }}/Sources/Bootstrap/Window" create "{{ project|replace:' ','_' }}/Sources/Screens/Root" - find "{{ project|replace:' ','_' }}/Sources" -type f -name "*.swift" -exec sed -i '' '/@MainActor/,+0d' {} \; fi + find "{{ project|replace:' ','_' }}/Sources" -type f -name "*.swift" -exec sed -i '' '/@MainActor/,+0d' {} \; NEEDLE_GENERATED="{{ project|replace:' ','_' }}/Generated/NeedleGenerated.swift" MOCKOLO_GENERATED="{{ project|replace:' ','_' }}Tests/Generated/MockoloGenerated.swift" [[ -f "$NEEDLE_GENERATED" ]] || touch "$NEEDLE_GENERATED" @@ -1009,7 +1011,7 @@ files: {% if path|replace:' ','' %} path: {{ path }} {% else %} - url: git@github.com:Tinder/Nodes.git + url: https://github.com/Tinder/Nodes.git version: {{ nodes }} {% endif %} NeedleFoundation: @@ -1017,7 +1019,7 @@ files: version: 0.25.1 Nimble: url: https://github.com/Quick/Nimble.git - version: 13.4.0 + version: 14.0.0 configFiles: Debug: BuildSettings/Debug.xcconfig Release: BuildSettings/Release.xcconfig @@ -1131,7 +1133,7 @@ files: # https://github.com/realm/SwiftLint/blob/0.52.4/Source/swiftlint/Commands/SwiftLint.swift#L8 unset BUILD_WORKSPACE_DIRECTORY - "$(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)" else echo "SwiftLint is skipped in CI." fi