conan
conan copied to clipboard
[bug] Unexpected gtest pattern match
Environment details
- Operating System+version: ubuntu22
- Compiler+version: gcc11
- Conan version: 2.0.7
- Python version: 3.10.6
Steps to reproduce
Run conan install --tool-requires "gtest/[>=1.13.0]"
This matches against the gtest/cci.20210126 package even though this is older than 1.13.0. It looks like pattern matching works strictly on alphabetical order. I believe that this means that any version that starts with a letter will always be considered newer than any semver versioned package.
I know that you can't magically know that 1.13.0 is newer than the other version, but maybe the >= could only apply to semver style version names (or at least not mixing the search between versions that start with numbers vs letters)
Logs
conan install --tool-requires "gtest/[>=1.13.0]"
======== Input profiles ========
Profile host:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux
os.distro=Ubuntu22.04
[conf]
tools.system.package_manager:mode=install
tools.system.package_manager:sudo=True
tools.build:jobs=6
Profile build:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux
os.distro=Ubuntu22.04
[conf]
tools.system.package_manager:mode=install
tools.system.package_manager:sudo=True
tools.build:jobs=6
======== Computing dependency graph ========
Graph root
cli
Build requirements
gtest/cci.20210126#dafbdf84b58cd687075ace7314651c1a - Cache
Resolved version ranges
gtest/[>=1.13.0]: gtest/cci.20210126
======== Computing necessary packages ========
gtest/cci.20210126: Checking 9 compatible configurations:
gtest/cci.20210126: '56a52efa35140eb5207ec825a0bb891b949cb615': compiler.cppstd=11
gtest/cci.20210126: '5b58b26bab3b604200b3120eac772627b2d8c6b9': compiler.cppstd=gnu11
gtest/cci.20210126: 'd85bc90be65eb77509ff219bf6fa4d97cfbb5c39': compiler.cppstd=14
gtest/cci.20210126: '068a098979e0fbce80ada5dd1bef5f4ba13d93ef': compiler.cppstd=gnu14
gtest/cci.20210126: '5005402964adccc23074a5ec72c621050a153327': compiler.cppstd=17
Hi @jsallay
thanks very much for your report.
I think we need to discuss this behavior, if a bug or a feature. As Conan version range resolution is actually a kind of extension over semver this behavior of comparing letters with numbers is not defined in semver. Conan allows it, following alphanumeric ordering (then letters go after numbers, they are considered newer), and that seems consistent and good. Think for example of versions like 1.1.1, 1.1.9, 1.1.a, I think most people would expect that sequence to be correctly ordered and the a version come after the 1-9 ones.
I know that you can't magically know that 1.13.0 is newer than the other version, but maybe the >= could only apply to semver style version names (or at least not mixing the search between versions that start with numbers vs letters)
I am afraid this is not possible, one of the reasons the Conan semver extensions do compare letters with numbers is because it is necessary to do so in many cases that versions exists with letters, like openssl, that were simply ignored in Conan 1.X. Discarding comparisons that not comply strictly with standard semver gets us back to the initial problems.
Probably the right approach is to be able to explicitly exclude cci.... versions? Why not just specifying it explicitly with test_requires("gtest/[>=1.0 <cci]")
The workaround is sufficient for my needs. Another potential solution would be to remove the cci version from conan center, since it is fairly old. I don't know if you guys have any sort of roll off policy for old packages.
I'll leave the issue open since you said I think we need to discuss this behavior, if a bug or a feature. Feel free to close it is you decide that it's not worth fixing.
Oh, yes, the cci.xxx version has been removed from the conan-center-index repo some time ago. But the binaries and recipes in ConanCenter actual server are never removed (at least so far, this might change in the future. Most likely we will do a freeze when moving to 2.0-only support in ConanCenter, and that will drop old cci.xxx versions of gtest)
Hello @memsharded , thanks for your replies on this topic 😄 .
I'm currently adding a version upgrade check for my Conan dependencies using
conan graph outdated conanfile.py / conan graph outdated --requires 'gtest/1.14.0'. Here always the cci.20210126 version is suggested as upgrade.
After discovering this bug also added suggested version range exclusion. However that excluision is ignored for the outdated check. Seems like it just checks package name and prints what it finds ordered by semver the most recent.
-> I understand that the upgrade check won't work if it considers the normal version range ("1.14.0") as that always results in the same version again. Is there any way to tell the outdated check to consider a version range which is (not) considered for upgrade? At the end Conan users would want to know when 1.14.1 / 1.15.0 is available to upgrade via Conan.
Removing the cci versions might be one approach but I think Conan needs some way to flag some versions so they are not considered for calculated version ranges (and only get downloaded if somebody specifies that version explicitly). gtest might be a popular case but this issue can just as well happen at any other package.
Hi @gsantner
Thanks for reporting this. It is true, the issue is that it is impossible to know the right time order when mixing regular semver-like versions and cci.XXX versions.
There are several aspects impacted by this:
- Regular resolution of version ranges. This works well when
cciversions are more modern than the semver ones, probably the most common scenario that happens when some repo stops creating tagged releases. But if there arecciversions and a repo starts doing tagged releases and using semver versions for Conan packages, version ranges will default tocci. This can be excluded with the range above, so this is a viable solution. - The
conan graph outdatedcommand. This cannot be solved with the version range, because the range is used to resolve the version, but retrieving the latest cannot be limited by the range, because it is not generally true. But maybe this one could be improved to at least provide information about this, and give both the cci and the semver alternatives as a result.
I'll check if it is possible to improve the conan graph outdated output.
To clarify, the issue wouldn't be solved with something like:
conan graph outdated --requires="somepkg/[>1 <cci]"
affecting the output of the command, because even if we applied that filter for somepkg itself, it could have transitive dependencies, and those dependencies could have both semver and cci versions, and that would still potentially report the wrong version.
Thanks, yes what you said is also what I meant to say albeit I wrote loads of text 😄 .
Is there any way to tell the outdated check to consider a version range which is (not) considered for upgrade?
Maybe a additional optional (default=None) parameter for the requires(), test_requires(), build_requires() and tool_requires() (https://docs.conan.io/2/reference/conanfile/methods/build_requirements.html) functions is a possibilty to put such restrictions
I have checked this a bit.
It is extremely complicated that Conan would be able to improve this, because it is an intrinsic limitation of the versioning approach, the defined cci versions in ConanCenter are not ordered when mixed with semver versions, this is something that cannot be easily overcome.
I am talking with the team to at least have a solution for the future, which could be outlined as:
- ConanCenter new
cciversions have to be ordered with semver - That means starting with
0.0.0.cci.DATEor something similar when cci is the first version - When there are existing previous versions like
1.2, then continue with1.2.cci.DATEto leave space for future versions
Maybe a additional flag for the requires(), test_requires(), build_requires() and tool_requires()
I am afraid this is not possible. The recipe is not even read for these cases, only the current version and the versions existing in the server can be taken into account. Even if the recipe could be read, it is not possible to modify recipes in the past to work retroactively, the conan graph outdated can resolve to older versions and older revisions under several conditions, like using lockfiles or explicitly pinned revisions.
The right solution to this issue is to propose a correct versioning approach, this would solve all the issues at once. It is true that it might take some time for ConanCenter to follow, and the legacy versions might be an issue as they will not be easily removed, but at least it won't happen for new cases.
Thanks, just as additional thought:
When that exclusion would see light, you can also specify i.e. gtest/1.14.0 as require, and gtest/<2.0.0 as update hint..and then you get the info that 1.15.0 is available, also when 2.1.0 would be available too by now. So it's not only possible to filter out "bad versions" by this, but also to exclude newer major versions - while still having a specific version locked (if you specify <2.0.0 directly it would upgrade without users immediate knowledge at future builds).
When that exclusion would see light, you can also specify i.e. gtest/1.14.0 as require, and gtest/<2.0.0 as update hint..and then you get the info that 1.15.0 is available,
We tried this with one of the first initial implementations of the conan graph outdated command, but it resulted in a bit too much complexity for the value. We might want to revisit this possibility again, but in our initial iterations we realized that the biggest value of this command is actually showing possible updates outside of the defined version ranges. Because checking possible updates within the ranges can be typically done with conan graph info --lockfile="" --update (making sure not to lock version), and that returns the new versions that can be used for an update. It is not as ergonomic as the conan graph outdated for information, but the updates within ranges are typically more integrated in the flow, while the thing that was really inconvenient was reporting the new versions outside of the defined ranges, and conan graph outdated focused on that use case.
The command is pretty new, we will most likely revisit it when it is more widely used and we see more repeated usage patterns and needs. At the moment it is a bit too early, as said above, it was a bit too much complexity for the value, so we will wait a bit until getting more experience and users feedback.
Thanks for the feedback!
Just dropping by to note that https://github.com/conan-io/conan/issues/14228#issuecomment-2175876313 was adopted into CCI , and new libraries will get that scheme moving forward. It's unfortunate that we can't implement this retroactively for the old scheme though
So I think this would be the conclusion:
- This is not a bug in Conan client per-se, the sorting of versions is consistent with the versioning alpha-numeric sorting
- The problem is with the
cci.xxxversions in ConanCenter, when mixed with regular versions.
As ConanCenter is now moving to a new scheme that will solve this issue and there is nothing to do on the Conan client, I am closing this issue as solved, but please open new tickets for any further question or issue. Thanks for your feedback!
@memsharded @AbrilRBS I would still consider it a bug if strongly outdated many years old versions are treated as most recent/newer than official released & tagged versions from current year.
Suggestion: To patch the sort ordering to put cci releases not conforming to new semver standard: By mapping the sorting version info prior sorting to a prefix with zero dot -> cci.20210126 -> 0.0.0cci.20210126.
This way some library from 2021 won't get in at one of the most demanded libraries like gtest is.
Suggestion: To patch the sort ordering to put cci releases not conforming to new semver standard: By mapping the sorting version info prior sorting to a prefix with zero dot -> cci.20210126 -> 0.0.0cci.20210126
The problem is that this is not correct in the very common use case of cci versions used after a non zero version has already been released, which happens often when projects stop doing releasing or versioning, but keep evolving. So mapping cci.xxx versions automatically to 0.0.0.cci would be quite breaking behavior
Is adjusting the recipes to the correct "base version" + cci postfix a option, and rebuilding those packages? Then a 2.5.0 gets preference over a older 0.9.0.cci.20180102.
But we can't remove the existing cci.xxx version from ConanCenter. That would also be breaking to users depending on them.
Suggesting year old versions security hole filled versions shouldn't be a viable upgrade / selected as default version because it's newest seen by Conan logic.
It is not Conan logic, it is ConanCenter versioning, it is different.
In practice the recommended way of using packags from ConanCener in production is using the guidelines in https://docs.conan.io/2/devops/using_conancenter.html, either using lockfiles or using your own server, which also helps to control this kind of issue.
OK sounds like a dead-end then. Meaning require either a wrapper around conan to filter out such bad stuff, or manually checking for new versions.
Suggesting years old security hole filled versions shouldn't be a viable upgrade / selected as default version because it's newest seen by Conan(/Center) logic.
There are many ways to solve this by my view, but if nothing is an option then it is like it is. Favoring newer version by addition date would have been a possibility too, given a old cci one would have been otherwise favored.
In practice the recommended way of using packags from ConanCener in production
No worry, it's not that much about what goes in production, of course should be explicit version. It is about using Conan generally. That obvious strongly outdated versions gets suggested as latest version / as update suggestion.
Re ConanCenter: https://conan.io/center/recipes/gtest, there gtest/1.15.0 is seemingly favored ""latest version"" opposed to conan client.
There are many ways to solve this by my view, but if nothing is an option then it is like it is.
I am afraid the proposed approaches are not really viable, I wish it was possible, but:
- It is really not possible to break existing users that depend on a
cci.xxxxversion because we remove it from ConanCenter? I am totally sure there are tons of users out there that would be really upset if we did that. - Adding logic in Conan client that turns every
cci.xxxversion into0.0.0.cci.versionwill also break all the cases in which thecci.xxxversion is posterior to other existingX.Y.Zversions, which happens very often.
I understand this might be inconvenient, but in SW dev things are often not perfect, and need to balance the different forces. In this case, for us, trying not to break existing users is a very high priority.
In the case of the web for conancenter, it knows that those versions are no longer maintained, and it can sort differently.
But pick then the example of range-v3: https://conan.io/center/recipes/range-v3?version=cci.20240905, and you will see the completely opposite scenario. It stopped doing versioned releases, so cci.20240905 is and should really be the latest one.
So the problem is that there are 2 completely different cases, so Conan client cannot assume in any direction, it is simply not possible to know if the cci versions are before or after the regular versions.
Would it be possible to pick what ConanCenter suggest as latest version, and it's sort order also at Conan client? At both range-v3 (CCI is the newest) and gtest (CCI is outdated) it shows the correct one.
Not only latest version seems about right, but overall the whole sort order shown in table.
Might be well that also here are special cases, but overall seems most correct to me.
I noticed i.e. https://conan.io/center/recipes/libxml2, where some bad versions are also marked and sorted down.
I am afraid that is not possible either. ConanCenter uses batch offline processing, reading all recipes versions, checking their deprecated status and other stuff, comparing the recipes to what things already exist in the ConanCenter server... it takes a long time (a few minutes) to process just 1 reference, and require connecting to different infrastructure fully internal sources, while Conan version-range resolution should be able to operate completely local (and fast), just by resolving against the Conan cache and the defined remotes (which might be completely private remotes, and actually they are in the vast majority of cases).
OK thanks for your time and replies!
Unfortunate that there are no possibilities to fix this officially.
Unfortunate that there are no possibilities to fix this officially.
We will most likely take the chance of https://blog.conan.io/2024/09/30/Conan-Center-will-stop-receiving-updates-for-Conan-1.html, to try to remove old cci.xxx versions when possible (not Conan 2 support), that might solve some issues.
In case somebody is interested on simple workaround, not even connecting to conan servers, not producing database loads on that end:
curl "https://raw.githubusercontent.com/conan-io/conan-center-index/refs/heads/master/recipes/range-v3/config.yml" | grep '^\s*"' | cut -d'"' -f2 | head -n1 (or having a mirror of the repo).
Yields 1.15.0 correctly for gtest, range-v3 also yields the cci version. Tried also with sort, but due unwritten rule that in PRs the really latest version is added at top of the file found it not needed. (Beside cci versions being dropped from the list from time to time).
This works directly against the current list of built versions by Conan CI, ignoring all of those oudated/unmaintained versions that have been removed from the list.