diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ceedeba3e615..ff460ca721a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: - name: Select Xcode ${{ matrix.xcode }} run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app - name: Update xcbeautify - run: brew upgrade xcbeautify + run: brew update && brew upgrade xcbeautify - name: List available devices run: xcrun simctl list devices available - name: Cache derived data @@ -52,23 +52,27 @@ jobs: strategy: matrix: command: [test, ''] - platform: [IOS, MAC_CATALYST, MACOS, TVOS, VISIONOS, WATCHOS] + platform: + - IOS + - MAC_CATALYST + - MACOS + - TVOS + # - VISIONOS # Unfortunately, visionOS on CI is too flakey + - WATCHOS xcode: [15.2, 15.4] exclude: - {xcode: 15.2, command: test} - {xcode: 15.4, command: ''} - {xcode: 15.2, platform: MAC_CATALYST} - {xcode: 15.2, platform: TVOS} - - {xcode: 15.2, platform: VISIONOS} + # - {xcode: 15.2, platform: VISIONOS} - {xcode: 15.2, platform: WATCHOS} - include: - - {xcode: 15.2, skip_release: 1} steps: - uses: actions/checkout@v4 - name: Select Xcode ${{ matrix.xcode }} run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app - name: Update xcbeautify - run: brew upgrade xcbeautify + run: brew update && brew upgrade xcbeautify - name: Install visionOS runtime if: matrix.platform == 'visionOS' run: | @@ -93,9 +97,6 @@ jobs: uses: chetan/git-restore-mtime-action@v2 - name: Debug run: make XCODEBUILD_ARGUMENT="${{ matrix.command }}" CONFIG=Debug PLATFORM="${{ matrix.platform }}" WORKSPACE=.github/package.xcworkspace xcodebuild - - name: Release - if: matrix.skip_release != '1' - run: make XCODEBUILD_ARGUMENT="${{ matrix.command }}" CONFIG=Release PLATFORM="${{ matrix.platform }}" WORKSPACE=.github/package.xcworkspace xcodebuild library-evolution: name: Library (evolution) @@ -105,7 +106,7 @@ jobs: - name: Select Xcode 15.4 run: sudo xcode-select -s /Applications/Xcode_15.4.app - name: Update xcbeautify - run: brew upgrade xcbeautify + run: brew update && brew upgrade xcbeautify - name: Build for library evolution run: make build-for-library-evolution @@ -125,7 +126,7 @@ jobs: - name: Select Xcode 16 run: sudo xcode-select -s /Applications/Xcode_16.2.app - name: Update xcbeautify - run: brew upgrade xcbeautify + run: brew update && brew upgrade xcbeautify - name: Set IgnoreFileSystemDeviceInodeChanges flag run: defaults write com.apple.dt.XCBuild IgnoreFileSystemDeviceInodeChanges -bool YES - name: Update mtime for incremental builds diff --git a/Examples/VoiceMemos/VoiceMemosTests/VoiceMemosTests.swift b/Examples/VoiceMemos/VoiceMemosTests/VoiceMemosTests.swift index b3b5444195b7..1a35760133e5 100644 --- a/Examples/VoiceMemos/VoiceMemosTests/VoiceMemosTests.swift +++ b/Examples/VoiceMemos/VoiceMemosTests/VoiceMemosTests.swift @@ -12,12 +12,14 @@ struct VoiceMemosTests { @Test func recordAndPlayback() async throws { let didFinish = AsyncThrowingStream.makeStream(of: Bool.self) - let clock = TestClock() + // NB: We would prefer to use a test clock here, but due to testing async still being unreliable + // in Swift, we will use a real clock and sleep, instead. + // let clock = TestClock() let store = TestStore(initialState: VoiceMemos.State()) { VoiceMemos() } withDependencies: { $0.audioPlayer.play = { @Sendable _ in - try await clock.sleep(for: .milliseconds(2_500)) + try await Task.sleep(for: .milliseconds(2_500)) return true } $0.audioRecorder.currentTime = { 2.5 } @@ -30,7 +32,7 @@ struct VoiceMemosTests { didFinish.continuation.finish() } $0.date = .constant(Date(timeIntervalSinceReferenceDate: 0)) - $0.continuousClock = clock + $0.continuousClock = ContinuousClock() $0.temporaryDirectory = { URL(fileURLWithPath: "/tmp") } $0.uuid = .constant(deadbeefID) } @@ -68,7 +70,7 @@ struct VoiceMemosTests { $0.voiceMemos[id: deadbeefURL]?.mode = .playing(progress: 0) } await store.receive(\.voiceMemos[id: deadbeefURL].delegate.playbackStarted) - await clock.run() + try await Task.sleep(for: .seconds(3)) await store.receive(\.voiceMemos[id: deadbeefURL].timerUpdated) { $0.voiceMemos[id: deadbeefURL]?.mode = .playing(progress: 0.2) @@ -82,6 +84,9 @@ struct VoiceMemosTests { await store.receive(\.voiceMemos[id: deadbeefURL].timerUpdated) { $0.voiceMemos[id: deadbeefURL]?.mode = .playing(progress: 0.8) } + await store.receive(\.voiceMemos[id: deadbeefURL].timerUpdated) { + $0.voiceMemos[id: deadbeefURL]?.mode = .playing(progress: 1.0) + } await store.receive(\.voiceMemos[id: deadbeefURL].audioPlayerClient.success) { $0.voiceMemos[id: deadbeefURL]?.mode = .notPlaying } diff --git a/Makefile b/Makefile index 5dfaa2d90e0a..8cfb4f2375f2 100644 --- a/Makefile +++ b/Makefile @@ -30,8 +30,10 @@ XCODEBUILD_FLAGS = \ XCODEBUILD_COMMAND = xcodebuild $(XCODEBUILD_ARGUMENT) $(XCODEBUILD_FLAGS) +# TODO: Prefer 'xcbeautify --quiet' when this is fixed: +# https://github.com/cpisciotta/xcbeautify/issues/339 ifneq ($(strip $(shell which xcbeautify)),) - XCODEBUILD = set -o pipefail && $(XCODEBUILD_COMMAND) | xcbeautify --quiet + XCODEBUILD = set -o pipefail && $(XCODEBUILD_COMMAND) | xcbeautify else XCODEBUILD = $(XCODEBUILD_COMMAND) endif diff --git a/Tests/ComposableArchitectureTests/StoreLifetimeTests.swift b/Tests/ComposableArchitectureTests/StoreLifetimeTests.swift index 4edcc26fa3c5..69d96cc4b238 100644 --- a/Tests/ComposableArchitectureTests/StoreLifetimeTests.swift +++ b/Tests/ComposableArchitectureTests/StoreLifetimeTests.swift @@ -145,20 +145,19 @@ final class StoreLifetimeTests: BaseTCATestCase { @MainActor @available(*, deprecated) - func testUnCachedStores() async { + func testUnCachedStores() async throws { Logger.shared.isEnabled = true - let clock = TestClock() let store = Store(initialState: Parent.State()) { Parent() } withDependencies: { - $0.continuousClock = clock + $0.continuousClock = ContinuousClock() } do { let child = store.scope(state: { $0.child }, action: { .child($0) }) child.send(.start) XCTAssertEqual(store.withState(\.child.count), 1) } - await clock.run(timeout: .seconds(5)) + try await Task.sleep(nanoseconds: 1_000_000_000) XCTAssertEqual(store.withState(\.child.count), 2) } }