Search Unity

  1. Looking for a job or to hire someone for a project? Check out the re-opened job forums.
    Dismiss Notice
  2. Unity 2020 LTS & Unity 2021.1 have been released.
    Dismiss Notice
  3. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Semantic versioning like 1.0.x is not working

Discussion in 'Package Manager' started by arielsan, Mar 24, 2019.

  1. arielsan

    arielsan

    Joined:
    Dec 3, 2013
    Posts:
    44
    Hi, I was testing semantic versioning (semver calculator) to depend on latest patch of a specific version but can't make it work. I supposed it was supported by reading the forums and even by the error code:

    Code (txt):
    1. An error occurred while resolving packages:
    2.   Project has invalid dependencies:
    3.     com.unity.collab-proxy: Version '1.2.x' is invalid. Expected one of: a 'SemVer' compatible value; a value starting with 'file:'; a Git URL starting with 'git:' or 'git+', or ending with '.git'.
    4.  
    Am I doing it wrong? is it not supported yet?

    Thanks!
     
    Last edited: Mar 25, 2019
    user012345 likes this.
  2. JakHussain

    JakHussain

    Joined:
    Oct 20, 2016
    Posts:
    318
    I'm pretty sure all 3 digits need to be numbers. You can also add "-preview" at the end of the version number for the preview tag to appear in the package manager UI.
     
  3. okcompute_unity

    okcompute_unity

    Unity Technologies

    Joined:
    Jan 16, 2017
    Posts:
    736
    Hi @arielsan ,

    Semantic Versioning (SemVer) is at the core of the Unity Package Manager. But, what you are trying to set is called version range. It refers to SemVer versions. Two related but different concepts. Version range is not supported for the moment by Unity Package Manager. This is in our long term plan though. Note that we plan to implement a Nuget (or Scientific) notation. This is different than npm implementation.

    Hope it helps,

    Pascal
     
    mandisaw and JakHussain like this.
  4. arielsan

    arielsan

    Joined:
    Dec 3, 2013
    Posts:
    44
    Yes, it helps, and clarifies the concepts :), sorry I was messing them up.

    We'll have to wait until version range is supported then :(

    Thanks!
     
  5. JKort

    JKort

    Joined:
    Sep 14, 2017
    Posts:
    1
    Any update on this? Also wondering why to opt for the nuget implementation when everything else seems to be based on npm packages. Personally think the npm ranges are easier to read as well :)
     
  6. mandisaw

    mandisaw

    Joined:
    Jan 4, 2018
    Posts:
    51
    Just a guess, but probably because .NET/Visual Studio already understands NuGet.
     
  7. Florian-Nouviale

    Florian-Nouviale

    Joined:
    Mar 14, 2013
    Posts:
    30
    Hi, any news on this ? It's difficult for us to maintain CI generated dependencies automatically without version range
     
  8. maximeb_unity

    maximeb_unity

    Unity Technologies

    Joined:
    Mar 20, 2018
    Posts:
    243
    Nuget interval ranges are already implemented in Unity in the Assembly Definition inspector (see Version Defines). It didn't seem to make sense to implement the same concept with two different notations in two related contexts.

    We might possibly support a limited set of npm range operators, but probably not the full notation; npm range syntax allows defining arbitrarily complex, non-continuous version ranges (e.g.
    ^1.0.0 || 2.1.4 || (> 2.4.0 <=3.0.0) 
    is a valid range in that notation), but continuous version ranges are actually a characteristic on which the package manager depends to resolve dependencies efficiently.

    Lastly, on a more technical aspect, the notation "X.Y.Z" is actually supported in the Nuget notation as a shortform for the range starting at version X.Y.Z (inclusive), with no upper bound. Compare with "X.Y.Z" in the npm range syntax, which represents a range containing _only_ version X.Y.Z, and nothing else. That means changing the semantics of the dependency version notation while keeping backward-compatibility for all existing packages would be problematic (although not impossible, for sure). On the other hand, using the Nuget notation just means keeping the current interpretation of X.Y.Z and adding support for new forms.
     
  9. maximeb_unity

    maximeb_unity

    Unity Technologies

    Joined:
    Mar 20, 2018
    Posts:
    243
    There's currently no ETA for this feature yet. The range notation we intend to support will allow packages to specify explicit ranges in order to let the Package Manager avoid choosing incompatible combinations (i.e. conflict resolution) but will not have the effect of making the Package Manager pick a higher version.

    @Florian-Nouviale I will make an educated guess that your scenario involves CI-triggered tests using the latest dependency versions to continuously assess compatibility. Am I correct? In that case, what you could use is the "resolutionStrategy" property in your project manifest.json. It's not yet publicly documented (this is about to change), but it works similarly to Nuget's dependencyVersion property (see https://docs.microsoft.com/en-us/nuget/release-notes/nuget-2.8#-dependencyversion-switch). The supported values are "lowest" (default), "highestPatch", "highestMinor" and "highest".

    For example, to ask the Package Manager to upgrade transitive dependencies to the highest compatible minor versions:

    Code (CSharp):
    1. // manifest.json
    2. {
    3.   "dependencies" {
    4.     ...
    5.   },
    6.   "resolutionStrategy": "higherMinor"
    7. }
    Note that this only affects transitive dependencies for now, so your CI would still need to generate/update your test projects' manifest.json files with the highest versions of the direct dependencies you need to test.
     
    dvallee_bhvr likes this.
  10. bcapdevila

    bcapdevila

    Joined:
    Oct 26, 2016
    Posts:
    12
    @maximeb_unity do you have a clearer view now when UPM is going to support Ranges ?

    We would like to migrate from our in-house packaging module to UPM. But the fact that there are no ranges, makes it hard to handle transitive dependencies. Blocker
     
  11. maximeb_unity

    maximeb_unity

    Unity Technologies

    Joined:
    Mar 20, 2018
    Posts:
    243
    Hi @bcapdevila ,

    To clarify, a dependency declared on version "1.0.0" is understood as a dependency on "at least 1.0.0". (In node-semver range notation, it would be ">=1.0.0", while in Nuget range notation, it would be "[1.0.0,)"... or its shortform "1.0.0", which you might recognize, by no accident.)

    Given that this represents a (semi-infinite) range, and given that the Package Manager is deterministic by default, it will try to use the lowest versions possible from those ranges. But if you want it to consider higher versions in the ranges in a given project, you can configure this by setting the resolutionStrategy property in your project manifest. So to achieve the equivalent of "^1.0.0" or "1.x" as seen on other range notations, you could set the resolutionStrategy to
    "highestMinor"
    . Unfortunately this is currently a project-wide option - you cannot opt-in to have different resolutionStrategy settings applied for different dependencies.
     
  12. bcapdevila

    bcapdevila

    Joined:
    Oct 26, 2016
    Posts:
    12
    @maximeb_unity thanks for your reply, it actually helps understand better how the system actually works.

    Indeed, it is unfortunate that the resolutionStrategy is only applicable to the project and not for individual dependencies. But more unfortunate is that UPM doesn't make use of a richer dependency resolution as Node does.

    Our in-house packages (Uplift), define finer dependency ranges (1.2*, 1.0.3+, etc) and supports transitive dependencies along with them.

    Are you planning to improve the way UPM handles resolution of dependencies? For example, individual resolution strategies? Or using Node system?

    Thanks for your reply
     
  13. maximeb_unity

    maximeb_unity

    Unity Technologies

    Joined:
    Mar 20, 2018
    Posts:
    243
    The node-semver range notation covers a superset of version ranges that can be expressed in Nuget interval range notation. The main advantage of node-semver in that case is the ability to have ranges with holes (since a range is in fact defined as one or more groups of constraints), whereas intervals must be continuous, by definition. So, (apologies if you already know all this, I guess this can benefit other readers of this thread) for example, the node-semver range expression
    2.0.0 || ^2.2.0
    expresses a range where 2.0.0 and 2.2.0 are part of the range, but not 2.1.0.; there's no way to express that in Nuget interval notation (AFAIK).

    That said, the fact that npm picks higher versions in the range is not due to the syntax. Ranges define a set of valid versions, no more, no less, and npm's dependency resolution logic chooses to pick the highest possible version in that range. This is good to get bug fixes for transitive dependencies, but it can also break your project if a transitive dependency introduces a regression in a dependent package (whether by not respecting SemVer, or due to a flaw in the dependent). Note that it wouldn't be a problem for users who use a lock file, because the older version of D in their lock file ensures that npm will not automatically upgrade D unless explicitly told so. But people who newly add P to their project will have a broken P, and have to deal with this issue somehow.

    That's a rather extreme example, but that has harmed people in the past, where it wasn't a bug that was introduced, but a security vulnerability. So the idea of instead always falling back on the lowest version of the range, which will never change (barring that lowest version of the package being unpublished or republished with different contents), seems a safer default. Ultimately, we believe the project author should be in control of how much risk they are willing to accept: pick versions of dependencies that were presumably more tested by the package authors (lowest), opt-in bug fixes (higherPatch), opt-in features (highestMinor), or bleeding edge latest-don't-care-about-compatibility (highest). Nuget has this exact same feature (IIRC the configuration key is "dependencyVersion") and at one point adopted "highestPatch" as the default rather than "lowest", as it was deemed a better compromise to get bug fixes.

    Thanks for sharing!

    We know what I discussed above doesn't cover all use cases, such as individual resolution strategies or fancier dependency notation. We are looking at ways to provide this extra flexibility for more advanced scenarios without negatively impacting the experience of the majority of users, and without introducing backward-compatibility issues. I cannot be more specific on which improvement we'll be doing and when, unfortunately.

    Just to clarify, using npm's notation would not change anything unless we also change how the ranges are considered (and I already explained above why we won't do that). In fact, UPM already supports one type of Nuget interval ranges, since e.g. "1.0.0" is a short-form notation in Nuget interval notation for "[1.0.0,)", equivalent to node-semver's ">=1.0.0". (Yes, it is too permissive for SemVer, and this is one aspect we intend to fix, along with improved conflict management support and UX.)
     
unityunity