conan icon indicating copy to clipboard operation
conan copied to clipboard

[bug] Conan tilde and caret range expressions don't work correctly with alphanumeric

Open RochaStratovan opened this issue 1 year ago • 8 comments

Environment details

  • Operating System+version: Windows 11 Pro N
  • Compiler+version: n/a
  • Conan version: 2.0.17
  • Python version: 3.12.1

Steps to reproduce

Conan tilde and caret range expressions don't work correctly with alphanumeric

2.0 Documentation Reference for Range expressions

The documentation for the tilde is

The tilde ~ operator can be used to define an “approximately” equal version range. requires = "pkg/[~1]" will include versions 1.3 and 1.8.1, but will exclude versions like 0.8 or 2.0. Likewise requires = "pkg/[~2.5]" will include 2.5.0 and 2.5.3, but exclude 2.1, 2.7, 2.8.

Which to summarize means ~<value> locks in and allows variation after value.

~1 translates to 1.* allowing 1.1.1, 1,3, etc. Where 1 is the locked value

Likewise, ~2.5 locks in the 2.5 prefix, allowing 2.5.0, 2.5.1, 2.5.1.9.3, etc.

This doesn't seem to work when using alpha-numeric characters. For example if we applied the rules identified above for ~2.2.0.branch-a then the expectation is 2.2.0.branch-a is locked in place and we would allow variability after that such as 2.2.0.branch-a.0, 2.2.0.branch-a.1.0, 2.2.0.branch-a.3.4.99, etc.

However, I found that this isn't working, as explained below.

Adjusting the example below for the caret (^) requires fails in the same way.

Consumer

I've adapted the excellent version examples from the 2.0 Versioning Tutorial, to play with and discover this. My consumer, lib2 depends upon two other libraries lib1a and lib1.

conanfile.py:

from conan import ConanFile

class Lib2Recipe(ConanFile):
    name = "lib2"
    requires = ["lib1a/[~2.2.0.branch-a,include_prerelease]",
                "lib1/[~1]"]

My goal for the above is to use the latest binary from the 2.2.0.branch-a versioning. I've included include_prerelease because I found it won't resolve without it.


Provider lib1a

I've generated several lib1a versions to investigate this.

$ conan list lib1a
Local Cache
  lib1a
    lib1a/2.0.0
    lib1a/2.1.0
    lib1a/2.1.1
    lib1a/2.1.2
    lib1a/2.2.0
    lib1a/2.2.0.branch-a.0     <<<<<
    lib1a/2.2.0.branch-a.0.1   <<<<<
    lib1a/2.2.0.branch-a.1     <<<<<
    lib1a/2.2.0.branch-a.2     <<<<<
    lib1a/2.2.0.branch-b.0
    lib1a/2.2.0.branch-b.1
    lib1a/2.2.0.branch-b.2

Expectation

Based on the above, I expect that lib2 would use lib1a/2.2.0.branch-a.2. I expect this based on the documentation that explains the tilde usage.


Reality

lib2 is actually using lib1a/2.2.0.branch-b.2 as illustrated in the following output.

$ conan install lib2

======== Input profiles ========
Profile host:
[settings]
arch=x86_64
build_type=Release
compiler=msvc
compiler.cppstd=14
compiler.runtime=dynamic
compiler.runtime_type=Release
compiler.version=193
os=Windows

Profile build:
[settings]
arch=x86_64
build_type=Release
compiler=msvc
compiler.cppstd=14
compiler.runtime=dynamic
compiler.runtime_type=Release
compiler.version=193
os=Windows


======== Computing dependency graph ========
Graph root
    conanfile.py (lib2/None): C:\Users\rocha\Desktop\TEST-CONAN\GRAPH\lib2\conanfile.py
Requirements
    lib1/1.2.0#eb9b91e4d2992a84e0d410ae5b8be4b9 - Cache
