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

[question] How to update a reference in a lockfile? #16636

Open
1 task done
maksim-petukhov opened this issue Jul 9, 2024 · 12 comments · May be fixed by #17577
Open
1 task done

[question] How to update a reference in a lockfile? #16636

maksim-petukhov opened this issue Jul 9, 2024 · 12 comments · May be fixed by #17577

Comments

@maksim-petukhov
Copy link

maksim-petukhov commented Jul 9, 2024

What is your question?

Hi. I started to use lockfiles and I have my libraries locked inside conan.lock (I used conan install ... -lockfile-out=conan.lock to create it and didn't edit it or used conan lock ... commands on it). Among them - qt/5.15.10#3c0bbf763b778e7b7fc6663eea043447 which I want to update. I've added some patches, built the package and now I have a new revision of it (qt/5.15.10#64e483ec8cfebb74e03da891c848e5a4) in our Artifactory. I also have a new requirement in my conanfile which I want to lock (let's say cpython). What I've tried so far:

  1. conan install . --profile:host ... --profile:build ... -o=&:my_option=my_value --lockfile-partial --lockfile-out=conan.lock --update returns ERROR: Requirement 'cpython/...' not in lockfile. But the documentation clearly states --lockfile-partial Do not raise an error if some dependency is not found in lockfile. Why do I have an error then?

  2. On the other hand this doesn't return an error (I moved --lockfile-partial to the beginning) and it adds cpython to the lockfile, though it doesn't update a reference of a qt in a lockfile:
    conan install . --lockfile-partial --profile:host ... --profile:build ... -o=&:my_option=my_value --lockfile-out=conan.lock --update. Again, according documentation --update Will install newer versions and/or revisions in the local cache for the given reference, or all in case no argument is supplied. and I believe that's what I want.

    In the logs I have:

     ```
     ======== Computing dependency graph ========
     Graph root
         conanfile.py: some\path\to\conanfile.py
     Requirements
         qt/5.15.10#3c0bbf763b778e7b7fc6663eea043447 - Cache
     ...
     ======== Computing necessary packages ========
     Requirements
        qt/5.15.10#3c0bbf763b778e7b7fc6663eea043447:fa0e758b93c42da18a2a0ee6f099fb6c0047624d#4e0a88d78229da2fd9a3835c25388f79 - Cache
     ```
    
  3. If I specify that I want to update qt it also doesn't update a reference of a qt in a lockfile: conan install . --lockfile-partial --profile:host ... --profile:build ... -o=&:my_option=my_value --lockfile-out=conan.lock --update=qt.

    Same logs.

So, how do I update the reference of qt in the lockfile to the latest available in the remote revision of qt?

conan 2.5.0

Have you read the CONTRIBUTING guide?

  • I've read the CONTRIBUTING guide
@AbrilRBS
Copy link
Member

AbrilRBS commented Jul 9, 2024

Have you seen conan lock update? It's available from Conan 2.5.0, and is meant to solve cases like this where it's a bit confusing as to how to update a specific reference :)

@maksim-petukhov
Copy link
Author

Have you seen conan lock update? It's available from Conan 2.5.0, and is meant to solve cases like this where it's a bit confusing as to how to update a specific reference :)

I've seen it. From the docs The command will replace existing locked references that matches the same package name with the provided argument values. I do not want to provide anything by hand. I want conan to get latest revision of qt from a remote (in my case it is 64e483ec8cfebb74e03da891c848e5a4), to put it cache and then update the lockfile with the new reference

@maksim-petukhov
Copy link
Author

@memsharded could you please comment on this issue?

@memsharded
Copy link
Member

I've seen it. From the docs The command will replace existing locked references that matches the same package name with the provided argument values. I do not want to provide anything by hand. I want conan to get latest revision of qt from a remote (in my case it is 64e483ec8cfebb74e03da891c848e5a4), to put it cache and then update the lockfile with the new reference

The lockfiles are actually locking things, this is its main purpose. Trying to have both packages locked and updated are contradictory goals.

If you want to get some specific package version "unlocked", then you can remove it from the lockfile with conan lock remove. Then, the next conan lock create will resolve to the latest one, or if using other command like conan install, then you can provide --lockfile-partial argument to let it resolve even if it is not in the lockfile.

@memsharded
Copy link
Member

Any further question here @maksim-petukhov?

@s-geiger-si
Copy link

