conan-io / conan

Conan - The open-source C and C++ package manager
https://conan.io
MIT License
8.13k stars 968 forks source link

[question] Conan 2 lockfiles: How-to lock pkgid and prev? #16899

Open SzBosch opened 2 weeks ago

SzBosch commented 2 weeks ago

Dear Conan team,

earlier with Conan 1 a lockfile contained the full reference incl. pkgid and prev.

With Conan 2.0.x this information is not anymore in the lockfile by default. But you provided a parameter "--lockfile-packages" which brought back this information.

Now with newer Conan versions (tried 2.4.1 and 2.6.0) this parameter is gone from the documentation, but can be still given on the command line, but giving an (non-breaking) error, e.g.:

conan lock create --requires="mypkg/1.0.0" --lockfile-packages
ERROR: The --lockfile-packages arg is private and shouldn't be used
...

What is the correct way to get a full lockfile incl. pkgid and prev?

Have you read the CONTRIBUTING guide?

memsharded commented 2 weeks ago

Hi @SzBosch

Thanks for your question.

Lockfiles in Conan 2 do not lock the package_id and package-revisions for 2 reasons:

The --lockfile-packages was just an internal experiment to check the potential extensibility of the current model, just in case, but this has finally not been necessary.

Please let me know if this clarifies your question.

SzBosch commented 2 weeks ago

Hi @memsharded,

thank you for the quick answer.

What I basically understood now is earlier (e.g. as explained here: https://blog.conan.io/2019/09/27/package-id-modes.html) the pkgid was only calculated from settings, options and requirements. The prev was calculated from the content (files)

Now it has changed to the pkgid is calculated from settings, options, requirements AND the content (files), correct?

With which version has this exactly changed? (with 2.0.x we are still able to create multiple prevs for the same pkgid)

memsharded commented 2 weeks ago

Now it has changed to the pkgid is calculated from settings, options, requirements AND the content (files), correct?

No, the package_id is still calculated from settings, options and requirements, and the package_revision is calculated from the package contents, this is why it is possible to build more than one package revision, because unfortunately C++ builds are not always deterministic: https://blog.conan.io/2019/09/02/Deterministic-builds-with-C-C++.html

But Conan 2 assumes that the configuration is correctly defined. If the source input is the same (same recipe-revision), and the configuration is also exactly the same (same profile inputs, settings, options, conf and dependencies) producing the same package_id, the resulting binary should be the same (modulo the non-determinism). Consequently, there is no reason to re-build a package binary when there already exist a package revision for the same recipe-revision+package_id, and as a result, a correct model and process will never have more than one package revision for that same combination.

SzBosch commented 2 weeks ago

Unfortunately it seems very easy for people (and even in automated CI/CD cases) to screw up this model by specifying a version in the conanfile.py, executing "conan export-pkg" and "conan upload", then modifying a file (which is not recipe relevant), forget to change the version in the conanfile.py and execute again "conan export-pkg" and "conan upload" resulting in an additional prev for the same version, rrev and pkgid.

Is there any possibility with conan to prevent or at least detect this issue?

memsharded commented 2 weeks ago

Unfortunately it seems very easy for people (and even in automated CI/CD cases) to screw up this model by specifying a version in the conanfile.py, executing "conan export-pkg" and "conan upload", then modifying a file (which is not recipe relevant), forget to change the version in the conanfile.py and execute again "conan export-pkg" and "conan upload" resulting in an additional prev for the same version, rrev and pkgid.

The first important recommendation, as documented in https://docs.conan.io/2/knowledge/guidelines.html, is that developers shouldn't be able to upload directly to production repos. Of course they can upload to "playground"-like repos, but not to production repos.

Then, for CI, it is way more unlikely to screw it up. In the first place, they are not locally modifying files at all, not using local flow with conan export-pkg, not exporting and uploading several times. When using conan create it is as simple as specifying conan create . --build=missing and it will avoid building new prevs for already existing binaries. Also, it is not that usual that the modified files are not related to the recipe at all. It might happen that some changes are done in the README, for example, but if using revision_mode = "scm", or using the scm capture mode (https://docs.conan.io/2/examples/tools/scm/git/capture_scm/git_capture_scm.html) it will still use the commit information, which would be a different commit anyway even if the changes are not "exported" with the recipe.

So we haven't seen issues with this in practice, and basically all occurrences of this situation happened because the process was "over-building" with some --build="*" or conan create without --build=missing and without any analysis of the changes.

It is important to note that one of the reason this was dropped in Conan 2 is because even if this an "inefficiency" and users might be unnecessarily rebuilding from source and wasting resources, the resulting binaries or the new package-revisions are basically the same binaries, just with some minor differences like embedded timestamps that results in a new package-revision. So defaulting to always using the latest package-revision is actually very safe, all the previous package-revisions were actually the same binary, so no need to lock it.

Is there any possibility with conan to prevent or at least detect this issue?

Detecting these inefficiencies is relatively easy, doing a conan list pkg/version:*#* --format=json > pkg_revisions.json will result in a json file that can be checked for multiple package revisions.