Check script lockfiles in CI - #29021
AlexWaygood wants to merge 3 commits into
Conversation
Typing conformance resultsNo changes detected ✅Current numbersThe percentage of diagnostics emitted that were expected errors held steady at 98.24%. The percentage of expected errors that received a diagnostic held steady at 98.24%. The number of fully passing files held steady at 134/146. |
Memory usage reportMemory usage unchanged ✅ |
|
Okay, codex only reminded me that this PR already existed after I'd already spent a bunch of time on this. But that PR has merge conflicts, and I think the script being added here is slightly superior in several other ways too:
|
|
| COMPLETION_FIXTURES = Path("crates/ty_completion_eval/truth") | ||
|
|
||
|
|
||
| def scripts() -> Iterator[Path]: |
There was a problem hiding this comment.
Can't we use ty for this?
TY_UV=scripts UV_LOCKED=1 ty check ./scriptswhich we already have in the dogfood step
ruff/.github/workflows/ci.yaml
Lines 426 to 431 in fad83a7
There was a problem hiding this comment.
we have a bunch of scripts that are not located in the scripts/ directory, which also need to be kept up to date
There was a problem hiding this comment.
You can pass them as CLI arguments. It just feels a bit silly to have this huge script.
There was a problem hiding this comment.
meh, I don't want to have to remember to update this workflow every time we add a new script. I'd much prefer automated discovery, which is what the new script I'm adding does.
this huge script
It doesn't seem that big to me 😆
There was a problem hiding this comment.
Ideally, we'd probably move all the scripts in one places, which would simplify this. I also think we do want the dogfood step to run on all scripts, meaning you still need to update that one whenever you add a misplaced script.
There was a problem hiding this comment.
Maybe. I do think there's some sense in having scripts that really only pertain to a single crate be located in those crates. The script for generating files in the ruff_python_ast crate does in some sense belong in that crate; the mdtest runner for ty_python_semantic does feel like it belongs in that crate.
Also, even if we did move all scripts inside scripts/, I still think the script I'm adding provides value, because it gives you a really easy way to update all lockfiles at once locally if this CI step fails.
There was a problem hiding this comment.
I don't mind the script for updating, but I don't think we should duplicate the dogfood step. Instead, scripts that should be checked should be added there.
| ): | ||
| continue | ||
|
|
||
| if b"# /// script" in full_path.read_bytes().splitlines(): |
There was a problem hiding this comment.
You can replace parts (most, all) of this by calling uv workspace list --scripts --preview-features workspace-list-scripts
There was a problem hiding this comment.
that silently skips scripts with invalid configuration rather than rejecting them
There was a problem hiding this comment.
This seems unfortunate. Good that ty check catches that for you :) (I guess that might not be true, it doesn't report scripts with a missing closing tag, but they're technically not scripts)
Maybe we need a much better ty project list --scripts 😆
There was a problem hiding this comment.
I updated the new script so that it runs ty on each script as it discovers them, and updated the dogfooding CI job to just use this script, and removed the new CI job that an earlier version of this PR added. It found ty errors in scripts that were not inside the scripts/ directory, so the PR now fixes those as well
| env: | ||
| # Enable experimental support for installing PEP 723 script dependencies. | ||
| TY_UV: scripts | ||
| UV_LOCKED: "true" |
There was a problem hiding this comment.
Hmm, I think this is worse. The point of dogfooding is that we dogfood it. I also find this much more difficult to understand.
There was a problem hiding this comment.
Well, I just wanted a CI check that verified that all our lockfiles were up to date, including ones that were not included in the ty-dogfooding check 😆
I can revert to the previous version where it was an entirely separate check? I don't particularly think it's important for every script in the repo to be included in the ty dogfooding check TBH. We get the vast majority of them checked in the existing dogfooding check on main, and I think that's enough.
But I really would like all scripts in the repo checked to see if their lockfiles are up to date. It's very annoying for me when crates/ty_python_semantic/mdtest.py.lock changes locally after I invoke it when working on a PR branch, because some previous PR that touched pyproject.toml should have updated that lockfile but didn't.
There was a problem hiding this comment.
My preferred solution would be:
- Keep your script to update the locks.
- I would probably just change the existing dogfooding step and add the two missing scripts. That's the easiest change
- But if you want to keep your script, I'd probably use your script to find all scripts, and pass them to
ty checkin the dogfooding step (you can write them to a@file or use echo or something like that)
There was a problem hiding this comment.
But if you want to keep your script, I'd probably use your script to find all scripts, and pass them to ty check in the dogfooding step (you can write them to a @ file or use echo or something like that)
Okay, I did that. We still need a separate check to confirm the lockfiles are up to date, though. We set UV_LOCKED: 1 in CI while doing the ty dogfooding check, but UV_LOCKED=1 doesn't imply --refresh, and there is no environment variable that you can set right now that does imply --refresh. This is one reason why I kept running into issues where scripts had stale lockfiles that would be updated as soon as I ran them locally, despite them passing the ty-dogfooding step in CI.
Check that repository PEP 723 scripts have up-to-date lockfiles in CI and dogfood ty on each script, including scripts outside
scripts/. The helper can also update the lockfiles and check the scripts locally withuv run scripts/check-scripts.py. It builds ty once unless--ty-binarysupplies an existing executable. CI passes--checkto verify lockfiles without updating them.I started with uv's equivalent check, but a few small modifications were required to make the check Ruff-compatible. After making those changes, I was unhappy with the readability of the script, so I rewrote it in Python for better readability and maintenance.
This PR also enables the
missing-exclude-newer-package-lockpreview feature, which omitsexclude-newer-packageoverrides from a script lockfile when the corresponding package is absent from that lockfile's resolution. Without that feature, changing an unrelated exemption in our global pyproject.toml file can cause every script's lockfile to be updated on its next run. The feature requires uv 0.12.10 or later, so our pyproject.toml file now enforces that minimum version of uv using thetool.uv.required-versionconfiguration setting.The broader ty check found a bug in the AST generator: if a source-order field is missing, the generator could reuse the last field or append
None. It now raises an error instead.Closes #27845.