I am a bit confused after reading this issue. I was expecting that the purpose of conan lock update was so that I can say `take dependency X and update the lock file it to a new version while keeping transitive dependencies consistent" and conan goes and computes a new partical dependency graph taking only that version into account (finding the correct revision if the version is ambiguous) and then produces a new lock file with minimal changes to other packages.

Is that not how it works?

So if I already have a lock file created and I want to make a minimal update to the lock file to bump a single package to a new version (without specifying the exact revision) how would I do that?

@memsharded
Copy link
Member

Hi @s-geiger-si

Is that not how it works?

No, conan lock update is basically a conan lock remove + conan lock add. No computation of the graph is done at all, just simple manipulation of the lockfile files.

So if I already have a lock file created and I want to make a minimal update to the lock file to bump a single package to a new version (without specifying the exact revision) how would I do that?

There are 2 alternatives:

  • You apply that lockfile at the moment you are bumping the single package into the new version, and capture the output lockfile. The process of conan create will automatically put the new version (even with its revision) into the lockfile, no need to call conan lock update. As in general it is desired to apply the lockfile anyway to the "single package" build, this might be a possibility
  • You can conan lock update to update the lockfile without revision, then any other lockfile operation like conan lock create or conan install that actually resolve the dependency graph can resolve the revision to the latest and add it to the lockfile.

@s-geiger-si
Copy link

Thanks for the clarification, it might help to document explicitly which conan lock commands only perform local lock file changes and which talk to the remote registry.

Regarding your suggestion, I am not sure how that would help me. I am usually not calling conan create in my local workspace. Instead, this happens in the CI/CD pipeline. When I run the build, install, create workflow in the pipeline I want to use the lockfile and ensure that the build is immutable. This currently works fine.

But on my local workspace I want to manage the lifecycle of the lock file without creating the package. I usually only run conan install and conan build and if that works then I push and let the pipeline do the testing, package creation and upload to the registry if everything checks out.

If I have an updated package version, what I can do is:

rm conan.lock
conan install conanfile.py --lockfile-out=conan.lock

This generates a new lock file using the latest versions in my local conan registry pulling in newer versions of the components that were just built by my CI/CD pipeline. But it has the risk that some unrelated libraries get also updated that I might not want to update that this point in time (usually 3rd party libraries like spdlog or boost).

So what I am really looking for is some command that also me to say: "Update a single package (or a list) to their respective latest versions (within the version range specified in the conanfile.py), make transitive changes if its needed to satisfy any dependencies and leave all other package versions constant."

Is this an uncommon workflow?

@memsharded
Copy link
Member

Maybe what you are looking for is the conan lock remove to unlock whatever dependencies you want, followed by a conan install or conan lock create command with the --lockfile-partial argument, that allows to use a lockfile in a way that if some dependency is not lock, it can freely resolve it without raising an error (strict mode which is the default).

@s-geiger-si
Copy link

You are right, the following is basically what I was looking for:

conan lock remove --requires libfoo/*
conan lock remove --requires libbar/*
conan lock remove --requires libbaz/*
conan install ./conanfile.py --update --lockfile-partial --lockfile-out=conan.lock --output ./cmake-build-debug

Afterwards my three libraries libfoo, libbar and libbaz are all updated to their respective latest versions but everything else remains at the previous version. Important aspects here:

  • The --update argument here was needed otherwise conan did not resolve newer versions from the registry
  • We cannot just write --require libbaz but need to use --require libbaz/* (or specify the exact version)
  • The --lockfile-partial argument is needed otherwise there is some difficult to understand error about a required library that does not appear in the lock file.

I wonder if there could be a short-hand for this to make this scenario easier for users that are not conan experts. Something like: conan update libfoo libbar libbaz and this would unlock the specified packages and perform an installation of newer versions with the remaining partial lock file using the --update argument and which generates a new lock file in place.

@memsharded
Copy link
Member

I think you can do them in one line:

conan lock remove --requires libfoo/* --requires=libbar/* ...

The --update argument here was needed otherwise conan did not resolve newer versions from the registry

Yes, indeed. By default Conan resolves from the Conan cache for performance reasons. It will only check for latest in the servers with --update, good point.

We cannot just write --require libbaz but need to use --require libbaz/* (or specify the exact version)

Also true, Conan 2 made patterns more explicit everywhere.

The --lockfile-partial argument is needed otherwise there is some difficult to understand error about a required library that does not appear in the lock file.

For conan lock create, this argument is implicit, it is not needed

I wonder if there could be a short-hand for this to make this scenario easier for users that are not conan experts. Something like: conan update libfoo libbar libbaz and this would unlock the specified packages and perform an installation of newer versions with the remaining partial lock file using the --update argument and which generates a new lock file in place.

The problem with that is that there are a lot of semantics and inputs missing:

  • Which lockfile (need --lockfile and --lockfile-out arguments)
  • Which configuration (profiles, settings, options, both for build and host) inputs are needed to build the graph
  • The same name of the command is not evident that it is updating a lockfile
  • It is making implicit the "root" conanfile of the project, which is always necessary. If it is not in the current folder, it can be quite confusing

This is still a relatively advanced operation, and while the proposal is easier to type, we are talking mostly about:

$ conan update libfoo libbar
# vs 
$ conan lock remove --requires libfoo/* --requires=libbar/*
$ conan lock create --update

I'll check with the team for considering something like this for inclusion to Conan, but at the moment it seems a bit too minor to be built-in.

Conan has the "custom commands" framework, so organizations can define their own command, if you want to try to implement your own conan update, that would be a good use case.

I'll check with the team for considering something like this for inclusion to Conan, but at the moment it seems a bit too minor to be built-in.

@memsharded memsharded added this to the 2.10.0 milestone Oct 29, 2024
@memsharded
Copy link
Member

I have discussed with the team, we would like to explore this idea a bit further.

As I see it, there could be 2 different approaches:

  • conan lock upgrade. It receives same arguments as conan install, <path/to/conanfile> or --requires=xxx/version plus all profile, settings, options, arguments, and --lockfile arguments defaulted to conan.lock. Then it needs some argument such as --update-requires=zlib/* to indicate which dependencies have to be updated. I have named this command conan lock upgrade to differentiate it with the existing conan lock update that we cannot break
  • using conan install .... with a new argument such as --lockfile-update=zlib/*, or maybe extending and reusing --lockfile-partial=zlib/*. It might also work together with the --update=zlib/* argument with a boolean --lockfile-update that leverages the --update values.

There are pros and cons to both approaches:

  • The first one needs users to be aware, learn and use a new command, and understand what it does. But it is a bit more explicit about the intention, and can define --lockfile default values.
  • The second one is more natural to most users, a regular conan install, specifying by arguments the things to be "unlocked" and updated. But the intention is not that evident. It also does a full installation of the binary, so most likely need to be implemented too in the conan graph info command

@memsharded memsharded modified the milestones: 2.10.0, 2.11 Nov 28, 2024
@memsharded memsharded modified the milestones: 2.11.0, 2.12.0 Dec 18, 2024
@perseoGI perseoGI linked a pull request Jan 15, 2025 that will close this issue
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants