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

MCP-0016: Semantic Versions for Libraries #1728

Open
modelica-trac-importer opened this issue Nov 4, 2018 · 49 comments
Open

MCP-0016: Semantic Versions for Libraries #1728

modelica-trac-importer opened this issue Nov 4, 2018 · 49 comments
Labels
enhancement New feature or request MCP Generic MCP label (prefer specific MCP label for grouping of issues belonging to the same MCP)

Comments

@modelica-trac-importer
Copy link
Collaborator

modelica-trac-importer commented Nov 4, 2018

Modified by dietmarw on 2 Dec 2015 10:08 UTC
We identified several potential “levels” of semantics. The first level was the idea that all libraries must use semantic versions syntax. This would have the basic benefit that it would address issues about how to express things like pre-release versions. It also provides a basis for defining ordering as well.

This MCP is about how to deal with semantics of version numbers. By this we
mean conclusions that could be drawn about compatibility between different
versions (e.g., something that uses 3.2.1 should be able to use 3.2.2). One of the topics that come up was the idea of bugs and bug fixes. It might be that API compatibility may be present, but that the actual implementations have issues.

Based on this, it was felt that the uses annotation was still useful because it allows a level of explicit dependencies. For this reason it was felt that library developers should be able to utilize semantic version compatibility but also to explicitly override it.

Document location

Current members of the working group

  • Henrik Tidefelt
  • Hans Olsson

Modified by dietmarw on 18 Sep 2015 07:56 UTC
We identified several potential “levels” of semantics. The first level was the idea that all libraries must use semantic versions syntax. This would have the basic benefit that it would address issues about how to express things like pre-release versions. It also provides a basis for defining ordering as well.

This MCP is about how to deal with semantics of version numbers. By this we
mean conclusions that could be drawn about compatibility between different
versions (e.g., something that uses 3.2.1 should be able to use 3.2.2). One of the topics that come up was the idea of bugs and bug fixes. It might be that API compatibility may be present, but that the actual implementations have issues.

Based on this, it was felt that the uses annotation was still useful because it allows a level of explicit dependencies. For this reason it was felt that library developers should be able to utilize semantic version compatibility but also to explicitly override it.

Document location

Current members of the working group

  • Henrik Tidefelt
  • Hans Olsson
  • Dietmar Winkler

Reported by mtiller on 9 Jun 2015 14:35 UTC
We identified several potential “levels” of semantics. The first level was the idea that all libraries must use semantic versions syntax. This would have the basic benefit that it would address issues about how to express things like pre-release versions. It also provides a basis for defining ordering as well.

This MCP is about how to deal with semantics of version numbers. By this we
mean conclusions that could be drawn about compatibility between different
versions (e.g., something that uses 3.2.1 should be able to use 3.2.2). One of the topics that come up was the idea of bugs and bug fixes. It might be that API compatibility may be present, but that the actual implementations have issues.

Based on this, it was felt that the uses annotation was still useful because it allows a level of explicit dependencies. For this reason it was felt that library developers should be able to utilize semantic version compatibility but also to explicitly override it.

Document location


Migrated-From: https://trac.modelica.org/Modelica/ticket/1728

@modelica-trac-importer
Copy link
Collaborator Author

Modified by dietmarw on 9 Jun 2015 14:51 UTC

@modelica-trac-importer
Copy link
Collaborator Author

Comment by mwetter on 10 Jun 2015 17:19 UTC
As a library author, I am fully supportive of the semantic versioning (and started using it for Buildings).

As not all library developers may be aware of what a backward compatible change is, and because it may quickly happen that a non-backward compatible change gets on the development branch inadvertently, I think robustness of library versioning could be increased if developers had access to a script, or at the minimum a checklist, that can be used to verify whether a library is indeed backwards compatible.

A (likely still incomplete test) could be that

  • all classes are still present,
  • all public instances are still present,
  • all parameters still have either the same default value or the same start attribute set,
  • no new parameter is introduced that has neither a default value nor its start attribute set, and
  • no parameter is converted from non-final to final.

As I doubt that all library developers will use semantic versioning, a keyword would be useful that indicates that a library indeed uses semantic versioning. I suggest a library should opt-in to use semantic versioning.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 24 Jun 2015 08:32 UTC
Replying to [comment:2 mwetter]:

As a library author, I am fully supportive of the semantic versioning (and started using it for Buildings).

As not all library developers may be aware of what a backward compatible change is, and because it may quickly happen that a non-backward compatible change gets on the development branch inadvertently, I think robustness of library versioning could be increased if developers had access to a script, or at the minimum a checklist, that can be used to verify whether a library is indeed backwards compatible.

I also tried to investigate how to best do this (i.e. planning to actually implement the feature), and then I got stuck since I realized that we haven't clearly defined what is allowed in various versions - and it is not even clear that it is possible (see below). (I tried to look through the documents for this MCP and couldn't find anything.)

A (likely still incomplete test) could be that

  • all classes are still present,
  • all public instances are still present,
  • all parameters still have either the same default value or the same start attribute set,
  • no new parameter is introduced that has neither a default value nor its start attribute set, and
  • no parameter is converted from non-final to final.

These restrictions on minor version are similar to "plug compatibility" (in section 6.4 of the specification) - which is basically to say that a user could redeclare a component of the old class with the new one.

(Additionally you require that the same value shall be used; that is problematic to check - and additionally I assume some want to allow minor tweaks of values.)

Similarly the restriction on patch-releases can be compared to the restriction in MSL for updates of the maintenance branch. (Alternatively that you can redeclare in either direction.)

However, the restrictions on the maintenance-branch in MSL are not 100% safe.

And with current Modelica I don't see how we can have 100% safe restrictions on non-major releases that allow current development. The changes in Modelica Specification to allow 100% safe realistic changes in libraries seems major (with realistic I mean usual minor changes for current modeling-building paradigms), and I am not certain of the exact details - or even if it is possible.

However, the unsafe cases are (a bit) farfetched, and we could accept that some things may break in rare cases - similarly as the restrictions on the maintenance branch of MSL (and of course a bug-fix can also break the behavior of some user models).

Note that I'm not saying that this makes it impossible to have semantic versioning in any form in Modelica, only that we need to define it clearly - and have realistic goals.

A minimum goal would be to use semantic version numbers without the semantics of semantic versions would be a solution, but it hardly feels like progress.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by sjoelund.se on 24 Jun 2015 08:44 UTC
Replying to [comment:2 mwetter]:

As not all library developers may be aware of what a backward compatible change is, and because it may quickly happen that a non-backward compatible change gets on the development branch inadvertently

A development branch is not the same thing as a release. It is possible to use pre-release version numbers on the development branch.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 24 Jun 2015 09:14 UTC
Replying to [comment:4 sjoelund.se]:

Replying to [comment:2 mwetter]:

As not all library developers may be aware of what a backward compatible change is, and because it may quickly happen that a non-backward compatible change gets on the development branch inadvertently

A development branch is not the same thing as a release. It is possible to use pre-release version numbers on the development branch.

I would more strongly say that one should use a pre-release version on the development branch (as soon there is any development).

However, that doesn't solve M. Wetter's problem, since it depends on what pre-release is it!
A pre-release of a patch-version should not contain new functionality.
A pre-release of a minor-version should not contain non-backward compatible changes (with regards to the functionality present in the previous released version).

@modelica-trac-importer
Copy link
Collaborator Author

Comment by sjoelund.se on 24 Jun 2015 09:20 UTC
Replying to [comment:5 hansolsson]:

A pre-release of a patch-version should not contain new functionality.
A pre-release of a minor-version should not contain non-backward compatible changes (with regards to the functionality present in the previous released version).

Not according to semantic versioning:

A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version

It is probably a good thing if pre-releases do satisfy these requirements, but they do not need to.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 24 Jun 2015 09:38 UTC
Replying to [comment:6 sjoelund.se]:

Replying to [comment:5 hansolsson]:

A pre-release of a patch-version should not contain new functionality.
A pre-release of a minor-version should not contain non-backward compatible changes (with regards to the functionality present in the previous released version).

Not according to semantic versioning:

A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version

It is probably a good thing if pre-releases do satisfy these requirements, but they do not need to.

Are you sure?

The semantic version specification both state that the minor version number MUST be incremented for any new functionality (without any exception for pre-release versions), and that pre-release versions MAY be indicated with additional information and it might be unstable and not satisfy the requirements on released versions.

