Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Package versioning (divergence, breaking changes, etc) #34047

Closed
43081j opened this issue Mar 20, 2019 · 6 comments
Closed

Package versioning (divergence, breaking changes, etc) #34047

43081j opened this issue Mar 20, 2019 · 6 comments

Comments

@43081j
Copy link
Contributor

43081j commented Mar 20, 2019

As seen in #33666 and many other PRs, I have noticed we often compromise on strong versioning to maintain synchronisation with source package versions.

An example, again, is #33666. Unfortunately, the types were incorrect throughout so fixing them would require a breaking change. However, the source package has no such major version, so we would diverge and have two different versions.

I have seen this happen often, not always noticed by us under code review.

I think, because we present the versions as being "in sync" and because that is commonly the case, people will choose to avoid following semver correctly and rather choose to strictly match the source version.


IMO we should be moving more towards promoting the idea of understanding that the two versions are not the same, the two packages are two distinct, separate packages.

We should recommend that new types start at 1.0, regardless of the source package's version. This and making it very clear that version bumps are fine and can diverge.

This would lead to the types following semver in a much smoother and stricter fashion, i think.

I believe the whole concept of coupled-versions is damaging the reliability and quality of this repo and is leading people to go against common sense/good practice.

I suspect most of the stealth-breaking-changes (patch/minor version bumps) that go out and cause issues to be opened are made because people don't want to increment the version.

/cc @sandersn @RyanCavanaugh @rbuckton

@rbuckton
Copy link
Collaborator

One of the motivations behind the current versioning scheme is discoverability. By correlating the "major" and "minor" segments of a types-package version to its related package version, we make it much easier to discover the correct types for a package.

For example, if you were creating a project that uses react@15, you could execute the following:

npm i react@15
npm i -D @types/react@15

Under the current versioning scheme, we use the "patch" segment to indicate changes to the types package itself. If you are concerned about a types package having significant changes, then you would avoid using a caret (^) range in your package.json

Alternative: Use a "pre-release" Version

In these versioning schemes, <types-package-version> would be the "major", "minor", and "patch" versions of the types-package itself, while <package-version> would be the "major" and "minor" versions of the related package.

<types-package-version>-<package-version>

Example: @types/foo@1.0.0-2.1

Pros:

  • Easy to read.
  • Easy to distinguish between types-package versions.
  • Easy to distinguish between related package versions.

Cons:

  • Caret versioning does not work:
    semver.satisfies("1.0.0-2.1", "^1.0.0-2.1") // true
    semver.satisfies("1.0.1-2.1", "^1.0.0-2.1") // false
  • Limits discoverability:
    npm i foo@2.1                 # ok
    npm i -D @types/foo@2.1       # error
    npm i -D @types/foo@1.0.0     # error

<package-version>-<types-package-version>

Example: @types/foo@2.1.0-1.0.0

Pros:

  • Easy to read.
  • Easy to distinguish between types-package versions.
  • Easy to distinguish between related package versions.
  • Caret versioning works in some cases:
    semver.satisfies("2.1.0-1.0.0", "^2.1.0-1.0.0") // true
    semver.satisfies("2.1.0-1.1.0", "^2.1.0-1.0.0") // true
    semver.satisfies("2.1.0-1.1.0", "^2.1.0-1") // true
  • Somewhat discoverable:
    npm i foo@2.1                 # ok
    npm i -D @types/foo@2.1.0-0   # ok

Cons:

  • Caret versioning does not work in other cases:
    semver.satisfies("2.1.0-1.1.0", "^2.1.0") // false
    semver.satisfies("2.1.0-1.1.0", "^2.1") // false
  • Only somewhat discoverable:
    npm i foo@2.1                 # ok
    npm i -D @types/foo@2.1       # error
    npm i -D @types/foo@2.1.0     # error

Conclusion

The biggest issue with using a "pre-release" segment is that any "pre-release" version is lesser than any non-pre-release version with the same "major", "minor", and "patch".

I'm open to discussing these or other alternatives, but it is important to keep in mind that discoverability is still a major motivator.

@43081j
Copy link
Contributor Author

43081j commented Mar 21, 2019

I understand. Your suggestion of <package-version>-<types-package-version> fits nicely but its a shame semver has some caveats.

Do you understand why it doesn't satisfy caret versioning? Maybe im just being blind but it looks like it should.

It would be much better than what we do now, though. We ship so many breaking changes because of people fighting semver, it'd be a lot smoother if we didn't have that state of mind.

@iwillspeak
Copy link

Coming from a Rust / .NET point of view I've seen libraries that provide FFI bindings to other libraries use some SemVer that includes the major and minor version of the 'target' library in the 'client' library's major version. e.g:

For bindings to LLVM 7.0 you could have a semver of 700.0.0, and then you can increment your minor and patch versions as usual. If you need to make a breaking change you can bump the major version to 701.0.0 and create a breaking change. People consuminng your wrapper library can still work out what versions of the 'target' library it is compatible with based on what you've packed into the major version.

This approach doesn't come without its own set of problems however.

@iwillspeak
Copy link

@orta
Copy link
Collaborator

orta commented Jun 7, 2021

Hi thread, we're moving DefinitelyTyped to use GitHub Discussions for conversations the @types modules in DefinitelyTyped.

To help with the transition, we're closing all issues which haven't had activity in the last 6 months, which includes this issue. If you think closing this issue is a mistake, please pop into the TypeScript Community Discord and mention the issue in the definitely-typed channel.

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

No branches or pull requests

5 participants