>>> lib1a/2.2.0.branch-b.2#eb1249058251aa8775aa32737bf08e96 - Cache <<<
Resolved version ranges
    lib1/[~1]: lib1/1.2.0
>>> lib1a/[~2.2.0.branch-a,include_prerelease]: lib1a/2.2.0.branch-b.2 <<<

======== Computing necessary packages ========
Requirements
    lib1/1.2.0#eb9b91e4d2992a84e0d410ae5b8be4b9:da39a3ee5e6b4b0d3255bfef95601890afd80709#0ba8627bd47edc3a501e8f0eb9a79e5e - Cache
>>> lib1a/2.2.0.branch-b.2#eb1249058251aa8775aa32737bf08e96:da39a3ee5e6b4b0d3255bfef95601890afd80709#0ba8627bd47edc3a501e8f0eb9a79e5e - Cache <<<

======== Installing packages ========
lib1/1.2.0: Already installed! (1 of 2)
lib1a/2.2.0.branch-b.2: Already installed! (2 of 2) <<<

======== Finalizing install (deploy, generators) ========
conanfile.py (lib2/None): Generating aggregated env files
conanfile.py (lib2/None): Generated aggregated env files: ['conanbuild.bat', 'conanrun.sh']
Install finished successfully

Logs

No response

RochaStratovan avatar Feb 09 '24 20:02 RochaStratovan

Hi @RochaStratovan

Thanks for your report. I have been having a look, and this is what I see:

  • ~2.2.0.branch-a is using the pre-release -a. The moment a pre-release is added, the expansion of the tilde is stopped. In other words, the tilde doesn't apply to the pre-release part. I think this is aligned with the standard semver approach, in which the tilde applies to major.minor.patch only.
  • If we try to use ~2.2.0.branch it works as expected, accepting 2.2.0.c and excluding 2.20.0.0 and 2.3

I think the current behavior is good. if you want to stablish a range of pre-releases better do it explicitly with [>=2.2.0.branch-a <=2.2.0.branch-z] or whatever the logic over the pre-release is desired. Because pre-releases are often alphabetical, and caret and tilde fail to express many of the alphabetical cases, for example ~2.dog cannot be processed with tilde, as version cannot be incremented.

My suggestion would be to avoid both tildes and carets for versions in general. Tons of developers really doesn't understand the difference and exact meaning of both, while a explicit [>=xxxx <yyyy] is quite straightforward, explicit and every one will understand it and know when something is in the range or not without much issues.

memsharded avatar Feb 10 '24 00:02 memsharded

@memsharded,

Thank you! I did not know that the (-) started pre-release. Based on the examples written in the Semantic versioning I thought -pre was the transition tag.

Can the documentation be updated to identify the characters that stop semantic versioning? After re-reading and playing with the tool I think dash (-) and plus (+) are in this category. I'm not sure if other characters will trigger this.

Thank you for the suggestion for tilde's. The challenge with the >=/<= logic is that it's not always clear when using alpha characters.

For example, we're investigating the usage of versions with the branch name:

# branch for JIRA EN-430
1.1.0.branch_en_430

# branch for SAST improvements
1.1.0.branch_sast

I feel it's pretty clear that using ~1.1.0.branch_sast will pull in the latest version/revision for the SAST branch. Whereas, asking colleagues about what >=/<= pattern to use for the same was not as straightforward.

RochaStratovan avatar Feb 12 '24 17:02 RochaStratovan

Thank you! I did not know that the (-) started pre-release. Based on the examples written in the Semantic versioning I thought -pre was the transition tag.

Yes, the - is the trigger, things after it will be "prerelease" info, like -alpha doesn't need the "pre" to be a prerelease

Can the documentation be updated to identify the characters that stop semantic versioning? After re-reading and playing with the tool I think dash (-) and plus (+) are in this category. I'm not sure if other characters will trigger this.

