-
-
Notifications
You must be signed in to change notification settings - Fork 636
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
Lockfiles: check if context's requirements are compatible with the lockfile's #12610
Comments
Counterpoint to this idea: sometimes removing a dependency does change the behavior of the build. For example, Flake8 plugins. When a user removes a Flake8 plugin from For user requirements, I do think we need to use the less precise "is compatible" check. Even though it has the same risk of not handling removing dependencies, it's necessary for performance so that we don't have to compute the entire resolve's requirement strings. And there's a workaround that users can manually regenerate the lockfile, we only won't automate telling them to. So I think the takeaway is: for tool lockfiles, stick to exact matching. For user requirements, switch to compatibility checking. |
Fwiw, if tool resolves also subsetted their locks, everything would work the same and be correct in the dep remove case. |
Ah, true. Thanks John! |
For now, we should expect that the lockfile metadata is well-formed and present. This allows us to simplify some of the code. Prework for #12610. [ci skip-rust] [ci skip-build-wheels]
This ensures that callers can't mess up the determinism of the lockfile's invalidation digest. It will also make #12610 more presentable for users, when we store the requirement strings in the lockfile rather than just a hash. [ci skip-rust] [ci skip-build-wheels]
I am going to start approaching this work today. My current interpretation is that "compatible" requirements, for now, is that the context's requirement strings are a subset of the requirement strings specified in the lockfile. In the future, we may be able to parse out version strings and do the requisite set math on requirements strings (which will also help simplify our interpreter constraints work), but right now that is out of scope. I currently do not have plans to verify that the header is unmodified, but that seems like a reasonable fix too. |
Sounds good! I agree with exact matches, ideally impervious to white space differences etc As discussed in DM, tool lockfiles should continue using a hash and exact matches. |
Here's what I intend to do then:
|
What's the motivation for embedding I suspect an even simpler modeling is something like this: {
"requirements": ["foo==1.2", "bar>=1"],
"requirementes_hash": null,
"interpreter_constraints": ["==3.6.*"],
"platforms": null,
} I know you also proposed some nesting: {
"requirements": ["foo==1.2", "bar>=1"],
"requirementes_hash": null,
"env": {
"interpreter_constraints": ["==3.6.*"],
"platforms": null,
},
} |
The motivation for embedding |
That expectation comes from our code itself. If it's a tool lockfile, we need |
What do you mean? Like a schema number? Ad discussed in #12683, I think we possibly would benefit from that, but probably not necessary because of the deprecation plan to not support older schema than the prior release's schema. We can likely keep it simple and leave that off, rather than needing to add and test this new mechanism. |
I meant hashing the data in the header |
Hm, I'm not sure that is important to address right now. We already have a big warning to not change the metadata. If you do, that's at your own peril. And it's easy to fix by regenerating the lockfile. I don't think we need an extra mechanism to validate they didn't tamper with the header. |
Seems reasonable |
Did you mean to close this @chrisjrn? This hasn't been merged to main. |
No, I must have accidentally clicked a button |
…ally specified requirements (#12782) This factors out versioning capabilities into `LockfileMetadata` so that it's possible to easily change the set of validation requirements for a lockfile. V1 represents the original lockfile version (where constraints and an invalidation digest are set). V2 allows for the old behaviour, but also allows specifying the input requirements for a lockfile, and verifying that the user requirements are ~a non-strict subset of~ identical to the input requirements. We decided to replace the requirements hex digest with requirements strings to allow us to test whether the lockfile produces a _compatible_ environment rather than an _identical_ environment, which will be useful for user lockfile support when we eventually enable that. In the meantime, tool lockfiles still test for an identical environment, but the extra data in the lockfile will allow for more fine-grained error messages in a future version. The implementations of `_from_json_dict` and `is_valid_for` are a bit repetitive; I can factor out the common behaviour with a bit of work, but given we expect to delete the V1 implementation before too long. Currently this _does not_ add the `platforms` capability to the header, but now it's going to be easy enough to bump the version number if we want to add more fields. Closes #12610
Currently, we expect that the consumer of a lockfile has identical input requirements to what was used to generate the lockfile. We do this by hashing the input requirements and saving that hash in the lockfile.
This works great for tool lockfiles, where the context's requirements should always be the same as what the tool lockfile was generated with. But it does not work well with user requirements, where often the context is a subset of a bigger universe of requirements. For example, a test only uses
requests
, which is 1 of 20 requirements in the lockfile. We should not error, so long as the version ofrequests
is compatible with what was used to generate the lockfile.We sort of do this right now with constraints files:
pants/src/python/pants/backend/python/util_rules/pex_from_targets.py
Lines 246 to 251 in c2f2eb0
But this compatibility check is not robust enough. It's only checking that the
project_name
is contained in the lockfile, whereas we need to validate that the entire requirement string is compatible. In a world of multiple user lockfiles, it will be valid to have one lockfile withDjango==2
and another lockfile withDjango==3
. We need to make sure the whole requirement is compatible.--
To implement, we should probably start preserving the original input requirement strings in the Pants metadata header at lockfile generation time. We can then check that the context's set of
Requirement
objects is aset.subset()
of the lockfile'sRequirement
objects.The text was updated successfully, but these errors were encountered: