diff --git a/.github/workflows/master-push.yml b/.github/workflows/master-push.yml index fbe19232e3..de84ea0260 100644 --- a/.github/workflows/master-push.yml +++ b/.github/workflows/master-push.yml @@ -6,7 +6,10 @@ on: - "master" - "release/**" env: - XCODE_VERSION: "['14.2', '14.3.1', '15.1', '15.2']" + XCODE_VERSION: "['14.2', '14.3.1', '15.1', '15.2', '15.3']" + # Github actions doesn't have Xcode 15.3 on any runners yet, so we can't run + # installation tests for it + XCODE_TEST_VERSIONS: "['14.2', '14.3.1', '15.1', '15.2']" PLATFORM: "['ios', 'osx', 'watchos', 'tvos', 'catalyst', 'visionos']" BUILD_PLATFORM: "['ios', 'iossimulator', 'osx', 'watchos', 'watchossimulator', 'tvos', 'tvossimulator', 'catalyst', 'visionos', 'visionossimulator']" DOC_VERSION: '15.2' @@ -31,6 +34,7 @@ jobs: needs: [cleanup] outputs: XCODE_VERSIONS_MATRIX: ${{ env.XCODE_VERSION }} + XCODE_TEST_VERSIONS_MATRIX: ${{ env.XCODE_TEST_VERSIONS }} BUILD_PLATFORM_MATRIX: ${{ env.BUILD_PLATFORM }} PLATFORM_MATRIX: ${{ env.PLATFORM }} VERSION: ${{ steps.get-version.outputs.VERSION }} @@ -47,7 +51,7 @@ jobs: version="$(sed -n 's/^VERSION=\(.*\)$/\1/p' "${GITHUB_WORKSPACE}/dependencies.list")" echo "VERSION=$version" >> $GITHUB_OUTPUT build-docs: - runs-on: macos-13 + runs-on: macos-14 name: Package docs needs: prepare steps: @@ -65,7 +69,7 @@ jobs: name: realm-docs path: docs/realm-docs.zip build-examples: - runs-on: macos-13 + runs-on: macos-14 name: Package examples needs: prepare steps: @@ -78,7 +82,7 @@ jobs: name: realm-examples path: realm-examples.zip build-product: # Creates framework for each platform, xcode version, target and configuration - runs-on: macos-13 + runs-on: macos-14 name: Package framework needs: prepare strategy: @@ -177,7 +181,7 @@ jobs: path: xcode-cloud-build-${{ steps.build-run.outputs.BUILD_RUN_ID }}.zip compression-level: 0 package-xcframework-platform: # Creates xcframework for each platform and xcode version - runs-on: macos-13 + runs-on: macos-14 name: Package xcframework for platform needs: [build-product, prepare] strategy: @@ -194,7 +198,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Select Xcode Version - run: sudo xcode-select -switch /Applications/Xcode_${{ matrix.xcode-version }}.app + run: sudo xcode-select -switch /Applications/Xcode_${{ env.RELEASE_VERSION }}.app - name: Restore frameworks uses: actions/download-artifact@v4 with: @@ -207,7 +211,7 @@ jobs: name: realm-${{ matrix.platform }}-${{ matrix.xcode-version }} path: realm-${{ matrix.platform }}-${{ matrix.xcode-version }}.zip package-release: # Creates xcframework for each platform and xcode version - runs-on: macos-13 + runs-on: macos-14 name: Package release file needs: [package-xcframework-platform, prepare] steps: @@ -231,7 +235,7 @@ jobs: name: realm-swift-${{ needs.prepare.outputs.VERSION }} path: pkg/realm-swift-${{ needs.prepare.outputs.VERSION }}.zip test-package-examples: - runs-on: macos-13 + runs-on: macos-14 name: Test examples needs: [package-release, prepare] steps: @@ -245,7 +249,7 @@ jobs: - name: Test examples run: sh -x build.sh release-test-examples test-ios-static: - runs-on: macos-13 + runs-on: macos-14 name: Run tests on iOS with configuration Static needs: package-release steps: @@ -255,7 +259,7 @@ jobs: - name: Test ios static run: sh -x build.sh test-ios-static test-osx-static: - runs-on: macos-13 + runs-on: macos-14 name: Run tests on macOS needs: package-release steps: @@ -267,7 +271,7 @@ jobs: export REALM_DISABLE_METADATA_ENCRYPTION=1 sh -x build.sh test-osx test-installation: - runs-on: macos-13 + runs-on: macos-14 name: Run installation test needs: [package-release, prepare] strategy: @@ -317,7 +321,7 @@ jobs: PLATFORM: 'osx' strategy: matrix: - xcode-version: ${{ fromJSON(needs.prepare.outputs.XCODE_VERSIONS_MATRIX) }} + xcode-version: ${{ fromJSON(needs.prepare.outputs.XCODE_TEST_VERSIONS_MATRIX) }} steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 55bb94acb5..47a2546bfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,19 +2,21 @@ x.y.z Release notes (yyyy-MM-dd) ============================================================= ### Enhancements * Lifted a limitation that would prevent declaring a model with only computed properties. ([#8414](https://github.com/realm/realm-swift/issues/8414)) +* Add Xcode 15.3 to the release package ([PR #8502](https://github.com/realm/realm-swift/pull/8502)). ### Fixed * ([#????](https://github.com/realm/realm-swift/issues/????), since v?.?.?) * Fix multiple arguments support via the `REALM_EXTRA_BUILD_ARGUMENTS` environment variable in `build.sh`. ([PR #8413](https://github.com/realm/realm-swift/pulls/8413)). Thanks, [@hisaac](https://github.com/hisaac)! +* Fix some of the new sendability warnings introduced in Xcode 15.3 ([PR #8502](https://github.com/realm/realm-swift/pull/8502)). ### Compatibility * Realm Studio: 14.0.1 or later. * APIs are backwards compatible with all previous releases in the 10.x.y series. -* Carthage release for Swift is built with Xcode 15.2.0. +* Carthage release for Swift is built with Xcode 15.3.0. * CocoaPods: 1.10 or later. -* Xcode: 14.2-15.2.0. +* Xcode: 14.2-15.3.0. ### Internal * Upgraded realm-core from ? to ? diff --git a/Gemfile b/Gemfile index 46479e192a..b3bb1e1371 100644 --- a/Gemfile +++ b/Gemfile @@ -3,5 +3,6 @@ source "https://rubygems.org" gem 'cocoapods' gem 'fileutils' gem 'jazzy' +gem 'jwt' gem 'octokit' gem 'pathname' diff --git a/Gemfile.lock b/Gemfile.lock index 7680647e13..6f9e8f22e2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -90,6 +90,8 @@ GEM sqlite3 (~> 1.3) xcinvoke (~> 0.3.0) json (2.7.1) + jwt (2.8.1) + base64 liferaft (0.0.6) minitest (5.22.2) molinillo (0.8.0) @@ -135,6 +137,7 @@ GEM rexml (~> 3.2.4) PLATFORMS + arm64-darwin-22 arm64-darwin-23 x86_64-darwin-20 @@ -142,6 +145,7 @@ DEPENDENCIES cocoapods fileutils jazzy + jwt octokit pathname diff --git a/Realm/Tests/SwiftUITestHost/SwiftUITestHostApp.swift b/Realm/Tests/SwiftUITestHost/SwiftUITestHostApp.swift index 82963fe89d..66568b7d6b 100644 --- a/Realm/Tests/SwiftUITestHost/SwiftUITestHostApp.swift +++ b/Realm/Tests/SwiftUITestHost/SwiftUITestHostApp.swift @@ -163,6 +163,7 @@ struct Footer: View { } } +@MainActor struct ContentView: View { @State var searchFilter: String = "" diff --git a/RealmSwift/BSON.swift b/RealmSwift/BSON.swift index 18399572ab..978b9d9992 100644 --- a/RealmSwift/BSON.swift +++ b/RealmSwift/BSON.swift @@ -20,7 +20,7 @@ import Realm /// A tag protocol which marks types that can be used as the partition value /// for synchronized Realms. -public protocol PartitionValue { +public protocol PartitionValue: Sendable { } /// Protocol representing a BSON value. diff --git a/RealmSwift/Impl/RealmCollectionImpl.swift b/RealmSwift/Impl/RealmCollectionImpl.swift index 45f2184d89..8792250f56 100644 --- a/RealmSwift/Impl/RealmCollectionImpl.swift +++ b/RealmSwift/Impl/RealmCollectionImpl.swift @@ -185,7 +185,15 @@ internal func with( let unchecked = Unchecked(wrappedValue: value) return try await actor.invoke { actor in if !Task.isCancelled { +#if swift(>=5.10) + // As of Swift 5.10 the compiler incorrectly thinks that this + // is an async hop even though the isolation context is + // unchanged. This is fixed in 5.11. + nonisolated(unsafe) let value = unchecked.wrappedValue + return try await block(actor, value) +#else return try await block(actor, unchecked.wrappedValue) +#endif } return nil } @@ -202,7 +210,15 @@ internal func with( guard let value = tsr.resolve(in: realm) else { return nil } +#if swift(>=5.10) + // As above; this is safe but 5.10's sendability checking can't prove it + // nonisolated(unsafe) can't be applied to a let in guard so we need + // a second variable + nonisolated(unsafe) let v = value + return try await block(actor, v) +#else return try await block(actor, value) +#endif } } #endif diff --git a/RealmSwift/Projection.swift b/RealmSwift/Projection.swift index 53af3a03ec..a655ca5b1c 100644 --- a/RealmSwift/Projection.swift +++ b/RealmSwift/Projection.swift @@ -788,28 +788,22 @@ private struct ProjectionProperty: @unchecked Sendable { let label: String } -// An adaptor for os_unfair_lock to make it implement NSLocking -@available(OSX 10.12, watchOS 3.0, iOS 10.0, tvOS 10.0, *) -private final class UnfairLock: NSLocking, Sendable { - func lock() { - os_unfair_lock_lock(impl) - } - func unlock() { - os_unfair_lock_unlock(impl) - } - +// A subset of OSAllocatedUnfairLock, which requires iOS 16 +internal final class AllocatedUnfairLock: @unchecked Sendable { + private var value: Value private let impl: os_unfair_lock_t = .allocate(capacity: 1) - init() { + + init(_ value: Value) { impl.initialize(to: os_unfair_lock()) + self.value = value } -} -// We want to use os_unfair_lock when it's available, but fall back to NSLock otherwise -private func createLock() -> NSLocking { - if #available(macOS 10.12, watchOS 3.0, iOS 10.0, tvOS 10.0, *) { - return UnfairLock() + func withLock(_ body: (inout Value) -> R) -> R { + os_unfair_lock_lock(impl) + let ret = body(&value) + os_unfair_lock_unlock(impl) + return ret } - return NSLock() } // A property wrapper which unsafely disables concurrency checking for a property @@ -828,12 +822,11 @@ internal struct Unchecked: @unchecked Sendable { } private final class ProjectionSchemaCache: @unchecked Sendable { - @Unchecked private static var schema = [ObjectIdentifier: [ProjectionProperty]]() - private static let lock = createLock() + private static let schema = AllocatedUnfairLock([ObjectIdentifier: [ProjectionProperty]]()) fileprivate func schema(for obj: T) -> [ProjectionProperty] { let identifier = ObjectIdentifier(type(of: obj)) - if let schema = Self.lock.withLock({ Self.schema[identifier] }) { + if let schema = Self.schema.withLock({ $0[identifier] }) { return schema } @@ -850,11 +843,12 @@ private final class ProjectionSchemaCache: @unchecked Sendable { originPropertyKeyPathString: originPropertyLabel, label: String(label))) } - Self.lock.withLock { + let p = properties + Self.schema.withLock { // This might overwrite a schema generated by a different thread // if we happened to do the initialization on multiple threads at // once, but if so that's fine. - Self.schema[identifier] = properties + $0[identifier] = p } return properties } diff --git a/RealmSwift/Query.swift b/RealmSwift/Query.swift index f6af381289..95b7429196 100644 --- a/RealmSwift/Query.swift +++ b/RealmSwift/Query.swift @@ -21,7 +21,7 @@ import Realm import Realm.Private /// Enum representing an option for `String` queries. -public struct StringOptions: OptionSet { +public struct StringOptions: OptionSet, Sendable { /// :doc: public let rawValue: Int8 /// :doc: diff --git a/RealmSwift/SwiftUI.swift b/RealmSwift/SwiftUI.swift index 5eade0d1a8..c689d66634 100644 --- a/RealmSwift/SwiftUI.swift +++ b/RealmSwift/SwiftUI.swift @@ -117,10 +117,22 @@ private func createEquatableBinding( /// Objects must have observers removed before being added to a realm. /// They are stored here so that if they are appended through the Bound Property /// system, they can be de-observed before hand. - @Unchecked - fileprivate static var observedObjects = [NSObject: SwiftUIKVO.Subscription]() + private static let observedObjects = AllocatedUnfairLock([NSObject: Subscription]()) + + static func store(_ obj: NSObject, _ subscription: Subscription) { + SwiftUIKVO.observedObjects.withLock { + $0[obj] = subscription + } + } + + static func cancel(_ obj: NSObject) { + SwiftUIKVO.observedObjects.withLock { + if let subscription: Subscription = $0.removeValue(forKey: obj) { + subscription.removeObservers() + } + } + } - @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) struct Subscription: Combine.Subscription { let observer: NSObject let value: NSObject @@ -134,23 +146,16 @@ private func createEquatableBinding( } func cancel() { - removeObservers() - SwiftUIKVO.observedObjects.removeValue(forKey: value) + SwiftUIKVO.cancel(value) } fileprivate func removeObservers() { - guard SwiftUIKVO.observedObjects.keys.contains(value) else { - return - } keyPaths.forEach { value.removeObserver(observer, forKeyPath: $0) } } fileprivate func addObservers() { - guard SwiftUIKVO.observedObjects.keys.contains(value) else { - return - } keyPaths.forEach { value.addObserver(observer, forKeyPath: $0, options: .init(), context: nil) } @@ -230,7 +235,7 @@ private final class ObservableStoragePublisher: Publisher where Obje } let subscription = SwiftUIKVO.Subscription(observer: kvo, value: value, keyPaths: keyPaths) subscriber.receive(subscription: subscription) - SwiftUIKVO.observedObjects[value] = subscription + SwiftUIKVO.store(value, subscription) } } } @@ -1163,7 +1168,7 @@ public extension BoundCollection where Value == List, Element: ObjectBa func append(_ value: Value.Element) { write { list in if value.realm == nil && list.realm != nil { - SwiftUIKVO.observedObjects[value]?.cancel() + SwiftUIKVO.cancel(value) } list.append(thawObjectIfFrozen(value)) } @@ -1217,7 +1222,7 @@ public extension BoundCollection where Value == MutableSet, Element: Ob func insert(_ value: Value.Element) { write { mutableSet in if value.realm == nil && mutableSet.realm != nil { - SwiftUIKVO.observedObjects[value]?.cancel() + SwiftUIKVO.cancel(value) } mutableSet.insert(thawObjectIfFrozen(value)) } @@ -1230,7 +1235,7 @@ public extension BoundCollection where Value == Results, Element: Objec func append(_ value: Value.Element) { write { results in if value.realm == nil && results.realm != nil { - SwiftUIKVO.observedObjects[value]?.cancel() + SwiftUIKVO.cancel(value) } results.realm?.add(thawObjectIfFrozen(value)) } @@ -1243,7 +1248,7 @@ public extension BoundCollection where Value == Results, Element: Proje func append(_ value: Value.Element) { write { results in if value.realm == nil && results.realm != nil { - SwiftUIKVO.observedObjects[value.rootObject]?.cancel() + SwiftUIKVO.cancel(value.rootObject) } results.realm?.add(thawObjectIfFrozen(value.rootObject)) } @@ -1305,7 +1310,7 @@ public extension BoundMap where Value.Value: ObjectBase & ThreadConfined { } // if the value is unmanaged but the map is managed, we are adding this value to the realm if value.realm == nil && self.wrappedValue.realm != nil { - SwiftUIKVO.observedObjects[value]?.cancel() + SwiftUIKVO.cancel(value) } write(self.wrappedValue) { map in var m = map @@ -1854,17 +1859,18 @@ private class ObservableAsyncOpenStorage: ObservableObject { @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension SwiftUIKVO { @objc(removeObserversFromObject:) static func removeObservers(object: NSObject) -> Bool { - if let subscription = SwiftUIKVO.observedObjects[object] { - subscription.removeObservers() - return true - } else { + Self.observedObjects.withLock { + if let subscription = $0[object] { + subscription.removeObservers() + return true + } return false } } @objc(addObserversToObject:) static func addObservers(object: NSObject) { - if let subscription = SwiftUIKVO.observedObjects[object] { - subscription.addObservers() + Self.observedObjects.withLock { + $0[object]?.addObservers() } } } diff --git a/build.sh b/build.sh index 503a90c325..2b492c6938 100755 --- a/build.sh +++ b/build.sh @@ -1343,9 +1343,9 @@ x.y.z Release notes (yyyy-MM-dd) ### Compatibility * Realm Studio: 14.0.1 or later. * APIs are backwards compatible with all previous releases in the 10.x.y series. -* Carthage release for Swift is built with Xcode 15.2.0. +* Carthage release for Swift is built with Xcode 15.3.0. * CocoaPods: 1.10 or later. -* Xcode: 14.2-15.2.0. +* Xcode: 14.2-15.3.0. ### Internal * Upgraded realm-core from ? to ? diff --git a/ci_scripts/ci_post_clone.sh b/ci_scripts/ci_post_clone.sh index 82bd376c7f..7fa373d0b1 100755 --- a/ci_scripts/ci_post_clone.sh +++ b/ci_scripts/ci_post_clone.sh @@ -77,6 +77,11 @@ if [[ "$target" == "release-package-build-"* ]]; then sed -i '' "s/REALM_HIDE_SYMBOLS = NO;/REALM_HIDE_SYMBOLS = YES;/" "$filename" fi +# Xcode cloud currently doesn't have visionOS installed for Xcode 15.3 +if [[ "$CI_WORKFLOW" == release-package-build-vision*_15.3 ]]; then + xcodebuild -downloadAllPlatforms +fi + # If we're building the dummy CI target then run the test. Other schemes are # built via Xcode cloud's xcodebuild invocation. We can't do this via a build # step on the CI target as that results in nested invocations of xcodebuild, diff --git a/contrib/UpgradingXcode.md b/contrib/UpgradingXcode.md index 653c183cf9..7d7cb86260 100644 --- a/contrib/UpgradingXcode.md +++ b/contrib/UpgradingXcode.md @@ -12,7 +12,7 @@ Check https://developer.apple.com/documentation/xcode-release-notes to see new X 3. Enable manually the new created workflows. 4. If needed, add environment values to the newly created workflows. 5. Update version(s) from xcode_versions in `scripts/package-examples.rb`. -6. Update XCODE_VERSION in `master-push.yml` and check if DOC_VERSION, RELEASE_VERSION and TEST_VERSION needs to be updated. +6. Update XCODE_VERSION in `.github/workflows/master-push.yml` and check if DOC_VERSION, RELEASE_VERSION and TEST_VERSION needs to be updated. 7. Search for `#if swift` and see if there's any we can remove. 8. Update the Carthage version in CHANGELOG.md (and add a changelog entry). 9. If there's new project settings migrations, open each of the Xcode projects and apply/skip them as applicable. Note that we generally do *not* want to use the Swift version migrations as we support multiple Swift versions at once. diff --git a/scripts/create-release-package.rb b/scripts/create-release-package.rb index ca4662478e..87f74c7882 100755 --- a/scripts/create-release-package.rb +++ b/scripts/create-release-package.rb @@ -20,7 +20,7 @@ def sh(*args) end def platforms(xcode_version) - if xcode_version.start_with? '15.2' + if xcode_version.to_f >= 15.2 %w{osx ios watchos tvos catalyst visionos} else %w{osx ios watchos tvos catalyst} diff --git a/scripts/package_examples.rb b/scripts/package_examples.rb index 4562c7f4a0..1c9fd67a5c 100755 --- a/scripts/package_examples.rb +++ b/scripts/package_examples.rb @@ -44,7 +44,7 @@ def replace_framework(example, framework, path) "examples/tvos/swift", ] -xcode_versions = %w(14.2 14.3.1 15.1 15.2) +xcode_versions = %w(14.2 14.3.1 15.1 15.2 15.3) # Remove reference to Realm.xcodeproj from all example workspaces. base_examples.each do |example| diff --git a/scripts/pr-ci-matrix.rb b/scripts/pr-ci-matrix.rb index 9c74daa09a..4b742bb70b 100755 --- a/scripts/pr-ci-matrix.rb +++ b/scripts/pr-ci-matrix.rb @@ -86,7 +86,7 @@ def action # because they don't care about Xcode versions, while some others are latest-only # because they're particularly slow to run. module Workflows - XCODE_VERSIONS = %w(14.2 14.3.1 15.1 15.2) + XCODE_VERSIONS = %w(14.2 14.3.1 15.1 15.2 15.3) all = ->(v) { true } latest_only = ->(v) { v == XCODE_VERSIONS.last } @@ -112,7 +112,7 @@ module Workflows Target.new('catalyst-swift', 'RealmSwift', oldest_and_latest, Destination.catalyst), Target.new('watchos', 'Realm', oldest_and_latest, Destination.generic), - Target.new('watchos', 'RealmSwift', oldest_and_latest, Destination.generic), + Target.new('watchos-swift', 'RealmSwift', oldest_and_latest, Destination.generic), Target.new('swiftui', 'SwiftUITests', latest_only, Destination.iOS), Target.new('swiftui-sync', 'SwiftUISyncTests', latest_only, Destination.macOS), diff --git a/scripts/xcode_cloud_helper.rb b/scripts/xcode_cloud_helper.rb index 064c36a85b..52726474f9 100755 --- a/scripts/xcode_cloud_helper.rb +++ b/scripts/xcode_cloud_helper.rb @@ -145,15 +145,15 @@ def get_artifact_info(id) get("/ciArtifacts/#{id}") end -def create_workflow(target, xcode_version) - result = post('ciWorkflows', create_workflow_request(target, xcode_version)) +def create_workflow(target, xcode_version, pull_request) + result = post('ciWorkflows', create_workflow_request(target, xcode_version, pull_request)) id = result["data"]["id"] return id end -def create_workflow_request(target, xcode_version) +def create_workflow_request(target, xcode_version, pull_request) xcode_version_id = get_xcode_id(xcode_version) - return { + data = { data: { type: 'ciWorkflows', attributes: { @@ -161,19 +161,8 @@ def create_workflow_request(target, xcode_version) description: 'Create by Github Action Update XCode Cloud Workflows', isLockedForEditing: false, containerFilePath: 'Realm.xcodeproj', - isEnabled: false, + isEnabled: true, clean: false, - pullRequestStartCondition: { - source: { - isAllMatch: true, - patterns: [] - }, - destination: { - isAllMatch: true, - patterns: [] - }, - autoCancel: true - }, actions: [target.action] }, relationships: { @@ -204,6 +193,30 @@ def create_workflow_request(target, xcode_version) } } } + + if pull_request + data[:data][:attributes][:pullRequestStartCondition] = { + source: { + isAllMatch: true, + }, + destination: { + isAllMatch: true, + }, + autoCancel: true + } + else + data[:data][:attributes][:manualBranchStartCondition] = { + source: { + isAllMatch: true, + }, + destination: { + isAllMatch: true, + }, + autoCancel: true + } + end + + data end def enable_workflow(id) @@ -274,6 +287,8 @@ def synchronize_workflows() } current_workflows = get_workflows.filter_map { |workflow| name = workflow['attributes']['name'] + # don't touch release pipeline jobs + next if name.start_with? 'release-' pieces = name.partition('_') {name: pieces.first, version: pieces.last, id: workflow['id']} } @@ -316,7 +331,7 @@ def synchronize_workflows() end workflows_to_create.each { |w| - id = create_workflow(w[:target], w[:version]) + id = create_workflow(w[:target], w[:version], true) puts "#{w[:target]}: https://appstoreconnect.apple.com/teams/69a6de86-7f37-47e3-e053-5b8c7c11a4d1/frameworks/#{get_realm_product_id}/workflows/#{id}" } workflows_to_remove.each { |w| @@ -559,7 +574,7 @@ def usage() configuration = ARGV.shift usage unless platform and xcode_version and target and configuration release_target = ReleaseTarget.new("#{prefix}-#{platform}-#{target}-#{configuration}", target, platform) - id = create_workflow(release_target, xcode_version) + id = create_workflow(release_target, xcode_version, false) puts id when 'delete-workflow' workflow_id = ARGV.shift