In that regard the behavior is as aligned to https://semver.org/ as possible, this is why it is not that explicitly documented, as long as it doesn't deviate from standard semver, it shouldn't need much detail in our docs, but sure, we can add some more detail.

For example, we're investigating the usage of versions with the branch name: I feel it's pretty clear that using ~1.1.0.branch_sast

I'd like to ask about that explicit requires including the branch. Because in principle the most practical approach is when developers don't need to change the requires of the dependants to resolve to something specific. Specially when there are many packages requiring that package. So it might be better to provide in the dependants something general like requires = "mypkg/[>=1.1 <2.0]" and that should also accept branch identifiers, that should probably be in the form of build-metadata, lets say that the latest stable version is mypkg/1.2, and you are preparing mypkg/1.3 as next, then it is possible to do something like mypkg/1.3+mybranchname. That will fit in the range, and developers that want to test it can do something like conan remove mypkg/* -c && conan install --requires=mypkg/1.3+mybranchname && conan install <myprojectconanfile> to have all packages in the dependency graph that contain a valid range to mypkg/1.3 to naturally resolve to it, because it is in the cache already, without needing to modify any recipe at all.

(A different discussion would be how pre-releases can be used to also opt-in for other developers and CI jobs to use non official versions yet)

memsharded avatar Feb 12 '24 17:02 memsharded

This was a case of thinking I knew the standard without reading the standard. I've never used pre-release at this or previous companies, and yet I thought I knew the standard.

It's pretty clear at the end when they give the classic syntax

<valid semver> ::= <version core>
                 | <version core> "-" <pre-release>
                 | <version core> "+" <build>
                 | <version core> "-" <pre-release> "+" <build>

Thank you for the reminder!


Thank you for the insights for using the build information to help with the branching. Overall we've been pretty happy with conan's documentation, but then we hit a wall when it comes down to actually using conan for real. I haven't found documentation for "how to use conan with branches and multiple packages" , etc. We've been playing with the tool to see if it'll meet our needs, but the lack of end-to-end how to documentation has greatly slowed us down. On the plus side, its forced me to play with the tool more and learn more, and quite possible added to your aggregation as I ask multiple questions each day :).

All kidding aside, a challenge I see with your suggestion is based on the following mock up

  lib1a
    lib1a/2.2.0
    lib1a/2.2.0+branch_en_305
    lib1a/2.2.0+branch_ps3_2044
    lib1a/2.2.0+branch_sb_1999
    lib1a/2.2.1
    lib1a/2.2.2
    lib1a/2.2.3

We're starting with 2.2.0 and planning for release 2.3.0 although each commit is a potentially deployable unit based on time and need.

Three projects know they're going to take a bit of time. These projects are managed by JIRA EN-305, PS3-2044 and SB-1999. The developers have branched from 2.2.0

Meanwhile, other changes have been completed and are ready to ship, brining our 2.2 baseline up to 2.2.3. The feature branches are behind, and will be synced with [email protected] eventually.

If I used requires = ["mypkg/[>=2.2.0 <2.3]"] in combination with pre-release this will pull in 2.2.3. Which is not what the devs working on each of their respective feature branches wants.

Granted, this challenge may be due to misunderstandings about how to use conan or the "conan way."

RochaStratovan avatar Feb 12 '24 18:02 RochaStratovan

Thank you for the insights for using the build information to help with the branching. Overall we've been pretty happy with conan's documentation, but then we hit a wall when it comes down to actually using conan for real. I haven't found documentation for "how to use conan with branches and multiple packages" , etc. We've been playing with the tool to see if it'll meet our needs, but the lack of end-to-end how to documentation has greatly slowed us down. On the plus side, its forced me to play with the tool more and learn more, and quite possible added to your aggregation as I ask multiple questions each day :).

Yes, we are aware of this. We started this journey with the "Devops guide" in https://docs.conan.io/2/devops.html, but there are a bunch of important sections there, specially those focused on CI. Unfortunately, we have been too busy we couldn't get time to do it yet. But it is definitely planned, don't hesitate to keep asking as many questions as you need 🙂

Meanwhile, other changes have been completed and are ready to ship, brining our 2.2 baseline up to 2.2.3. The feature branches are behind, and will be synced with [email protected] eventually.

I see your point. One of the challenges of binaries branch-merge model is that it is not that evolved compared with Git model, and it faces the major challenge that binaries cannot be merged, so it basically reduces the options to something similar to "rebase". That, in binary-space could mean that the branch creating lib1a/2.2.0+branch_en_305 is branched from the 2.2.0 git source branch mostly, and it is tested with PRs to the 2.2.0 release branch, more or less. If developers rebase on the 2.2.2 or 2.2.3, probably that should create binaries lib1a/2.2.3+branch_en_305, isn't it?

If I used requires = ["mypkg/[>=2.2.0 <2.3]"] in combination with pre-release this will pull in 2.2.3. Which is not what the devs working on each of their respective feature branches wants.

That is an important point, not always! For example:

  • If lib1a/2.2.0+branch_en_305 is the only lib1a version that is in the Conan cache, and you don't use --update, then it will be resolved as the solution in the range. Not necessary to use lockfiles, not necessary to change conanfile requires or anything like that. Regular conan install of any package that depends directly on indirectly on a range that contains it will be resolved to it.
  • If multiple versions of lib1a are in the cache, applying a lockfile to conan install will also force to use the specific version that you want, also without needing to change any conanfile at all.

In general, when there is concurrent development of features in source branches that branch and merge, there is needed some provision for concurrency over binaries. There are several possible strategies:

  • Doing changes in recipes to force the usage of certain specific versions of dependencies. Not very practical
  • Using different server repositories, lets say that you could create a new server repo for each branch. Then you can safely put and resolve binaries against that server repo, and it will resolve to the specific versions that you want and you put in that repo
  • Using lockfiles, that allows to work with given sets of dependencies versions, so even new versions come up and are made available in the server repos, it is still possible to use the desired locked subset of dependencies.

This is not necessarily contradicting the above, you could be resolving against lib1a/2.2.0+branch_en_305 using a lockfile because you are still in the 2.2.0 base branch, and then you rebase, you start doing lib1a/2.2.3+branch_en_305, your lockfile updated to lock that version and start working against that version while the lockfile protects you against possible liba1/2.2.4 that is made available concurrently

memsharded avatar Feb 12 '24 19:02 memsharded

What is the recommanded way for branch versions? conan-io/docs#3652

Thank you for this reference. I excitedly read through this. However, it appears that the suggested solution of using build metadata (i.e. +build.en_305, etc.) has the same restrictions/issues that I mentioned as a problem for the mock up I mentioned in my previous comment when using say pre-release.

It doesn't work with the filter ~2.2.0+build.en_305. For example with

  lib1a
    lib1a/2.0.0
    lib1a/2.1.0
    lib1a/2.1.1
    lib1a/2.1.2
    lib1a/2.2.0
    lib1a/2.2.0+build.en_305
    lib1a/2.2.0+build.en_305.1
    lib1a/2.2.0+build.en_305.2
    lib1a/2.2.0+build.sb_2099.1
    lib1a/2.2.0+build.sb_2099.2
    lib1a/2.2.0+build.sb_2099.3
    lib1a/2.3.0

The filter ~2.2.0+build.en_305 is desired to return 2.2.0+build.en_305.2 but it returns 2.2.0+build.sb_2099.3

If two feature branches are created from the same point, 2.2.0 then it doesn't work.


Binary Branch-Merge Model

I understand this complexity. This complexity is why we choose not to use a pre-release/build-metadata for this. We're don't require that the developers for branch_en_305 immediately rebase onto latest 2.2.2 or 2.2.3 as soon as they become available.

If we used the pre-release model, then their work would become blocked or slowed as they have to continually rebase as the new versions are pushed to the remotes. Which could be on a daily basis!


Alternative Methods

Thank you for sharing these alternative methods!

Before I dig too much into what you shared, I feel should explain that in our environment, most of the devs will not use conan commands directly. Maybe 20% of our devs, the power-users, will but the bulk of them prefer to focus on creating and designing code and greatly dislike having to wrangle with the devops tools like CMake, GitLab, etc. These are NOT slackers, they are very knowledgeable developers, devops tooling is just not where their skills or interest resides.

Consequently, part of our interactions with devops tools, is a need to templatize or streamline them as easy as possible to integrate the tools into the existing command sequences the devs are accustomed tool.

This is of importance because I suspect that in our work, the users will nearly always work with --update enabled and pulling from our local repository, as this would be embedded in the current scripts they use for their development cycle.

As an aside, our Dev's won't work directly with the ConanCenter repository. We may pull in libraries from ConanCenter to our local repository as mentioned in some of your documentation, but it won't be possible as a standard action.

Having said that, I'm interested in these variations that you mention. As I learn more I can potentially adapt these into the development patterns our devs are accustomed to.

  • Doing changes in recipes to force the usage of certain specific versions of dependencies. Not very practical

I understand this method, and I agree for large scenarios it can be challenging. Our dependency depth is typically 3-4 deep at most. We're not a full stack application, we are more on the OS / pure application side of things. With the power of conanfile.py's python interactions and the tips from the examples, we understand we could create a pure text version file that's read by the recipes. Combining this with lockfile abilities, this seems like a straightforward way to do it. I think it's a method that fairly easy to explain.

  • Using different server repositories, lets say that you could create a new server repo for each branch. Then you can safely put and resolve binaries against that server repo, and it will resolve to the specific versions that you want and you put in that repo

Can you refer to documentation that explains how to do this? I've seen this mentioned a few times in different locations but haven't found a clear explanation on this. I admit I haven't actively searched for this yet either. It's on my long list of conan investigations. In our discussions, this scenario has been mentioned with enthusiasm.

Would this method require that all dependencies for a product be placed on this other server repository? For example suppose:

  1. EXE-A needs LIB-B, LIB-C and LIB-D

  2. We start a feature branch on EXE-A branch_SB_1999

From the little bit you've shared I assume this means EXE-A's packages are deployed to a separate server repository. What about LIB-B, LIB-C and LIB-D? Would they also need to be copied over to the server repository too?

At other companies I've developed with we did need to branch all the dependencies. However, a fellow designer is pushing to see if we can do this in an model where we can use EXE-A@branch_SB_1999 and maybe LIB-B@branch_SB_1999 while using LIB-C@dev and LIB-D@dev.

  • Using lockfiles, that allows to work with given sets of dependencies versions, so even new versions come up and are made available in the server repos, it is still possible to use the desired locked subset of dependencies.

How would we use a lockfile to use just 2.2.0+branch_en_305?

If I walk through this for an example where application ImageConverter.exe needs the library png.lib. It seems like the process would be:

  1. Pull png.lib, update the recipe to create the version 2.2.0+branch_en_305
  2. Pull ImageConverter and create a lockfile. Edit the lockfile to use [email protected]+branch_en_305.

However, as work is done on png.lib and changes are merged/committed to the feature branch, how does ImageConverter obtain these changes? Off the top of my head, I'm guessing that you're thinking of using the latest revision model?

RochaStratovan avatar Feb 13 '24 23:02 RochaStratovan

There are 2 different discussions here, one the ~ one and the other the definition of process and CI flow.

Lets try to clarify first the first one:

The filter ~2.2.0+build.en_305 is desired to return 2.2.0+build.en_305.2 but it returns 2.2.0+build.sb_2099.3

This was commented above, the ~ indeed doesn't aim to apply to build-metadata, only to the major.minor.patch part. In that regard the Conan implementation doesn't diverge much from the official semver one.

The recommendation there is to replace ~ for the explicit alternative, so:

[>=2.2.0+build.en.305  <2.2.0+build.en.306]

will work. Note how the strategy is to convert en_305 to en.305, so we can now easily apply integer increments to make it work (not that <2.2.0+build.en_306 will not work, it will in most cases, because by chance the alphabetical order also satisfies, but it might not be the case for all cases).

If you are going for this versioning, note a couple of things:

  • The branches will resolve in alphabetical order, so +build.zz will always have precedence over +build.en, and might not be always the case. You might want to reverse, and use first a number as identifier of the branch, and the final field can be the name like +build.123.1.mybranch, so all build metadata can have a better natural sorting compared to arbitrary branch names
  • You can name it +branch explicitly, or just drop the name, directly +123.1.mybranch also works, and save the +build part

Finally, something to be considered together with the global CI flow: when to use pre-releases and when to use build metadata. Why a branch will generate build metadata and not a pre-release? Pre-releases have some nice advantages:

  • By default they are opt-in, they are not resolved by regular version ranges. So they can be put even in the same server repository and they won't be used by default by other packages.
  • Users can activate their usage via a conf and decide to opt-in for those pre-releases

memsharded avatar Feb 14 '24 18:02 memsharded

@memsharded

Thank you for your continued patience and responses. Running tests and investigations based on your feedback helps me learn more and more about all of this.

This is a summary of what I think you've said.

  1. Tilde (~) only works with semantic versioning, meaning major.minor.patch as defined in the SemVar 2.0 syntax. It does not work with pre-release or build elements. Pre-release and build elements start at the first - or +. Moreover, tilde (~) logic does not extend beyond the three identifiers in semantic versioning.

    Examples of pre release and build version
    # pre-release
    1.2.3-candidate.1
         ^^^^^^^^^^^^
    
    # build
    1.2.3+2024.02.15
         ^^^^^^^^^^^
    
    # pre-release with build
    1.2.3-candidate.1+2024.02.15
         ^^^^^^^^^^^^^^^^^^^^^^^
    
    Example of tilde notation with versions

    Available versions

    $ conan list "lib1a/4*"
    Local Cache
      lib1a
        lib1a/4.4.3
        lib1a/4.4.4.en.305
        lib1a/4.4.4.en.305.1
        lib1a/4.4.4.en.305.2
        lib1a/4.4.4.en.305.3
        lib1a/4.4.4.en.305.4
        lib1a/4.4.4.en.306
        lib1a/4.4.4.en.306.1
        lib1a/4.4.4.en.306.2
        lib1a/4.4.4.en.306.3
        lib1a/4.4.4.en.306.4
        lib1a/4.4.5
    
    Pattern Results
    ~4 4.4.5
    ~4.4 4.4.5
    ~4.4.3 4.4.5
    ~4.4.4 4.4.5
    ~4.4.4.en.305 4.4.5

    @memsharded , after doing this example, I see why you say it's best not to use tilde versions. Based on my investigation it really only locks in the major and/or minor identifiers.

  2. Try to keep numeric and alpha identifiers separate. It makes comparison logic easier. For example 1.2.3.en.499 instead of 1.2.3.en_499.

    When doing comparisons such as [>=1.2.3.en.499 <1.2.3.en.500] the comparison is purely with the last identifier, makes it numeric,

    Whereas comparison such as [>=1.2.3.en_499 <1.2.3.en_500] triggers an alphabetic comparison between en_499 and en_500.

    Examples The following versions are printed in precedence order
    lib1a/9.9.9.en_1
    lib1a/9.9.9.en_10
    lib1a/9.9.9.en_100
    lib1a/9.9.9.en_2
    lib1a/9.9.9.en_3
    

    vs making the numeric element part of the dot notation. Once again these are printed in precedence order.

    lib1a/8.8.8.en.1
    lib1a/8.8.8.en.2
    lib1a/8.8.8.en.3
    lib1a/8.8.8.en.10
    lib1a/8.8.8.en.100
    
    Example of conan's comparison logic

    Available versions

    $ conan list "lib1a/4*"
    Local Cache
      lib1a
        lib1a/4.4.3
        lib1a/4.4.4.en.305
        lib1a/4.4.4.en.305.1
        lib1a/4.4.4.en.305.2
        lib1a/4.4.4.en.305.3
        lib1a/4.4.4.en.305.4
        lib1a/4.4.4.en.306
        lib1a/4.4.4.en.306.1
        lib1a/4.4.4.en.306.2
        lib1a/4.4.4.en.306.3
        lib1a/4.4.4.en.306.4
        lib1a/4.4.5
    
    Pattern Results
    >=4.4.3 <4.4.4 4.4.3
    >=4.4.4 <4.4.5 4.4.4.en.306.4
    >=4.4.4.en.305 <4.4.4.en.306 4.4.4.en.305.4
    >=4.4.4.en.306 <4.4.4.en.307 4.4.4.en.306.4

    The last pattern illustrates that the comparison works even if 4.4.4.en.307 does not exist.

  3. You recommend using build elements for branch information combined with version ranches such as >=2.2.0+build.en.305 <2.2.0+build.en.306 (also note that alpha and numeric identifiers are not combined)

    I tried this and it doesn't work. This is shown in the examples below. Moreover it seems like there's a scenario that is a bug because the pattern that was returned was, in my opinion, wrong.

    Note: this same scenario works fine when replacing the + with . as illustrated in the previous example (i.e. not using build semantics).

    Example output and illustration of potential defect

    Available versions

    $ conan list "lib1a/2.2.0*"
    Local Cache
      lib1a
        lib1a/2.2.0
        lib1a/2.2.0+build.en.305
        lib1a/2.2.0+build.en.305.1
        lib1a/2.2.0+build.en.305.2
        lib1a/2.2.0+build.sb.2099.1
        lib1a/2.2.0+build.sb.2099.2
        lib1a/2.2.0+build.sb.2099.3
        lib1a/2.2.0.1
        lib1a/2.2.0.2
    
    Pattern Results
    >=2.2.0+build.en.305 <2.2.0+build.en.306 Can not be resolved

    However if I add 2.2.0+build.en.306 to update the available versions it no longer fails with cannot be resolved. Instead it returns the wrong version.

    $ conan list "lib1a/2.2.0*"
    Local Cache
      lib1a
        lib1a/2.2.0
        lib1a/2.2.0+build.en.305
        lib1a/2.2.0+build.en.305.1
        lib1a/2.2.0+build.en.305.2
        lib1a/2.2.0+build.en.306     <<<<<<<<<<<<<
        lib1a/2.2.0+build.sb.2099.1
        lib1a/2.2.0+build.sb.2099.2
        lib1a/2.2.0+build.sb.2099.3
        lib1a/2.2.0.1
        lib1a/2.2.0.2
    
    Pattern Results
    >=2.2.0+build.en.305 <2.2.0+build.en.306 lib1a/2.2.0+build.en.306

    This is unexpected. I said less than ...build.en.306 and yet it returned ...build.en.306

RochaStratovan avatar Feb 15 '24 19:02 RochaStratovan

The build element scenario listed above may be related to https://github.com/conan-io/conan/issues/15650

RochaStratovan avatar Feb 27 '24 20:02 RochaStratovan

Hi @RochaStratovan just dropping by to confirm that your reported issue was in fact similar to the one you linked. We fixed it in Conan 2.2.0, and I have just added your failing test to our test suite, thanks a lot for taking the time to investigate it :)

AbrilRBS avatar Jun 27 '24 13:06 AbrilRBS