From 37ed91720de43b758f2b2d2191d032d5e70861a2 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 3 Oct 2025 08:14:59 -0400 Subject: [PATCH 1/6] Bump swiftly version to 6.2.0 to support new macOS SDK in CI --- .swift-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 698ae49b2301ecfb14635ff8a40a505c11d4fffe Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 3 Oct 2025 08:38:03 -0400 Subject: [PATCH 2/6] In preparation for swift 6.2 remove Ubuntu 20.04 verification --- .github/workflows/62_snapshot_check.yml | 6 +++--- .github/workflows/nightly_snapshot_check.yml | 6 +++--- .github/workflows/pull_request.yml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) 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..4dee6d47 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; 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..4d86fcd3 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; then swift build --build-tests; else swift test; fi' releasebuildcheck: name: Release Build Check / Linux From d18fe80f8d665fc07c78f791273839043124107f Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 3 Oct 2025 08:42:59 -0400 Subject: [PATCH 3/6] Fix shell pull request shell script --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 4d86fcd3..5abd059c 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -50,7 +50,7 @@ jobs: - name: Build and Test # 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; 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 From 0da2346d02137dd1a957259632b68512e2cf5c8b Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 3 Oct 2025 08:43:54 -0400 Subject: [PATCH 4/6] Fix nightly shell script --- .github/workflows/nightly_snapshot_check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly_snapshot_check.yml b/.github/workflows/nightly_snapshot_check.yml index 4dee6d47..8a431143 100644 --- a/.github/workflows/nightly_snapshot_check.yml +++ b/.github/workflows/nightly_snapshot_check.yml @@ -22,7 +22,7 @@ jobs: - name: Build and Test # 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; 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 From 38516e6cf7c5e79effc2dac5f6a19a7b43bb401f Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 3 Oct 2025 09:32:01 -0400 Subject: [PATCH 5/6] Fix test failures by chcecking for throwing of UninstallCancelledError --- Sources/Swiftly/Uninstall.swift | 2 +- Tests/SwiftlyTests/SwiftlyTests.swift | 12 ++++++++-- Tests/SwiftlyTests/UninstallTests.swift | 31 ++++++++++++++++++------- 3 files changed, 33 insertions(+), 12 deletions(-) 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..46d3c748 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,7 +292,7 @@ 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]) + 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\"") }.isEmpty) } @@ -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") }) From 083f86ab04216bdfa189d8f95a8880840e9fe3ab Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 3 Oct 2025 11:31:47 -0400 Subject: [PATCH 6/6] Update uninstall xcode test to check for case where the xcode system toolchain is not present --- Tests/SwiftlyTests/UninstallTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/SwiftlyTests/UninstallTests.swift b/Tests/SwiftlyTests/UninstallTests.swift index 46d3c748..d503e831 100644 --- a/Tests/SwiftlyTests/UninstallTests.swift +++ b/Tests/SwiftlyTests/UninstallTests.swift @@ -293,7 +293,7 @@ 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], throws: Uninstall.UninstallCancelledError.self) - #expect(!output.filter { $0.contains("No toolchains can be uninstalled that match \"xcode\"") }.isEmpty) + #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