Only the requirement for minor version is a "MUST" which is clearly defined.

My interpretation is that pre-release versions ideally should satisfy the requirements, but since they are not fully tested it is less guaranteed than for released versions. (Even released versions may break compatibility by mistake, that is covered in the semver-faq.)

Added: However, the main point from M.Wetter is how to avoid releasing this breaking change by mistake; and for that case I say that not adding the changes at all seems the safest choice. (Which can then be combined by verifying it afterwards.)

@modelica-trac-importer
Copy link
Collaborator Author

Comment by sjoelund.se on 24 Jun 2015 09:46 UTC
I am sure. It was a direct quote from semver.org. You are correct that they should ideally satisfy the requirements, but they do not need to. I guess so you can start development not knowing if the next release will be a major, minor, or patch release.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 24 Jun 2015 12:00 UTC
Replying to [comment:8 sjoelund.se]:

I am sure. It was a direct quote from semver.org. You are correct that they should ideally satisfy the requirements, but they do not need to.

And still the spec states that you MUST increment the version number, not merely that you should do it.

A simple conclusion is that SemVer spec is inconsistent, which has been reported by others (primarily regarding released versions that were incorrect):

semver/semver#229

Which contains the following about violating the "MUST" for incrementing versions:
"The violation exists forever, so any project which has ever violated rule 8 (or 6, 7, etc.) is not SemVer compliant and will never again be SemVer compliant."

I guess so you can start development not knowing if the next release will be a major, minor, or patch release.

See also semver/semver#124

Added: However, regardless of this we are in agreement that the pre-release versions SHOULD NOT contain incompatibilities that would be incorrect for the corresponding released version.

The term 'SHOULD NOT' (using RFC 2119 as in SemVer) is a recommendation where exception can occur - and "user made an error that will be corrected" would be a valid exception in my opinion - but still something that we should try to avoid.

@modelica-trac-importer
Copy link
Collaborator Author

Modified by dietmarw on 18 Sep 2015 07:56 UTC

@modelica-trac-importer
Copy link
Collaborator Author

Comment by henrikt on 23 Sep 2015 10:37 UTC
In order to bring the discussion back to the ticket, I'll try to summarize the main problems that need to be resolved.

Before going to the problems, however, I'll state some things that seem clear to me at this point.

  1. I consider a (Modelica) language version header (MCP-0015) a widely accepted prerequisite for the semantic versioning of libraries. In the discussion below, let's assume that semantic versioning of libraries is introduced in Modelica language version 3.S ("S" for "Semantic").

  2. The semantics of a a version number is a property of the library, not a property of the model that uses the library. That is, even if a model uses Modelica version 3.S, not all its uses annotations are necessarily refering to semantic version numbers. Conversely, a tool that is able two handle multiple versions of the language at the same time may allow a model using language version 3.3 (as can be seen by the absence of a language version header) to have uses annotations pointing to libraries with semantic version numbers, and resolve these version numbers as such.

  3. If the language specification mandates that library version numbers are semantic as of language version 3.S, I think that the way we define semantics must be able to rely on version numbers following the semantic rules. To support this, we must find ways to deal with the scenarios where the semantic rules have been violated.

  4. The discussion about semantic versioning of libraries should not be mixed up with the need for versioning of non-top level packages.

  5. The most popular form of a semantic version number seems to be X.Y.Z, where X is called 'major version', Y is called 'minor version', and Z is called 'patch version'.

Main problems

  1. Expressiveness of single version uses annotations. With semantic version numbers, it seems sufficient to only have uses annotations that are basically in the form of valid semantic version numbers. The special case of version numbers with build metadata is discussed separately below. (The need for having multiple version numbers will also be discussed below.) When multiple versions of a library are available, a version number in a uses annotation is resolved to the one of highest precedence (according to semver.org) among those that are compatible with the uses annotation. Possible use cases (SemVerLib is some library using language version 3.S):
  • uses(SemVerLib(version="1.0.0")) — may be resolved by any SemVerLib of major version 1 (except development versions like 1.0.0-alpha)
  • uses(SemVerLib(version="1.2.0")) — may be resolved by any SemVerLib of major version 1 and minor version at least 2.
  • uses(SemVerLib(version="1.2.3")) — may be resolved by any SemVerLib of major version 1, and minor version greater than 2, or minor version equal to 2 with patch version at least 3.
    The simplicity of this level of expressiveness makes it trivial to merge multiple uses of the same library: If all uses annotations point to the same major version, it is always correct to only consider the one with the highest precedence. For example, if one uses annotation points to 3.2.1 and another points to 3.3.2, they can only be resolved jointly if there is an available version that is compatible with 3.3.2. If multiple versions are allowed in the uses annotation, each major version can be considered separately, and the version can be resolved if there is at least one major version available that is compatible with each use of the library. If some uses annotations disagree on the major version, there is no resolution unless the tool is able to handle multiple versions of a library at the same time.
    Things that cannot be expressed:
  • Major version at least 1. (Only exact matching of major version makes sense in view of semantic versioning rules.)
  • Version 1.2.3 and nothing else. (Not being interested in other compatible versions according to the rules of semantic versioning doesn't make sense. This kind of library dependency is the very problem we are trying to solve by specifying semantics of version numbers. Of course, a user shouldn't be forced to have other versions than 1.2.3 on his/her system, thereby having the freedom to get version 1.2.3 and nothing else for his/her own models. However, once such a model is given to another user, there is clearly no guarantee anymore that some other compatible version 1.2.3 is not installed on the other user's system.)
  • Varsion 1.2.3 or any compatible version except 1.2.5. (Not being interested in version 1.2.5 doesn't make sense in view of semantic versioning rules. However, in case a mistake was made and rules were broken in version 1.2.5, ways to address the situation must be discussed.)
  • More advanced variants of the above, like version ranges or more general patterns, etc.
  1. Implications for conversion annotations. For a library that is developed entirely using semantic version numbers (first release was using language version 3.S or later), it is clear that conversion annotations should only specify conversions between major versions of the library. Hence, library version 4.3.2 will typically include all the conversions below and no other:
conversion(from(version={"1"}, ...),
           from(version={"2"}, ...),
           from(version={"3"}, ...))

When library version 5.0.0 is released, backward incompatible changes can hopefully be addressed with conversion scripts, so from(version={"4"}, ...) is added, and the conversions then remain unchanged until library version 6.0.0 is released.

The difficult part is how to handle conversions for libraries that started out using non-semantic version numbers. For the sake of discussion, consider a variant of conversion annotations that specify both a source and target version, and let's say that version 4.0.0 of the library was the first version using semantic version numbering:

conversion(from(version={"1.0.0", "1.0.1"}, toVersion="1.1.0", ...),
           from(version={"1.1.0"}, toVersion="2.0.0", ...),
           from(version={"2.0.0", "2.1.0", "3.0.0"}, toVersion="3.0.1", ...),
           from(version={"3.0.1"}, toVersion="4.0.0", ...))

Since the library is now using semantic version numbering, no new conversions will be needed when releasing 4.0.1, 4.1.0, 4.1.1, 4.2.0, etc. Not until version 5.0.0 is released does it make sense to add a new conversion:

conversion(from(version={"1.0.0", "1.0.1"}, toVersion="1.1.0", ...),
           from(version={"1.1.0"}, toVersion="2.0.0", ...),
           from(version={"2.0.0", "2.1.0", "3.0.0"}, toVersion="3.0.1", ...),
           from(version={"3.0.1"}, toVersion="4.0.0", ...),
           from(version={"4.0.0"}, toVersion="5.0.0", ...))

Now, the problem is that library version 5.0.0 being marked with language version 3.S or later does not say anything about which language version that was used for library version 4.Y.Z. Consider trying to find a conversion for a model currently using library version 4.3.2:

  • If library version 4 was using semantic version numbers, then the correct conversion to apply is that from 4.0.0 to 5.0.0.
  • If library version 4 was not using semantic version numbers, then a conversion from 4.3.2 to 5.0.0 is missing.
    One possible resolution here is to infer that version 4 must have used semantic version numbers since:
    • version 5 of the library is using semantic version numbers, and
    • there clearly existed a version 4.3.2 of the library, but version 5.0.0 says nothing about conversion from that particular version.
      Another implication of semantic version numbers is that if version 4.3.2 is marked with language version 3.S or later, it should be illegal to specify a conversion to any version under 4 except 4.0.0. For instance, the following should not be allowed:
conversion(...,
           from(version={"2.0.0", "2.1.0", "3.0.0"}, toVersion="4.0.0", ...),
           from(version={"4.0.0"}, toVersion="4.0.1", ...))

Since the library is using semantic version numbers as of version 4, it should be safe to use "4" as an abbreviation of "4.0.0" to remove redundant zeros and to make it harder to make the mistake of specifying illegal conversions:

conversion(from(version={"1.0.0", "1.0.1"}, toVersion="1.1.0", ...),
           from(version={"1.1.0"}, toVersion="2.0.0", ...),
           from(version={"2.0.0", "2.1.0", "3.0.0"}, toVersion="3.0.1", ...),
           from(version={"3.0.1"}, toVersion="4", ...),
           from(version={"4"}, toVersion="5", ...))

Yet another question related to conversion annotations is how to make a difference between major versions where a conversion is able to take care of upgrading models, and major versions where no such conversion exists. Making a difference may not be strictly necessary, but it would tighten the integration of semantic version numbering and conversion annotations, see the section on having a generation number as part of the version below.

  1. The semantics of the version numbers. As has already been noted, it is not obvious how to apply the semantics at semver.org to Modelica libraries, and questions have been raised regarding how to deal with violations against the versioning rules. I think it is best to make separate rules for Modelica library semantic versioning, based on ideas from semver.org. The basic rules could be formulated as:
  • Bump major version when a backward incompatible change is introduced.
  • Bump minor version when new stuff is added in a backward compatible way.
  • Bump patch version when existing stuff is modified (bugfixes, etc) in a more or less backward compatible way.
    I don't think that one has to care about stuff that depend on buggy behavior, and therefore break when a bug is fixed (meaning that fixing a bug should not imply bumping major version). The trickier question is what to do when changing (improving) the dynamic behavior of a component in the library. That will break correctness testing against reference results computed with the old dynamics, so in a way it seems like a backward incompatible change. I would, however, prefer to consider this similar to depending on buggy behavior, and therefore not require bumping of the major version.
  1. How to resolve a uses annotation when a library is using semantic versioning. As mentioned above, I think this one is obvious. Among the available versions of the library, simply pick the version of highest precedence among those that are semantically compatible. I guess the controversial part here might be that a uses annotation is not guaranteed to be resolved to the exact same version of the library, even if that version is available. Some examples of how to resolve uses(SomeLib(version="3.2.1")):
= Available versions = = Resolution = = Comment =
3.2.0, 3.2.2, 4.0.0 3.2.2
3.2.1, 3.3.0, 4.0.0 3.3.0
3.2.0, 4.0.0 N/A Possible dependency on a bugfix that appeared in 3.2.1.
3.2.1-alpha, 4.0.0 N/A
  1. How to update a uses annotation when making changes to a library using semantic versioning. If the uses annoation points at the version currently loaded, nothing needs to be done. The question is what to do when the currently loaded version is a later version that is compatible with the version in the uses annonation. Are there other alternatives than:
  • Refuse to make changes without updating the uses annoation to the currently loaded version.
  • Force the user to disable all newer versions, so that the loaded version is the exact version in the uses annotation.
  1. How to migrate a library non-semantic version numbering to semantic version numbering. When resolving a uses annotation with version="3.2.1", one has to be able to tell which of the available versions of the library that match. By just looking at "3.2.1" in the model, one cannot tell whether it is a semantic version number or not, and therefore one doesn't know whether the dependency may be resolved with version 3.2.2 or not. To figure this out, one must be able to infer this by looking at available versions of the library. If no version 3.... of the library is available, one can stop thinking, since no matching version can be found anyway. Now, if 3.2.2 is available and doesn't use semantic versioning, then we know that 3.2.1 cannot be resolved. On the other hand if 3.2.2 is available and uses semantic versioning, we need to be able to conclude what to do. Hence, it should be required all library versions of the same major version use the same type of versioning. As a consequence, many libraries will need to bump their major version when starting to use language version 3.S. (The exception is when a library has been following the semantic versioning rules even before starting to use langueage version 3.S.)

  2. Generation part of the version number. Personally, I am in favor of a four part version number, W.X.Y.Z, where W is the generation number, and is bumped only when a library is reincarnated with a completely new design, or when a library goes from generation 0 (library design is still under active development) to generation 1 (library design has settled and library is ready for widespread use). In most ways, W.X will work just as X alone in a three part version number. However, conversion scripts should not be expected to deal with upgrades between different generations, and parallel development in different generations can be done without the need to make patch releases with updated conversions. Having the generation number as part of the version number avoids the need to put the generation number in the name of the library, allowing a nicer user experience. For example, if a new MultiBody library would be developed one day, "MultiBody" is still a very good name for such a library, and a generation number in the version avoids the need to use an ugly name such as "MultiBody2". Another possible way to use a generation number is to require the generation number to be increased each time the backward incompatible changes cannot be handled with a conversion script.

  3. Version numbers with build metadata. For example, after releasing version 3.2.1, but before it is known whether the next release should be 3.2.2, 3.3.0, or 4.0.0, it is useful to have version numbers with build metadata, and attach something like a SHA1 and the number of commits since the last tagged version, like 3.2.1+123asd.18. I find it problematic that such a version number has equal precedence to 3.2.1 according to semver.org. I'd expect library developers to have both the latest release and one or more development versions installed on their system, and I don't think resolving a uses annotations pointing to version 3.2.1 with any of the development versions make sense. One possible solution could be to not follow the precedence rules at semver.org when resolving the version in a uses annotation, and only allow 3.2.1+ to match versions with build metadata (and no other versions that would be semantically compatible with 3.2.1, like 3.2.2), and also allow uses annotations pointing out a particular version with build metadata. This avoids the need to define new precedence rules for versions with build metadata, and a user who wants to use the latest of the versions with metadata can either make sure to only have that version installed, or point to a particular version.

  4. Allow parallel development in distinct major versions. There is little reason to allow parallel developmet in distinct minor versions (that is, starting from 3.2.1, first release 3.3.0, and then make additional patches to the minor version 2 in 3.2.2), since a new minor version should be better than the previous in every aspect (in particular, contain the same bugfixes). The question whether parallel development should be allowed in distinct major versions, that is, starting from 3.2.1, first make backwards incompatible changes and release 4.0.0, then fix a bug in major version 3 and release 3.2.2 (or add a new feature and release 3.3.0, for that matter). Allowing parallel development means that version precedence (as defined at semver.org) does not necessarily correspond to chronological order, or that a version with higher precedence should be expected to be superior. The main problem I see here comes when semantic versioning is combined with conversion annotations, as releasing new features in 3.3.0 may call for additional conversion operations to be added to the already released major version 4. It may not be more difficult to handle than require that a the new conversions are included in a new patch release of major version 4, but it's nevertheless a problem to be considered.

  5. Multiple versions in the uses annotation. Sometimes, a package may be compatible with more than one major version of a library, because the backward incompatible changes don't affect the parts of the library that are actually used. Should the package be forced to select only one of the major versions, or should multiple versions be allowed in the uses annotation? If multiple versions would be allowed, it would probably be a good idea to disallow semantically compatible versions in the list. For example, uses(SomeLib(version={"2.0", "2.1", "3.2.1", "4.0.0"})) could be allowed if versioning was introduced in version 3.0.0, while uses(SomeLib(version={"2.0", "2.1", "3.2.1", "3.3.0"})) wouldn't make sense in terms of semantic versioning (specifying "3.3.0" is redundant in the presence of "3.2.1").

@modelica-trac-importer
Copy link
Collaborator Author

Comment by henrikt on 24 Sep 2015 14:27 UTC
Some scenarios to support the discussion:

  1. LibA depends on LibB v 3.2.1, user uses LibA without making modifications to it.
    a. User has one or more versions of LibB installed that are compatible with 3.2.1.
    b. User has no version of LibB installed that is compatible with 3.2.1.

  2. LibA depends on LibB v 3.2.1, user makes changes to LibA, has one or more versions of LibB installed that are compatible with 3.2.1.
    a. Version 3.2.1 is one of the installed versions.
    b. Version 3.2.1 is not one of the installed versions.

  3. LibA is at version 3.2.1, and library developer is fixing a bug.
    a. The bug is fixed and shall be released immediately.
    b. The bug is fixed, but more development is expected before the next release.

  4. LibA is at version 3.2.1, library developer adds a new component, and — by mistake — only bumps the minor version to 3.2.2 when releasing a new vewsion of the library.

  5. LibA is at version 3.2.1, a bad design change is made, leading to the release of the very impopular version 4.0.0, and a regretful library developer wants to resume development of major versio 3. (New releases under major version 3 may require updated conversion annotations in major version 4, thereby requiring new patch releases of major version 4.)

  6. LibA is at version 3.2.1, a backward incompatible change is made, and is — by mistake — released in version 3.2.2 (alternatively, in version 3.3.0).

  7. LibA is at version 3.2.1, and a change is made that shall be released immediately (avoiding the question of how to label development versions in this scenario).
    a. A bug is fixed in a completely backwards compatible way.
    b. A bug is fixed in a non-backwards compatible way.
    c. An error in the expression for the inertia matrix of a rigid body is corrected. More generally, fixing errors in the dynamics of ideal (undisputed definition of correct dynamics) components.
    d. A real parameter value is changed to tweak model dynamics.
    e. A structural parameter value is changed.
    f. An expression is changed to tweak model dynamics.
    g. The dynamics of a component is fundamentally changed (without changing the interface).
    h. A new component is added.
    i. An obsolete component is removed.
    j. A component of poor quality is removed.
    k. Aestetic changes are made (icons, diagrams, documentation).
    The idea is not to get a list of actions to take in each of these scenarios, but to verify that a small number generic rules gives a clear answer in each case.

  8. An old well-maintained pre-3.S library at version 1.5.0 is updated to language version 3.S. (Makes sense to think of "1" as generation, and "5" as major, suggesting to make next version 1.6.0.0.)

  9. An old well-maintained pre-3.S library at version 13.7.1 is updated to language version 3.S. (Makes sense to think of "13" as major, suggestion to make next version 14.0.0, or 1.14.0.0.)

  10. A user upgrades to a newer semantically compatible version of a library, but finds that some models that depend on the library break because of this. (Library developer needs to be informed, so that the problems can be fixed in a new patch release.)

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 25 Sep 2015 08:36 UTC
First a minor clarification about current status and semantic versioning, which will then lead to more complicated issues (that haven't gotten enough attention in my opinion).

There are three parts of semantic versioning:

  1. Format of version numbers
  2. How to compare version numbers
  3. Semantics of semantic versioning

Versions number in Modelica 3.3r1 are defined including ordering (except as listed below). The version numbers in Modelica 3.3r1 are more general (more levels) - and are slightly different than semantic versioning - using space instead of hyphen to separate pre-release/beta versions, and having "build" as a separate number instead of part of the version number.

The comparisons of versions use the same logic in Modelica 3.3r1 and semantic versioning; except for some odd cases for hierarchical pre-release versions (which I don't think we have used; basically SemVer allows "Beta.9", "Beta.10" to be correctly ordered).

There are also unordered versions in Modelica 3.3r1 - that was intended for things like "MyVersion", "Testing" - I don't know if anyone actually uses those version numbers; and I don't have any strong feelings about them.

But what abut semantics?

Modelica 3.3r1 does not define any semantics for the versions, and I believe this should be main focus - but there are three main issues:

  • We don't (yet) have a clear definition of the semantics for public API/backward compatibility. [Plug compatibility is different.]
  • It seems unclear that we can get reasonable semantics for public API that handles all existing cases and is 100% safe.
  • Semantic Versioning 2.0.0 lacks reasonable error handling (see below).

This means that we need to completely need to define the semantics of versions and cannot just reference an existing version of Semantic Versioning.

The things we need to consider are:

  • Many operations currently construct public elements in existing tools (e.g. 'New class' and Drag'n'drop in Dymola) and any new public elements is an extension of the public API. In some cases that could be reduced in tools by as default creating "protected" elements, but the usability must be considered.
  • Adding a named element (public or protected) to any public class is formally a breaking change, since someone could use "extends ..." and get a conflict (some cases could break for "import A.*" as well). For MSL we try to avoid it for new builds - especially for partial classes - but that is a bit ad-hoc. This is not covered by plug-compatibility since we don't have replaceable base-classes (anymore).

One might think that we could define the public API in a way that does not allow "extends ..." from non-partial classes. However, e.g. VehicleInterfaces have non-partial classes that are intended to extend from - with no special marking; and there are also other cases where extending is normal.
We might also want to more or less exclude the Examples from the public API for some libraries - but the details are unclear.

If we cannot find a 100% safe solution the benefits seems less clear.

One possibility would be that we could e.g. extend the uses-annotation to indicate that we use more than the public API, e.g.: "uses(Modelica="3.2", extendingFrom= true)", but how and what it brings isn't clear.
Similarly we could add something to indicate that a non-partial class is intended to be used as a base-class (new keyword? annotation?).

I'm not saying that using the semantics of semantic versioning is a bad idea or impossible - just that the details are unclear at the moment; and we have a lot of work to do - and that success is not guaranteed.

Replying to [comment:11 henrikt]:

Here is some input for the discussion tomorrow evening. I know it is a lot, but I don't know how to organize it all in a ticket thread like this. Perhaps some of this should go into a development document, and then we could break down the discussion in this thread to consider smaller parts of the document.

In order to bring the discussion back to the ticket, I'll try to summarize the main problems that need to be resolved.

Before going to the problems, however, I'll state some things that seem clear to me at this point.

  1. I consider a (Modelica) language version header (MCP-0015) a widely accepted prerequisite for the semantic versioning of libraries. In the discussion below, let's assume that semantic versioning of libraries is introduced in Modelica language version 3.S ("S" for "Semantic").

  2. The semantics of a a version number is a property of the library, not a property of the model that uses the library. That is, even if a model uses Modelica version 3.S, not all its uses annotations are necessarily refering to semantic version numbers. Conversely, a tool that is able two handle multiple versions of the language at the same time may allow a model using language version 3.3 (as can be seen by the absence of a language version header) to have uses annotations pointing to libraries with semantic version numbers, and resolve these version numbers as such.

  3. If the language specification mandates that library version numbers are semantic as of language version 3.S, I think that the way we define semantics must be able to rely on version numbers following the semantic rules.

I am not sure that we can make an informed decision whether semantic versioning should be required starting from a specific version or not before we have more information about the details - as indicated previously 'public API' is not clear.

Thus I would propose to delay this until the other issues are resolved, or possibly having it optional while we are working on the details - that would allow us to get some of the benefits before everything is clear.

To support this, we must find ways to deal with the scenarios where the semantic rules have been violated.

I agree that we need to handle cases where errors have occurred in a good way, and will later try to explain how that could be handled.
However, the only way to deal with it according to the specifications of Semantic Versioning 2.0.0 is to reject your software as non-conformant, i.e. reject all versions of your software as non-conformant.

I am not even sure that the SemVer specification allows you to say that only some library versions are semantically versioned - i.e. even if we don't make any mistakes in the future we might still not be able to say that MSL is semantically versioned due to older versions.

You might argue that this is extreme - but either we follow an existing version of SemVer (which doesn't work in case of errors) - or we clearly define our own rules "in the spirit of SemVer".

  1. Generation component of the version number. Personally, I am in favor of a four part version number, W.X.Y.Z, where W is the generation number, and is bumped only when a library is reincarnated with a completely new design, or when a library goes from generation 0 (library design is still under active development) to generation 1 (library design has settled and library is ready for widespread use).

Having four part version numbers is also an alternative that can be discussed, and is close to the current MSL versions, except that Z is separated out into the build-number. (A separate build-number has some minor problems, e.g. pre-release versions of builds are oddly numbered: "3.2.1 Release Candidate 5" - build 4 is more logically "3.2.1.4 Release Candidate 5" in the sense that the Release Candidates are per build.)

I understand that for other projects this is also quite common, and have seen several people arguing for adding something like that to Semantic Versioning.

However, it is not any version of Semantic Versioning 2.0.0. But if we anyway have to define our own rules that is not a problem - we just need clear understandable rules.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by choeger on 25 Sep 2015 09:40 UTC
Since I am not at the meeting, just a few comments:

  • Package managers require a defined (partial) order of versions. Semantic versioning provides that specific semantics - as could the Modelica specification. I think this first point is both crucial and undisputed.

  • Semantic versioning provides compatibility assertions on top of that. The current debate focuses mostly on if and how that compatibility can be ensured. Hans just mentioned hygiene of superclasses as a very good point, that has not been discussed yet. Of course, one can always bump the major version (and our mental preference of rather small version numbers is of course completely irrational). However, it is debatable whether there are that many potential changes to a Modelica library that warrant a minor version bump instead of just a patch level one.

My pragmatic conclusion would be to introduce mandatory semantic versioning syntax, semantic versioning ordering semantics and, optionally, semantic versioning compatibility semantics (e.g. by an additional annotation). That way, a library could safely migrate to complete semantic versioning semantics by setting a flag and still use semantic versioning syntax for older versions.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by henrikt on 25 Sep 2015 10:00 UTC
It seems like we are all pretty much on the same page.

To me, there appears to be several important subtopics of this discussion, with the most difficult one being how to define backward compatibility in a useful manner. I don't see how we can manage discussion of all of these topics at the same time in this ticket alone. How about creating sub-tickets for the different sub-topics, so that each can be discussed in isolation?

@modelica-trac-importer
Copy link
Collaborator Author

Comment by henrikt on 25 Sep 2015 10:16 UTC
Replying to [comment:13 hansolsson]:

I am not sure that we can make an informed decision whether semantic versioning should be required starting from a specific version or not before we have more information about the details - as indicated previously 'public API' is not clear.

There was lengthy discussions about this in Waterloo, and then, the conclusion was that semantic versioning should be mandatory as of the language version where it is introduced. This causes no problems for legacy libraries, as they will still use an older version of the language, and when a new library is released using the new version of the language, one just have to make sure to bump the major version if the previous version number was in the form of a semantic version number.

The more general argument for making semantic versioning mandatory is that we don't want a language with features that can be turned on and off. If we introduce an optional language feature now, this would be an excuse for introducing even more feature switches when it is hard to find agreement on other language improvements in the future. For example, I sometimes find it a bit scary that there are non-differentiable built in functions that don't generate events, but I understand that introducing a feature switch for this into a growing collection of switches would be a mess both for users and tool makers.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 30 Sep 2015 13:12 UTC
I realized something related to versions.

The different version schemes mostly differ in how they construct ONE string containing all parts of the version-information (API-version (possibly split into (generation), major, minor), patch (or build), pre-release-information, meta-data).

Having one string is useful for tools - but for humans it seems easier to understand if we actually present the parts separately. This has also been both for the Modelica Standard Library and Modelica Language Specification.

Considering some recent MSL and MLS version we have:
MSL 3.2.1+build.3 ->
API-version: 3.2.1
Patch-level: 3
Optional pre-release/beta indicator (empty here):

MSL 3.2.1+build.4-rc1 ->
API-version: 3.2.1
Patch-level: 4
Optional pre-release/beta indicator: rc1

MLS 3.3 revision 1 ->
API-version: 3.3
Patch-level: 1 (although some parts are more than a "bug-fix")
Optional pre-release/beta indicator (empty here):

MLS 3.4 ->
API-version: 3.4
Patch-level: 0
Optional pre-release/beta indicator:

There are then two separate questions:

  • What are the versions formally called. Using semantic versioning (extended with generation number) it would be uniquely be: API + "." + Patch +(if beta=="" then "" else "-"+beta), i.e. "3.2.1.3" and "3.2.1.4-rc1", "3.3.1", "3.4.0-...".

  • What do the annotations/library descriptions contain? Obviously one possibility is to have the string above, but another solution would be to have three separate annotations, as indicated above.
    The reason for having them separate isn't to make it easier for tools (the difference is very minor) - but to help humans understand it.

As for the currently unnamed version a simple idea would be to just use the date, e.g.: "2015-09-30" (i.e. YYYY-MM-DD format); since they will be sorted correctly and before any alpha/beta/rc. (It is formally a valid pre-release identifier in semantic versioning, even though not exactly in the spirit.)
Having some prefix would be nicer, except that it is has to be alphabetically before "alpha".

It might also be that we need something completely different during development (i.e. before the beta-phase).

Replying to [comment:14 choeger]:

Since I am not at the meeting, just a few comments:

* Package managers require a defined (partial) order of versions. Semantic versioning provides that specific semantics - as could the Modelica specification. I think this first point is both crucial and undisputed.

I agree that an ordering is needed.

And just to be clear: the current Modelica Specification already provides a partial ordering for versions (which for normal versions is the same order as defined by semantic versioning).

My pragmatic conclusion would be to introduce mandatory semantic versioning syntax, semantic versioning ordering semantics and, optionally, semantic versioning compatibility semantics (e.g. by an additional annotation). That way, a library could safely migrate to complete semantic versioning semantics by setting a flag and still use semantic versioning syntax for older versions.

To me there are two parts of the compatibility semantics: patches and normal versions.

I believe the specification could limit patches to compatible bug-fixes (that distinction is fairly clear), but the separation of other changes into minor/major is currently semantically unclear and should be optional.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by otter on 12 Nov 2015 10:04 UTC
Replying to [comment:27 sjoelund.se]:

Pre-release version numbers work rather OK for us in OpenModelica using git. For example: v1.9.4-dev.473+gea54626: 1.9.4 development, 473 commits from development started, git hash ea54626 (note that there may be multiple copies 473 commits deep, even in the same branch). The git hash is there so we know exactly what commit someone is using, and the sequence is there to give the user (of nightly builds) the feel of a linearly increasing version number.

Does this also work if there are different forks and different branches in different forks? Even if this works then this means probably that for every committ "somehow" the version number has to be updated in the library (which seems not practical).

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 12 Nov 2015 10:23 UTC
Replying to [comment:27 sjoelund.se]:

Pre-release version numbers work rather OK for us in OpenModelica using git. For example: v1.9.4-dev.473+gea54626: 1.9.4 development, 473 commits from development started, git hash ea54626 (note that there may be multiple copies 473 commits deep, even in the same branch). The git hash is there so we know exactly what commit someone is using, and the sequence is there to give the user (of nightly builds) the feel of a linearly increasing version number.

If you rely on the git-hash to disambiguate versions you are not following semantic versioning (depending on version that is either a bit wrong - or completely wrong).

As I understand your scenario with distributed development scenario it might be that 405, 413 and 473 is one branch and 406, 413 (with other hash) and 460 are on another branch.

An issue with distributed development is that there is no strict order between the versions on different branches that make sense (as assumed by semantic versioning), but what you state is that users only look at a sub-set of version (the nightly builds) - and that sub-set is strictly ordered (since the nightly builds are centralized).

Basically you are not really following any published version of semantic versioning - but something inspired by it. That wouldn't be a problem if people stated that (and specified those rules).

Added: Mathematically speaking the difference is that semantic versioning imposes a 'total order', but we only have 'partially ordered set' (at least for the distributed development versions).

@modelica-trac-importer
Copy link
Collaborator Author

Comment by sjoelund.se on 12 Nov 2015 10:47 UTC

If you rely on the git-hash to disambiguate versions you are not following semantic versioning (depending on version that is either a bit wrong - or completely wrong).

We don't. The released versions will all use unique identifiers though (which are monotonous). A git describe in someone else's repository might use the same id, but the official repository's HEAD will not re-use IDs. With the hashes, you can tell if someone for example uses a different repository or branch (so, unofficial releases).

No one else can make an official release anyway. I mean... some random person (let's say me) can't start distributing MSL as 4.7.3 and expect that it follows semver. And the fact that someone would create this file does not magically make the official MSL not follow semver anymore.

Of the releases (made from the HEAD of the master branch on the development server), the ordering is total. And that can be considered authoritative.

Note: Maintenance branches can be handled in a similar way (if for example, the last release is 3.3.0, you can have it auto-increment release builds like 3.3.1 for 1 commit into the branch).

Anyway, I do not think it is problematic as long as one sets up a good system for how to deal with versions.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 12 Nov 2015 11:20 UTC
Replying to [comment:30 sjoelund.se]:

Anyway, I do not think it is problematic as long as one sets up a good system for how to deal with versions.

I agree, and the problem is that we need a good system for how to deal with versions, or more specifically:

  • One would think that if we add semantic versioning we would actually have semantics of versions - including how to know if it is a released version or a development version. I don't see the benefit of super-strict rules if we don't know when they apply.
  • Semantic versioning (in current forms) does not fit the requirements of distributed development. Requiring an order between unrelated development versions does not make sense, and I don't see that this scenario is a major issue for the license and a non-issue for the versioning.
    (It might be that we should solve both issues together: modified work must be marked as being non-released, and then relaxing the rules for such versions.)

@modelica-trac-importer
Copy link
Collaborator Author

Comment by choeger on 12 Nov 2015 13:18 UTC
Replying to [comment:31 hansolsson]:

* Semantic versioning (in current forms) does not fit the requirements of distributed development.

Why? In what scenario would there be which problem? e.g. the linux kernel follows something very similar to semver and is one of the largest distributed projects that I know of - so I assume they would have hit any practical problem.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 12 Nov 2015 14:10 UTC
Replying to [comment:32 choeger]:

Replying to [comment:31 hansolsson]:

* Semantic versioning (in current forms) does not fit the requirements of distributed development.

Why? In what scenario would there be which problem? e.g. the linux kernel follows something very similar to semver and is one of the largest distributed projects that I know of - so I assume they would have hit any practical problem.

The Linux kernel uses a hierarchical numbered version number for released versions; I believe we all agree that it makes sense - and we already use that for MSL, and it is specified in the current Modelica specification.

However, Linux kernel does not follow semantic versioning (in terms of version numbering and semantics). Even the current Modelica version specification seems closer to semantic versioning than the Linux kernel versioning described below.

At least according to
https://en.wikipedia.org/wiki/Linux_kernel#Version_numbering
they have generation.major.minor (and sometimes .emergencyPatch) and development versions use initial of developers, not any generic "dev", "alpha" designator and thus avoid the problem of distribution and strict ordering.

For the semantics the Linux kernel is not following semantic versioning (regarding API-changes). That's why Linus asked if he should make Linux kernel 4.0 or not; whereas it for semantic versioning would be automatic iff any internal API in the kernel had any incompatible change.

I have a feeling that telling Linus to use semantic versioning in its current form might not get a polite response.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by henrikt on 13 Nov 2015 08:21 UTC
Replying to [comment:31 hansolsson]:

Replying to [comment:30 sjoelund.se]:
* One would think that if we add semantic versioning we would actually have semantics of versions - including how to know if it is a released version or a development version. I don't see the benefit of super-strict rules if we don't know when they apply.
* Semantic versioning (in current forms) does not fit the requirements of distributed development. Requiring an order between unrelated development versions does not make sense, and I don't see that this scenario is a major issue for the license and a non-issue for the versioning.

I'll try repeat/rephrase what I think sjoelund.se already explained here. The good intention to have distributed development in mind does not mean we should promote versioning anarchy by the way we open things up in the semantic versioning scheme we decide on. Distributed development is good, but having multiple authorities that independently define their own official version numbers for the same library is not good. Each library should have one authority that defines the content of official releases that the corresponding version numbers.

In my opinion, a contributor should never introduce version numbers deriving from not yet officially released version numbers. If the intention is to make a new feature part of a specific not yet released version, there are cleaner ways to communicate this to the primary maintainer than to encode it in a semantic version number. For a big contribution project, clearly communicating which (feature) branch is being distributed is probably a better idea than fiddling with the semantical parts of a semantic version number. Users will have to be aware anyway that they are not using an official release, and a version number like 4.3.2+NewMultiBody.7654.gea54626 could be one way of telling that this is a non-official release of the NewMultiBody project, currently 7654 commits from the official release 4.3.2, having hash gea54626. (Note that it is the NewMultiBody project itself that decides to include its name in the build metadata.)

Since not everybody is using Git, we cannot decide on a semantic versioning scheme where a Git hash is a mandatory part. We just have to make sure that the scheme is flexible enough to make it possible to specify build metadata like the one used by OpenModelica or in the NewMultiBody example above.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 13 Nov 2015 09:21 UTC
Replying to [comment:34 henrikt]:

Replying to [comment:31 hansolsson]:

Replying to [comment:30 sjoelund.se]:
* One would think that if we add semantic versioning we would actually have semantics of versions - including how to know if it is a released version or a development version. I don't see the benefit of super-strict rules if we don't know when they apply.
* Semantic versioning (in current forms) does not fit the requirements of distributed development. Requiring an order between unrelated development versions does not make sense, and I don't see that this scenario is a major issue for the license and a non-issue for the versioning.

I'll try repeat/rephrase what I think sjoelund.se already explained here. The good intention to have distributed development in mind does not mean we should promote versioning anarchy by the way we open things up in the semantic versioning scheme we decide on. Distributed development is good, but having multiple authorities that independently define their own official version numbers for the same library is not good. Each library should have one authority that defines the content of official releases that the corresponding version numbers.

I agree, and my main input is that distributed development and sites like github makes it even more important to have a good versioning system, because the development no longer have a strict order(the official releases still do), and all versions are available to the public at the same level (including development ones).

In my opinion, a contributor should never introduce version numbers deriving from not yet officially released version numbers. If the intention is to make a new feature part of a specific not yet released version, there are cleaner ways to communicate this to the primary maintainer than to encode it in a semantic version number. For a big contribution project, clearly communicating which (feature) branch is being distributed is probably a better idea than fiddling with the semantical parts of a semantic version number. Users will have to be aware anyway that they are not using an official release, and a version number like 4.3.2+NewMultiBody.7654.gea54626 could be one way of telling that this is a non-official release of the NewMultiBody project, currently 7654 commits from the official release 4.3.2, having hash gea54626. (Note that it is the NewMultiBody project itself that decides to include its name in the build metadata.)

Yes, something like the above might work. One solution might be to be generous with project names (and use user-names as backup/part of hierarchy) - and/or possibly accept that development versions may not unique version numbers.

An interesting part of this is that you are also discussing post-release development, i.e. 4.3.2+changes whereas semver only discusses pre-releases 4.3.3-notYetDone. (There are several proposals for changing this aspect of semver, of course.)

If we consider a distributed scenario where people want to (report and) fix bugs and propose additions I agree that the scenario of post-release version might in many cases be a preferable alternative to pre-release versions.
That keeps the decision about new releases centralized - without blocking development.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by henrikt on 13 Nov 2015 09:45 UTC
Replying to [comment:35 hansolsson]:

Replying to [comment:34 henrikt]:

In my opinion, a contributor should never introduce version numbers deriving from not yet officially released version numbers. If the intention is to make a new feature part of a specific not yet released version, there are cleaner ways to communicate this to the primary maintainer than to encode it in a semantic version number. For a big contribution project, clearly communicating which (feature) branch is being distributed is probably a better idea than fiddling with the semantical parts of a semantic version number. Users will have to be aware anyway that they are not using an official release, and a version number like 4.3.2+NewMultiBody.7654.gea54626 could be one way of telling that this is a non-official release of the NewMultiBody project, currently 7654 commits from the official release 4.3.2, having hash gea54626. (Note that it is the NewMultiBody project itself that decides to include its name in the build metadata.)

Yes, something like the above might work. One solution might be to be generous with project names (and use user-names as backup/part of hierarchy) - and/or possibly accept that development versions may not unique version numbers.

Right, let us not try to enforce global uniqueness of build metadata. We would be doomed to fail unless we introduce something the size of reverse DNS namespaces for build metadata. Imagine having to deal with version numbers like 4.3.2+com.wolfram.NewMultiBody.7654.gea54626, and how projects would have to agree on which reverse DNS to use… and not even this would work for individual contributors that don't have their own domain…

I don't think that we shouldn't even define project and/or user names in the versioning scheme, only not that such things should go into the build metadata part if someone wants to include such information. We should not define semantics for the build metadata, so by just looking at a semantic version number with build metadata, it won't be clear if the alphanumeric chunks denote project names, user names, branch names, exceptional hashes, or whatever. The interpretation of the build metadata should be defined where the non-official version is being distributed. Let us focus on the semantics of official release versions, including official pre-release versions.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by mtiller on 13 Nov 2015 13:29 UTC
Replying to [comment:35 hansolsson]:

Replying to [comment:34 henrikt]:

Replying to [comment:31 hansolsson]:

Replying to [comment:30 sjoelund.se]:
* One would think that if we add semantic versioning we would actually have semantics of versions - including how to know if it is a released version or a development version. I don't see the benefit of super-strict rules if we don't know when they apply.
* Semantic versioning (in current forms) does not fit the requirements of distributed development. Requiring an order between unrelated development versions does not make sense, and I don't see that this scenario is a major issue for the license and a non-issue for the versioning.

I'll try repeat/rephrase what I think sjoelund.se already explained here. The good intention to have distributed development in mind does not mean we should promote versioning anarchy by the way we open things up in the semantic versioning scheme we decide on. Distributed development is good, but having multiple authorities that independently define their own official version numbers for the same library is not good. Each library should have one authority that defines the content of official releases that the corresponding version numbers.

I agree, and my main input is that distributed development and sites like github makes it even more important to have a good versioning system, because the development no longer have a strict order(the official releases still do), and all versions are available to the public at the same level (including development ones).

I'd like to address the two comments that "Semantic versioning (in current forms) does not fit the requirements of distributed development" and "distributed development and sites like github makes it even more important to have a good versioning system".

Let's take a step back here to recognize that npmjs.org hosts over 205,000 packages. They use semantic versioning (https://docs.npmjs.com/getting-started/semantic-versioning). Furthermore, nearly all of those packages are actually developed via GitHub. As such, I'm puzzled by the notion that semantic versioning is somehow not sufficient for use either with GitHub or that it would somehow be insufficient for distributed version control. As we say in English, "the proof is in the pudding".

That being said, one advantage they have in the Javascript world is the de facto universal registry that is npmjs.org. So in some sense, what we might be missing is a definite source for naming that disambiguates any competing claims to a name. But that is part of what Dietmar and I have been trying to do with the impact project because if you look carefully you will see that the public impact index (which is what is used by our impact search engine(impact.github.io) and the impact command-line tool is based on the projects specifically registered on GitHub under the modelica, modelica-deprecated and modelica-3rdparty organizations. In other words, we are already attempting to establish a fixed namespace to avoid confusion over library names. This approach allows people, without issue, to fork and modify libraries.

In summary, GitHub+Semantic Versioning = proven success at scale. I would argue that what this discussion highlights more than anything is the need for a universal registry of Modelica packages and an associated index. That is what we are trying to do with impact. So I think our energy would be better spent trying to realize such a registry than arguing about whether distributed development and semantic versioning can actually work.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 13 Nov 2015 13:45 UTC
Replying to [comment:36 henrikt]:

Replying to [comment:35 hansolsson]:

Replying to [comment:34 henrikt]:

In my opinion, a contributor should never introduce version numbers deriving from not yet officially released version numbers. If the intention is to make a new feature part of a specific not yet released version, there are cleaner ways to communicate this to the primary maintainer than to encode it in a semantic version number. For a big contribution project, clearly communicating which (feature) branch is being distributed is probably a better idea than fiddling with the semantical parts of a semantic version number. Users will have to be aware anyway that they are not using an official release, and a version number like 4.3.2+NewMultiBody.7654.gea54626 could be one way of telling that this is a non-official release of the NewMultiBody project, currently 7654 commits from the official release 4.3.2, having hash gea54626. (Note that it is the NewMultiBody project itself that decides to include its name in the build metadata.)

Yes, something like the above might work. One solution might be to be generous with project names (and use user-names as backup/part of hierarchy) - and/or possibly accept that development versions may not unique version numbers.

Right, let us not try to enforce global uniqueness of build metadata. We would be doomed to fail unless we introduce something the size of reverse DNS namespaces for build metadata. Imagine having to deal with version numbers like 4.3.2+com.wolfram.NewMultiBody.7654.gea54626, and how projects would have to agree on which reverse DNS to use… and not even this would work for individual contributors that don't have their own domain…

I agree - except a terminology change.

We shouldn't call it metadata as that causes confusion with metadata in semver (which is ignored for the versioning - more or less strictly depending on version); whereas this development-tag is an important part of the version.

What I don't want is to that claim that we use semver - and/or its terminology and then have different semantic meaning, even if we certainly wouldn't be the first ones to do that.

Let us focus on the semantics of official release versions, including official pre-release versions.

I agree that the important part is handling official versions, and being able to tell if it is an official version or not.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by henrikt on 16 Nov 2015 07:43 UTC
Replying to [comment:38 hansolsson]:

Replying to [comment:36 henrikt]:

Right, let us not try to enforce global uniqueness of build metadata. We would be doomed to fail unless we introduce something the size of reverse DNS namespaces for build metadata. Imagine having to deal with version numbers like 4.3.2+com.wolfram.NewMultiBody.7654.gea54626, and how projects would have to agree on which reverse DNS to use… and not even this would work for individual contributors that don't have their own domain…

I agree - except a terminology change.

We shouldn't call it metadata as that causes confusion with metadata in semver (which is ignored for the versioning - more or less strictly depending on version); whereas this development-tag is an important part of the version.

OK, but then we don't agree. :) What I suggested was to use the semver metadata concept, so that we don't have to define order in version number anarchy (where anybody is entitled to introduce version numbers at will, and distribute more or less official versions of a library in a completely decentralized manner).

The official registry that Mike suggested in comment 37 would be one way of defining what the official version numbers are, as well as indirectly defining the authorities defining version numbers for each library (by means of privileges to add new version numbers to the distribution site listed in the official registry). Personally, I think that each library would be able to define this by itself, without a need for an official registry. If a library fails to include a README file listing the primary distribution site and/or include this information in the top level package documentation, they might as well fail to register themselves with the official registry. (In my opinion, an official registry plays a more important roll for the allocation of library package roots — compare Java namespaces.) Anyway, I think the main point that Mike is making here is that the important thing is defining what the official versions are, rather than trying to define semantics of non-official versions.

What I don't want is to that claim that we use semver - and/or its terminology and then have different semantic meaning, even if we certainly wouldn't be the first ones to do that.

Sure, that seems sensible. It's just that, at the moment, the terminology from semver is still the best match for our discussions. In the end, we will need to define our own terminology, but even then, I think that large overlap with semver terminology is desirable to avoid confusion when talking about versions with those who have already adopted semver terminology for their mental picture of semantic versioning in general.

Let us focus on the semantics of official release versions, including official pre-release versions.

I agree that the important part is handling official versions, and being able to tell if it is an official version or not.

Again, this is not something that has to be clear from the semantic version number itself. It is enough to assume that each library has a single official site where official versions are defined. If a version is listed there, it is official, and vice versa. If you want an official release of a library, don't use a version with build metadata in the version number; get yourself a plain version instead, and it will be an official version as long as there aren't wild contributors to the library out there that don't respect the library's build metadata scheme (which should, at least, ensure that any deviation from an official release is marked with some sort of non-empty build metadata in the version number). Again, if we focus on the semantics of official releases, it should be up to each library to define how to use the build metadata part of the version number.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 17 Nov 2015 15:40 UTC
Replying to [comment:39 henrikt]:

Again, this is not something that has to be clear from the semantic version number itself. It is enough to assume that each library has a single official site where official versions are defined. If a version is listed there, it is official, and vice versa. If you want an official release of a library, don't use a version with build metadata in the version number; get yourself a plain version instead, and it will be an official version as long as there aren't wild contributors to the library out there that don't respect the library's build metadata scheme (which should, at least, ensure that any deviation from an official release is marked with some sort of non-empty build metadata in the version number). Again, if we focus on the semantics of official releases, it should be up to each library to define how to use the build metadata part of the version number.

I see, the idea is that we follow semver syntax and official versions have special "metadata" tags (either empty or some "magic" mark - which may depend on the package); and non-official versions have different non-empty ones.

That is fine and could work if we describe it.( * )

However, using the meta-data to give precedence to different versions is not semver 2.0.0 semantics from http://semver.org/ (and later even clearer):
Precedence MUST be calculated by separating the version into major, minor, patch and pre-release identifiers in that order (Build metadata does not figure into precedence).
MUST: This word, or the terms "REQUIRED" or "SHALL", mean that the definition is an absolute requirement of the specification.

Using pre-release syntax would require more discipline (as previously indicated) - and one can view this as reinterpreting meta data as "post-release information" ("-" means before and "+" after!).

*: One possibility would be cryptographic checksum for the official releases, although there are issues to resolve regarding that.

Replying to [comment:37 mtiller]:

I'd like to address the two comments that "Semantic versioning (in current forms) does not fit the requirements of distributed development" and "distributed development and sites like github makes it even more important to have a good versioning system".

Let's take a step back here to recognize that npmjs.org hosts over 205,000 packages. They use semantic versioning (https://docs.npmjs.com/getting-started/semantic-versioning).

The claim is that there are 205,000 packages and they state that they use semver.
One would think that this means that 205,000 packages use semver in some meaningful way, right?

Well, when I looked of the most recently changes packages 7 of 12, and for the most downloaded 6 of the 20 were below version 1.

That means that semver does not give ANY compatibility guarantees for those packages.

And for the ">=1.0.0" packages when looking I could see that many don't *strictly* follow semver (looking through changelog), and semver makes it clear that you can only follow it strictly; once your package is no longer semver compliant you are out. I believe that strictness is what attracts many to semver (it sounds impressive) - but then the strictness is often ignored in practice (when it comes in conflict with practical problems).

Additionally even npmjs does not strictly follow semver, in particular the precedence is different regarding pre-release tags (I actually find that the npmjs-precedence makes more sense than the semver one and solves some problems, but it doesn't suffice).

So, the point remains that forking in git and github causes similar problems for both semver and the Modelica License; and I don't see why we should solve one and ignore the other.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by mtiller on 17 Nov 2015 16:32 UTC
Hans, I don't understand your comments. A package with a version number less than 1.0.0 is still using semver. Such a version means "this is not ready for use, anything could break". I don't see why the presence of such packages doesn't constitute "meaningful" use of semver. They are using semver to express exactly what they want to express.

Furthermore, people who label their code with incorrect versions are irrelevant. No matter what system we come up with here, users will always be free to abuse the system. The important point with npm is that people are, in effect, punished for such things because their users will complain that their code is breaking when it shoudn't.

It would be more helpful if you pointed out specifically what you mean when you say "npm" doesn't follow semver for pre-releases. It may very well be true, but I couldn't find any reference to what you are talking about.

Finally, what would be more compelling as an argument would be to point out where any of these issues actually impacted somebody. We spend a lot of time in Modelica chasing ghosts of problems where actual problems don't exist.

My point was that lots of people use npm successfully. Nothing you said refutes that statement. This discussions is, in my opinion, a great example of the proverb "Perfect is the enemy of good". What is to be gained by spending what is likely to be years arguing about the perfect versioning system? I am willing to stipulate that semver may not be perfect. But I assert it is good enough and I don't feel you've demonstrated otherwise.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 17 Nov 2015 17:39 UTC
Replying to [comment:41 mtiller]:

Hans, I don't understand your comments. A package with a version number less than 1.0.0 is still using semver. Such a version means "this is not ready for use, anything could break".

And 6 out of 20 most downloaded packages were such packages.
Do you honestly not see that there is a problem when something that is not ready for use is used?

Furthermore, people who label their code with incorrect versions are irrelevant. No matter what system we come up with here, users will always be free to abuse the system. The important point with npm is that people are, in effect, punished for such things because their users will complain that their code is breaking when it shoudn't.

If a specification has an 'absolute requirement' it is not irrelevant if people break it.

According to semver the package is no longer compliant. The specification text for semver (in contrast to the FAQ) does not specify ANY way of getting back on track - or what 'back on track is', in fact there is NO WAY back.

That does not help users; so people ignore that and try to be sensible instead.

It would be more helpful if you pointed out specifically what you mean when you say "npm" doesn't follow semver for pre-releases. It may very well be true, but I couldn't find any reference to what you are talking about.

https://docs.npmjs.com/misc/semver#prerelease-tags

Finally, what would be more compelling as an argument would be to point out where any of these issues actually impacted somebody. We spend a lot of time in Modelica chasing ghosts of problems where actual problems don't exist.

The problem exists if we actually follow semver, but since you seem unconvinced that an absolute requirements matter - let us consider a practical example:
https://trac.modelica.org/Modelica/ticket/1241

I agree with the change, and I don't like that people are afraid to make sensible changes - just because of some theoretical compatibility issue.

Users don't complain if the interface is incompatible with previous version; they only complain if the change impacted them negatively.

My point was that lots of people use npm successfully. Nothing you said refutes that statement. This discussions is, in my opinion, a great example of the proverb "Perfect is the enemy of good". What is to be gained by spending what is likely to be years arguing about the perfect versioning system? I am willing to stipulate that semver may not be perfect. But I assert it is good enough and I don't feel you've demonstrated otherwise.

I don't want a perfect a versioning system - just one that has rules you can actually follow; whereas semver claims to be the perfect system.

And I didn't say that npm was bad - I discussed problems with semver, that matters since npm handles semver syntax and semantics that are both semver and semver-like.

So, I don't want a perfect versioning system just something basic with a suitable syntax and some rules (similar to the npm-summary of semver):

  • Major is for breaking things; ideally with conversion scripts (to be accepted)
  • Minor is for additions (public models and variables) - it should not break normal Modelica models
  • Patch is for the rest - no additional public models or variables, and it should not break normal Modelica models (and ideally not any other legal Modelica models)
  • Development versions are marked in some way so that they are not mistaken for actual releases
  • In case of error - make a patch that restores compatibility and communicate this.
  • And precedence for released version is the usual hierarchical numbering
    This is not intended to rule out any alternative for the syntax of the version numbers; and an alternative is to say that if the changes are fully handled by conversion scripts there is no breaking change.

The "normal Modelica models" needs to be defined to make it suited for Modelica; see comment 2 and 3 above - it is amazing how little the concrete problems of defining compatibility in Modelica have been discussed.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by henrikt on 27 Nov 2015 08:49 UTC
Should we try to get some time at the next meeting just for bringing some structure to the discussions?

@modelica-trac-importer
Copy link
Collaborator Author

Modified by dietmarw on 2 Dec 2015 10:08 UTC

@modelica-trac-importer modelica-trac-importer added MCP Generic MCP label (prefer specific MCP label for grouping of issues belonging to the same MCP) and removed MCP process labels Nov 4, 2018
@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 13 Sep 2016 13:16 UTC
Design group:
This ticket is long and it is somewhat difficult to follow the discussion.

One possibility is to split off separate tickets for specific topics - and just cross-linking them to this one. Do we agree that this is a good idea? Yes.

Some trac-systems can create sub-tickets, dependencies etc - we will just have to handle that manually. E.g. we will have to ensure that all subtickets are closed before closing the main one. We could also install the addon in trac for it - but then it adds maintenance.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by leo.gall on 24 Apr 2018 11:56 UTC
Does this ticket replace #573 Package improvements?

How do we get going, again? Plan a joint meeting of MAP-LANG and MAP-LIB?

@modelica-trac-importer
Copy link
Collaborator Author

Comment by dietmarw on 24 Apr 2018 12:20 UTC
I don't think it replaces #573 but can be handled independently. Having finally semantic versioning in place and standing on the shoulders of a giant like npm is definitely they way to go. They have a semver based system that is the largest registry (with today 619670 packages and growing by about 500 per day) in the world and *just works* (http://www.modulecounts.com/). If you are in doubt ask people like Michael Tiller who work with this on a daily basis.

So the pragmatic solution is to simply use this as also suggested by @HansOlsson

@modelica-trac-importer
Copy link
Collaborator Author

Comment by henrikt on 26 Apr 2018 20:23 UTC
One of the obstacles holding this back has been the Language Version MCP #1726, which has been considered a prerequisite for starting to apply semantic versioning rules for libraries. I'll move it now to _Under Evaluation', which gives us at least some progress in this area.

I still think it will be necessary to break down the discussion into sub-topics, before organizing something as big as a joint MAP-LANG and MAP-LIB meeting. Perhaps someone from MAP-LIB would like to join the working group, and then the working group could begin by doing the break-down? With a better overview, I hope we (as in this ticket thread) will be able to identify the most important sub-topics to be discussed in a bigger group.

@casella
Copy link
Collaborator

casella commented Jun 22, 2022

See also #3209 for the specific issue of what "backwards compatible" actually means.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request MCP Generic MCP label (prefer specific MCP label for grouping of issues belonging to the same MCP)
Projects
None yet
Development

No branches or pull requests