Package Collection Format

For me at least, I have seen build failures after upgrading from one patch version to another, so yes, I would say it matters. Personally I am more concerned with incompatibilities when they happen and would appreciate any additional detail available.

IMO 5.3.0 means .0 only but 5.3 could mean 5.3.*.

I agree that there are only rare situations where a patch release would affect compatibility (although as Yim said, it can happen) it's more about whatever gets decided the rules should be well specified otherwise we'll get a mix of "5.3", "5.3.1", "5.3.0", and "I don't know, I think it was five point something" :joy:.

I'd still say a full semantic version would be best, but I'd say whatever gets decided it should be one or the other.

I hadn't thought too much about the details :grimacing:

Looking at the two options you mention, I'm not keen that the latest and latest pre release would be removed from the versions array. So if this is something that's worth capturing, it should either be in addition, or could potentially be a property off the version object.

  "packages": [
    {
      "versions": [
        {
          "version": "1.0.0-alpha.1",
          "latestPreRelease": "true"
          ...
        },
        {
          "version": "0.5.2",
          "latestRelease": "true"
          ...
        },

Maybe?

1 Like

I don't know why, but historically Swift releases don't fully follow semver. The first release of a minor version never includes the .0 patch version for some reason. There was never an official Swift 5.3.0, just Swift 5.3, which was followed by Swift 5.3.1.

1 Like

The drawback is that a collection might end up with multiple latest* versions. Like I noted, SwiftPM already computes the latest version, so one option is to keep the logic there and replace latestVersion with latestRelease and latestPreRelease.

1 Like

If SwiftPM already computes latest* it's probably not worth adding those fields. As you say, there's either duplication or the difficulty of ensuring integrity.

The reason I mentioned this to Dave was that it can be a bit fiddly to determine these versions from the array and depending on who's going to consume collections, they may have to do so themselves.

I guess this could be revisited if there are clients other than SwiftPM.

1 Like

One thing that might be worth considering is whether license information should also be able to be specified at the package level, in addition to the version level.

If we had license be an optional property of both packages and versions, then it could act as an override at the version level over whatever was specified at the package level.

So, something like this would specify that the package was released at 0.1.0 with a MIT license, but that 0.2.0 is licensed under the BSD-3-Clause license.

"packages": [
	{
		"url": "https://www.example.com/repos/RepoOne.git",
		"summary": "Package One",
		"readmeURL": "https://www.example.com/repos/RepoOne/README",
		"license": {
			"name": "BSD-3-Clause"
		}
		"versions": [
			{
				"version": "0.1.0",
				"packageName": "PackageOne",
				"license": {
					"name": "MIT"
				}
			},
			{
				"version": "0.2.0",
				"packageName": "PackageOne",
			}
		]
2 Likes

Makes sense. In other words, package.license, if set, should contain the current license info for the package, whereas version.license provides a snapshot of that info.

Yep, and both are optional. I didn't include url in my example JSON but they should both allow the URL as well as the name.

Just one more point about the license field. We have plenty of packages in the Swift Package Index where we do not definitively know the license type. This is for one of three reasons:

  1. The package has no license
  2. The package has a commercial or non-standard license
  3. The package has an open-source license, but GitHub has failed to recognise it. Usually, because it's got some extra information lines at the top or bottom of the license.

In cases 2 and 3, I'd suggest the license parameter should include url but not name as we do have the license URL. In the case of 1, I think it's probably practical to just omit license completely, but that doesn't very effectively communicate that the package is completely unlicensed.

name can be any string really (including empty string), and any unrecognized name will just be interpreted as other(name) license type. I suppose we could make name optional such that other(nil) is possible.