diff --git a/.github/workflows/62_snapshot_check.yml b/.github/workflows/62_snapshot_check.yml index d4130b57..bce5befb 100644 --- a/.github/workflows/62_snapshot_check.yml +++ b/.github/workflows/62_snapshot_check.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - container: ["ubuntu:20.04", "ubuntu:22.04", "ubuntu:24.04", "redhat/ubi9", "debian:12"] + container: ["ubuntu:22.04", "ubuntu:24.04", "redhat/ubi9", "debian:12"] container: image: ${{ matrix.container }} steps: @@ -20,9 +20,9 @@ jobs: - name: Prepare the action run: ./scripts/prep-gh-action.sh --install-swiftly --swift-snapshot 6.2 - name: Build and Test - # UBI 9 and Ubuntu 20.04 - See https://github.com/swiftlang/swift/issues/80908 + # UBI 9 - See https://github.com/swiftlang/swift/issues/80908 # UBI 9 - See https://github.com/swiftlang/swift/issues/80909 - run: bash -c 'if [[ "${{ matrix.container }}" == "redhat/ubi9" ]]; then swiftly run +6.2-snapshot swift build --build-tests; elif [[ "${{ matrix.container }}" == "ubuntu:20.04" ]]; then swiftly run +6.2-snapshot swift build --build-tests; else swiftly run +6.2-snapshot swift test; fi' + run: bash -c 'if [[ "${{ matrix.container }}" == "redhat/ubi9" ]]; then swiftly run +6.2-snapshot swift build --build-tests; else swiftly run +6.2-snapshot swift test; fi' tests-selfhosted-macos: name: Test (Smoke Test - Nightly Swift Toolchain) / macOS Sequoia ARM64 diff --git a/.github/workflows/nightly_snapshot_check.yml b/.github/workflows/nightly_snapshot_check.yml index e27e696f..8a431143 100644 --- a/.github/workflows/nightly_snapshot_check.yml +++ b/.github/workflows/nightly_snapshot_check.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - container: ["ubuntu:20.04", "ubuntu:22.04", "ubuntu:24.04", "redhat/ubi9", "debian:12"] + container: ["ubuntu:22.04", "ubuntu:24.04", "redhat/ubi9", "debian:12"] container: image: ${{ matrix.container }} steps: @@ -20,9 +20,9 @@ jobs: - name: Prepare the action run: ./scripts/prep-gh-action.sh --install-swiftly --swift-snapshot main - name: Build and Test - # UBI 9 and Ubuntu 20.04 - See https://github.com/swiftlang/swift/issues/80908 + # UBI 9 - See https://github.com/swiftlang/swift/issues/80908 # UBI 9 - See https://github.com/swiftlang/swift/issues/80909 - run: bash -c 'if [[ "${{ matrix.container }}" == "redhat/ubi9" ]]; then swiftly run +main-snapshot swift build --build-tests; elif [[ "${{ matrix.container }}" == "ubuntu:20.04" ]]; then swiftly run +main-snapshot swift build --build-tests; else swiftly run +main-snapshot swift test; fi' + run: bash -c 'if [[ "${{ matrix.container }}" == "redhat/ubi9" ]]; then swiftly run +main-snapshot swift build --build-tests; else swiftly run +main-snapshot swift test; fi' tests-selfhosted-macos: name: Test (Smoke Test - Nightly Swift Toolchain) / macOS Sequoia ARM64 diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 31831e76..5abd059c 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -39,7 +39,7 @@ jobs: strategy: fail-fast: false matrix: - container: ["ubuntu:20.04", "ubuntu:22.04", "ubuntu:24.04", "redhat/ubi9", "debian:12", "fedora:39"] + container: ["ubuntu:22.04", "ubuntu:24.04", "redhat/ubi9", "debian:12", "fedora:39"] container: image: ${{ matrix.container }} steps: @@ -48,9 +48,9 @@ jobs: - name: Prepare the action run: ./scripts/prep-gh-action.sh --install-swiftly - name: Build and Test - # UBI 9 and Ubuntu 20.04 - See https://github.com/swiftlang/swift/issues/80908 + # UBI 9 - See https://github.com/swiftlang/swift/issues/80908 # UBI 9 - See https://github.com/swiftlang/swift/issues/80909 - run: bash -c 'if [[ "${{ matrix.container }}" == "redhat/ubi9" ]]; then swift build --build-tests; elif [[ "${{ matrix.container }}" == "ubuntu:20.04" ]]; then swift build --build-tests; else swift test; fi' + run: bash -c 'if [[ "${{ matrix.container }}" == "redhat/ubi9" ]]; then swift build --build-tests; else swift test; fi' releasebuildcheck: name: Release Build Check / Linux diff --git a/.swift-version b/.swift-version index 358e78e6..4ac4fded 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -6.1.0 \ No newline at end of file +6.2.0 \ No newline at end of file diff --git a/Sources/Swiftly/Uninstall.swift b/Sources/Swiftly/Uninstall.swift index cff43464..2f608aae 100644 --- a/Sources/Swiftly/Uninstall.swift +++ b/Sources/Swiftly/Uninstall.swift @@ -10,7 +10,7 @@ struct Uninstall: SwiftlyCommand { static let allSelector = "all" } - private struct UninstallCancelledError: Error {} + package struct UninstallCancelledError: Error {} private struct ToolchainSelectionResult { let validToolchains: Set diff --git a/Tests/SwiftlyTests/SwiftlyTests.swift b/Tests/SwiftlyTests/SwiftlyTests.swift index 59bedf9f..b8d412a2 100644 --- a/Tests/SwiftlyTests/SwiftlyTests.swift +++ b/Tests/SwiftlyTests/SwiftlyTests.swift @@ -237,9 +237,11 @@ public enum SwiftlyTests { try await cmd.run(Self.ctx) } + public struct NoError: Error {} + /// Run this command, using the provided input as the stdin (in lines). Returns an array of captured /// output lines. - static func runWithMockedIO(_ commandType: T.Type, _ arguments: [String], quiet: Bool = false, input: [String]? = nil, format: SwiftlyCore.OutputFormat = .text) async throws -> [String] { + static func runWithMockedIO(_ commandType: T.Type, _ arguments: [String], quiet: Bool = false, input: [String]? = nil, format: SwiftlyCore.OutputFormat = .text, throws expectedError: E.Type = NoError.self) async throws -> [String] { let handler = TestOutputHandler(quiet: quiet) let provider: (any InputProvider)? = if let input { TestInputProvider(lines: input) @@ -263,7 +265,13 @@ public enum SwiftlyTests { ) } - try await cmd.run(ctx) + if expectedError != NoError.self { + try await #expect(throws: expectedError) { + try await cmd.run(ctx) + } + } else { + try await cmd.run(ctx) + } return await handler.lines } diff --git a/Tests/SwiftlyTests/UninstallTests.swift b/Tests/SwiftlyTests/UninstallTests.swift index 050cb99a..d503e831 100644 --- a/Tests/SwiftlyTests/UninstallTests.swift +++ b/Tests/SwiftlyTests/UninstallTests.swift @@ -8,7 +8,9 @@ import Testing /// Tests that `swiftly uninstall` successfully handles being invoked when no toolchains have been installed yet. @Test(.mockHomeToolchains(Self.homeName, toolchains: []), .mockedSwiftlyVersion()) func uninstallNoInstalledToolchains() async throws { - _ = try await SwiftlyTests.runWithMockedIO(Uninstall.self, ["uninstall", "1.2.3"], input: ["y"]) + try await #require(throws: Uninstall.UninstallCancelledError.self) { + _ = try await SwiftlyTests.runWithMockedIO(Uninstall.self, ["uninstall", "1.2.3"], input: ["y"]) + } try await SwiftlyTests.validateInstalledToolchains( [], @@ -33,7 +35,9 @@ import Testing } // Ensure that uninstalling when no toolchains are installed is handled gracefully. - try await SwiftlyTests.runCommand(Uninstall.self, ["uninstall", "latest"]) + try await #require(throws: Uninstall.UninstallCancelledError.self) { + try await SwiftlyTests.runCommand(Uninstall.self, ["uninstall", "latest"]) + } } } @@ -51,7 +55,9 @@ import Testing ) } - _ = try await SwiftlyTests.runWithMockedIO(Uninstall.self, ["uninstall", "1.2.3"], input: ["y"]) + try await #require(throws: Uninstall.UninstallCancelledError.self) { + _ = try await SwiftlyTests.runWithMockedIO(Uninstall.self, ["uninstall", "1.2.3"], input: ["y"]) + } try await SwiftlyTests.validateInstalledToolchains( installed, @@ -73,7 +79,9 @@ import Testing ) } - _ = try await SwiftlyTests.runWithMockedIO(Uninstall.self, ["uninstall", "main-snapshot-2022-01-01"], input: ["y"]) + try await #require(throws: Uninstall.UninstallCancelledError.self) { + _ = try await SwiftlyTests.runWithMockedIO(Uninstall.self, ["uninstall", "main-snapshot-2022-01-01"], input: ["y"]) + } try await SwiftlyTests.validateInstalledToolchains( installed, @@ -239,7 +247,9 @@ import Testing /// Tests that aborting an uninstall works correctly. @Test(.mockedSwiftlyVersion(), .mockHomeToolchains(Self.homeName, toolchains: .allToolchains(), inUse: .oldStable)) func uninstallAbort() async throws { let preConfig = try await Config.load() - _ = try await SwiftlyTests.runWithMockedIO(Uninstall.self, ["uninstall", ToolchainVersion.oldStable.name], input: ["n"]) + try await #require(throws: Uninstall.UninstallCancelledError.self) { + _ = try await SwiftlyTests.runWithMockedIO(Uninstall.self, ["uninstall", ToolchainVersion.oldStable.name], input: ["n"]) + } try await SwiftlyTests.validateInstalledToolchains( .allToolchains(), description: "abort uninstall" @@ -282,8 +292,8 @@ import Testing } @Test(.mockedSwiftlyVersion(), .mockHomeToolchains(Self.homeName, toolchains: [])) func uninstallXcode() async throws { - let output = try await SwiftlyTests.runWithMockedIO(Uninstall.self, ["uninstall", "-y", ToolchainVersion.xcodeVersion.name]) - #expect(!output.filter { $0.contains("No toolchains can be uninstalled that match \"xcode\"") }.isEmpty) + let output = try await SwiftlyTests.runWithMockedIO(Uninstall.self, ["uninstall", "-y", ToolchainVersion.xcodeVersion.name], throws: Uninstall.UninstallCancelledError.self) + #expect(!output.filter { $0.contains("No toolchains can be uninstalled that match \"xcode\"") || $0.contains("No toolchains match these selectors: xcode") }.isEmpty) } // MARK: - Multiple Selector Tests @@ -379,7 +389,8 @@ import Testing let output = try await SwiftlyTests.runWithMockedIO( Uninstall.self, ["uninstall", ToolchainVersion.oldStable.name, "invalid-selector"], - input: ["n"] // Abort at error prompt + input: ["n"], // Abort at error prompt + throws: Uninstall.UninstallCancelledError.self ) // Should show error and abort @@ -398,7 +409,8 @@ import Testing func uninstallNoMatchSelectors() async throws { let output = try await SwiftlyTests.runWithMockedIO( Uninstall.self, - ["uninstall", "main-snapshot", "5.99.0"] // Neither installed + ["uninstall", "main-snapshot", "5.99.0"], // Neither installed + throws: Uninstall.UninstallCancelledError.self ) #expect(output.contains { $0.contains("No toolchains match these selectors: main-snapshot, 5.99.0") }) @@ -416,7 +428,8 @@ import Testing func uninstallAllInvalidSelectors() async throws { let output = try await SwiftlyTests.runWithMockedIO( Uninstall.self, - ["uninstall", "invalid-1", "invalid-2"] + ["uninstall", "invalid-1", "invalid-2"], + throws: Uninstall.UninstallCancelledError.self ) #expect(output.contains { $0.contains("Invalid toolchain selectors: invalid-1, invalid-2") })