Skip to content

Handle install 6.4-snapshot properly#561

Open
ktoso wants to merge 3 commits into
mainfrom
wip-handle-6.4
Open

Handle install 6.4-snapshot properly#561
ktoso wants to merge 3 commits into
mainfrom
wip-handle-6.4

Conversation

@ktoso

@ktoso ktoso commented Jun 13, 2026

Copy link
Copy Markdown

swift.org changed the url scheme and 6.4 now needs to become 6.4.x.

We should not require users to know about this and installing 6.4 or 6.4-snapshot is totally expected to work.

This fixes the known urls and also adds a fallback for the future;

Options to consider:

  • we could remove the fallback... I'm just being extra careful about future i guess, perhaps too much?
  • we could default all versions from 6.4 onwards to add the .x always, but that's pretty spectulative so i didn't do that.

Current scheme adds the .x for 6.4 and for others it would attempt a fallback to .x but now try it first.

Resolves #560


before:

-> % swiftly install 6.4-snapshot
Fetching the latest 6.4 development branch snapshot...
-----------------------------
A new release of swiftly is available.
Please run `swiftly self-update` to update.
-----------------------------
Error: Unexpected response, expected status code: ok, response: undocumented(statusCode: 404, OpenAPIRuntime.UndocumentedPayload(headerFields: [(field: Server: Apple, next: 65535), (field: Date: Sat, 13 Jun 2026 02:43:54 GMT, next: 65535), (field: Content-Type: text/html, next: 65535), (field: Content-Length: 146, next: 65535), (field: Strict-Transport-Security: max-age=31536000; includeSubdomains, next: 65535), (field: X-Frame-Options: SAMEORIGIN, next: 65535), (field: X-XSS-Protection: 1; mode=block, next: 65535), (field: Age: 2, next: 65535), (field: Via: https/1.1 jptyo5-edge-mx-010.ts.apple.com (acdn/316.16515), https/1.1 jptyo5-edge-fx-028.ts.apple.com (acdn/316.16515), next: 65535), (field: X-Cache: hit-stale, miss, next: 65535), (field: CDNUUID: f0997761-ef15-4f9d-ac2e-03889f7307d5-156837625, next: 65535), (field: Connection: keep-alive, next: 65535)], body: Optional(OpenAPIRuntime.HTTPBody)))

after

-> % ./.build/debug/swiftly install 6.4-snapshot
Fetching the latest 6.4 development branch snapshot...
Installing 6.4.x-snapshot-2026-06-10
                                                                                                        Downloading 6.4.x-snapshot-2026-06-10
 2% [====------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------]
Downloaded 42.1 MiB of 1855.3 MiB^C

swift.org changed the url scheme and 6.4 now needs to become 6.4.x.

We should not require users to know about this and installing 6.4 or
6.4-snapshot is totally expected to work.

This fixes the known urls and also adds a fallback for the future;

Options to consider:
- we could remove the fallback... I'm just being extra careful about
  future i guess, perhaps too much?
- we could default all versions from 6.4 onwards to add the .x always,
  but that's pretty spectulative so i didn't do that.

Current scheme adds the .x for 6.4 and for others it would attempt a
fallback to .x but now try it first.

@ktoso ktoso left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ll do some more testing if this doesn’t break anything after the weekend;

Comment thread Sources/SwiftlyCore/HTTPClient.swift Outdated
default:
return false
}
}

@ktoso ktoso Jun 15, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So here's where we could take a policy decision to just assume future versions follow this .x style or be conservative like it is now and just special case the 6.4... WDYT is better? I guess we'll find out in the future either way heh

Maybe flip it for v >= 6.4 -> true?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So to answer your question, it is expected that the .x will be part of any release development branch, aligning with the branch name on the Swift repository on GitHub, so this can probably be reduced to v >= 6.4.

That said, I wonder if it would make sense to do this in the ToolchainVersion? If it's a snapshot, and the version is 6.4 or newer, the patch version automatically chooses x. Then we don't have to add the additional .release(major, minor, nil) below, and I think we can drop the logic in the catch portion of the getSnapshotToolchains below. The patch string will just return x.

@etcwilde etcwilde left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I talked with @shahmishal about this earlier today. The 6.4.x is intentional, specifically so that folks don't expect 6.4.0 when they pull down a 6.4 snapshot from swift.org.
Since Swiftly already gives you the latest, the 6.4.x behavior is already expected.

Since the website is going to start calling the nightlies with .x, but swiftly already makes it apparent that a snapshot is a snapshot in the version selector, I think that it's valuable to accept both.

