swiftlang / swift-package-manager

The Package Manager for the Swift Programming Language
Apache License 2.0
9.72k stars 1.34k forks source link

Support version tags with custom prefix or suffix #5780

Open jtbandes opened 2 years ago

jtbandes commented 2 years ago

Description

I work on a project in a monorepo that provides published libraries in multiple languages, including Swift. I would like to track the Swift package version using git tags with a custom prefix, like releases/swift/v1.0.0. We use this scheme so that we can version each language's packages separately. Examples of our release tags for other languages: https://github.com/foxglove/mcap/tags

Expected behavior

I would like a way to specify in Package.swift that my tags are prefixed with releases/swift/v.

Actual behavior

It appears that when one uses a dependency of the form .package(url: "https://github.com/my/repo", from: "1.0.0"), SwiftPM will only consider git tags named 1.0.0, v1.0.0, and similar.

WowbaggersLiquidLunch commented 2 years ago

It appears that when one uses a dependency of the form .package(url: "https://github.com/my/repo", from: "1.0.0"), SwiftPM will only consider git tags named 1.0.0, v1.0.0, and similar.

Yes, this is correct. Currently, the only accepted forms are (v)x.y(.z)(-pre-release)(+build-metadata). Basically a more leniently parsed SemVer 2.0.0 that allows dropping the patch version and prefixing a lowercase "v"[^1]: https://github.com/apple/swift-package-manager/blob/eb62733fc421666e54a85f7570731d709c66c830/Sources/Basics/Version%2BExtensions.swift#L19-L25

I think your request makes sense, especially seeing many of Swift's own repositories group release tags like what you've shown. Maybe we can loosen the rule a bit more so that if the tag looks like a path, then we take just the last path component of it and verify that it follows the current rule?

[^1]: Actually a bit more lenient than this, due to a few bugs I introduced last year, which I hope I can fix some time soon.

jtbandes commented 2 years ago

if the tag looks like a path, then we take just the last path component of it and verify that it follows the current rule?

Does this approach provide any way to restrict the prefixes that are considered? While splitting path components could be part of the solution, I wouldn’t want swiftpm to consider all tags whose last path component looks like a version, because then it’d be mixing up versions from all the different packages in the repo. The point of this request is to restrict matching to a subset of the tags.

WowbaggersLiquidLunch commented 1 year ago

Hi sorry for the late response!

Does this approach provide any way to restrict the prefixes that are considered?

No.

While splitting path components could be part of the solution, I wouldn’t want swiftpm to consider all tags whose last path component looks like a version, because then it’d be mixing up versions from all the different packages in the repo. The point of this request is to restrict matching to a subset of the tags.

Ok I think I know what you mean now. Sorry for misunderstanding your request at first!

I think maybe we could add some new methods as follows to PackageDescription for your needs?

func package(url: String, from version: Version, groupedUnder tagGroup: String) -> Package.Dependency
func package(url: String, from version: Version, prefixedBy prefix: String = "v") -> Package.Dependency
jtbandes commented 1 year ago

Yes, that could work. In my case I’d use groupedUnder: “releases/swift” or prefixedBy: “releases/swift/v”.

I’m not sure if this setting belongs in the .package() dependency, or in the Package struct itself. Putting it in the Package struct would allow the package repo to set it once and then it would work automatically for anyone who wants to depend on it. Putting it in .package() means anyone who wants to depend on the package needs to remember to include the prefix info in their dependency.

jtbandes commented 1 year ago

Side note: I’m guessing that the forthcoming package registry (SE-0292) would also help, because then I could simply choose which tags I upload to the registry. But having your proposed solutions would still be good, for packages that are pulled from git repos.

jcapogna commented 8 months ago

@jtbandes How did you resolve this? I see your package contains swift now. I am running into the same problem with adding a swift package to a monorepo.

jtbandes commented 8 months ago

To my knowledge it’s not resolved; consumers have to depend on a specific commit SHA. Although there is another issue blocking consumers from depending on the package, #5351

jcapogna commented 8 months ago

@jtbandes I don't know if this helps you, but I solved this for myself by writing a semantic-release plugin that "publishes" my Swift subpackage to a standalone Git repository for easier consumption. https://www.npmjs.com/package/semantic-release-git-publish