I think it might be interesting to automatically have the snapshot set the patch to "x" if it's 6.4 or greater and one wasn't specified explicitly. Then we should update the parseReleaseSnapshotWithPatch test to use 6.4 for each, and include a 6.4-snapshot case that should also map to a .release(major: 6, minor: 4, patch: "x") snapshot version to ensure that it's handling the mapping correctly.

Comment thread Sources/SwiftlyCore/HTTPClient.swift Outdated
default:
return false
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So to answer your question, it is expected that the .x will be part of any release development branch, aligning with the branch name on the Swift repository on GitHub, so this can probably be reduced to v >= 6.4.

That said, I wonder if it would make sense to do this in the ToolchainVersion? If it's a snapshot, and the version is 6.4 or newer, the patch version automatically chooses x. Then we don't have to add the additional .release(major, minor, nil) below, and I think we can drop the logic in the catch portion of the getSnapshotToolchains below. The patch string will just return x.

@ktoso

ktoso commented Jun 19, 2026

Copy link
Copy Markdown
Author

Gotcha, let me rework this a bit then. Bottom line is I think we do want to accept the 6.4-snapshot if the .x was not specified, but we won't do the nil case in the enum but model it with defaulting to the x instead if I understood you correctly. I'll take a stab at it

@ktoso ktoso requested a review from etcwilde June 19, 2026 06:59
@ktoso

ktoso commented Jun 19, 2026

Copy link
Copy Markdown
Author

This ended up much cleaner, please have another look @etcwilde -- thanks!

@etcwilde etcwilde left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that a lot better. Thanks for making the changes.

I'd like to add verification that 6.4.x-snapshot and 6.4-snapshot evaluate to the same thing, and that 5.7.x-snapshot and 5.7-snapshot don't.


/// From Swift 6.4 onward the swift.org URL scheme uses `X.Y.x`, so a bare
/// `6.4-snapshot` (no explicit patch) is normalized to `patch: "x"`.
@Test func parseReleaseSnapshotWithoutPatch() throws {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I think we need to verify that 5.7.x-snapshot and 5.7-snapshot don't evaluate to the same thing and that 6.4-snapshot and 6.4.x-snapshot do.

Since toolchains moving forward will all carry the .x patch, I'm inclined to say that we should take the parseReleaseSnapshot name for the new test verifying the behaviour of 6.4-snapshot and 6.4.x-snapshot, and rename the old test function something liken parseDeprecatedReleaseSnapshot.

Then we merge this with the parseReleaseSnapshotWithPatch test above.

@Test func parseDeprecatedReleaseSnapshot() throws {
    var parses = [
        "5.7-snapshot",
        "5.7-SNAPSHOT",
        "5.7-DEVELOPMENT-SNAPSHOT",
        "swift-5.7-snapshot",
        "swift-5.7-SNAPSHOT",
        "swift-5.7-DEVELOPMENT-SNAPSHOT",
    ]
    try runTest(.snapshot(branch: .release(major: 5, minor: 7, patch: nil), date: nil), parses)

    parses = [
        "5.7.x-snapshot",
        "5.7.x-SNAPSHOT",
        "5.7.x-DEVELOPMENT-SNAPSHOT",
        "swift-5.7.x-snapshot",
        "swift-5.7.x-SNAPSHOT",
        "swift-5.7.x-DEVELOPMENT-SNAPSHOT",
    ]
    try runTest(.snapshot(branch: .release(major: 5, minor: 7, patch: "x"), date: nil), parses)
}

@Test func parseReleaseSnapshot() throws {
    let parses = [
        "6.4-snapshot",
        "6.4.x-snapshot",
        "6.4-SNAPSHOT",
        "6.4.x-SNAPSHOT",
        "6.4-DEVELOPMENT-SNAPSHOT",
        "6.4.x-DEVELOPMENT-SNAPSHOT",
        "swift-6.4-snapshot",
        "swift-6.4.x-snapshot",
        "swift-6.4-SNAPSHOT",
        "swift-6.4.x-SNAPSHOT",
        "swift-6.4-DEVELOPMENT-SNAPSHOT",
        "swift-6.4.x-DEVELOPMENT-SNAPSHOT",
    ]
    try runTest(.snapshot(branch: .release(major: 6, minor: 4, patch: "x"), date: nil), parses)
}

This should cover everything in parseReleaseSnapshot, parseReleaseSnapshotWithPatch and parseReleaseSnapshotWithoutPatch.
Thoughts?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, sounds good -- and I like the having the "deprecated" for the old one, I'll follow up soon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

swiftly install 6.4-snapshot fails because url schema change

2 participants