Skip to content

Add import lint workflow and lock-sync hook - #5

Open
gkennos wants to merge 8 commits into
mainfrom
lint-imports
Open

gkennos wants to merge 8 commits into
mainfrom
lint-imports

Conversation

@gkennos

@gkennos gkennos commented Aug 11, 2026 •

Copy link
Copy Markdown
Member

Closes #1.
Closes #4.
Fixes #3.

Summary

  • Add a reusable lint-imports.yml workflow for package-owned import-linter contracts
  • Document the lint-imports workflow and add it to the MkDocs workflow index
  • Add dependency-range guidance for sibling CaVa packages during repo onboarding
  • Add .githooks/pre-commit template for uv.lock refreshes when dependency lines change in pyproject.toml
  • Fix the hook dependency-name extraction so it is portable on macOS/BSD tooling and exits cleanly when a staged pyproject.toml change has no dependency-line candidates

Notes

This PR now combines the import-boundary workflow from #4 with the lock-sync hook work currently represented in #2. It does not add the earlier lowest-direct resolution input or Dependabot template approach.

Nico Loesch and others added 7 commits July 23, 2026 00:43
Adds an optional `resolution` input (default `highest`) to build-test.yml
and build-test-postgres.yml, forwarded to `uv sync --resolution`, so
consumers can add a second CI job verifying that a declared dependency
floor is actually sufficient (not just the latest resolvable version).

Adds a canonical templates/dependabot.yml scoped to the CAVA sibling packages, pre-labelled `dependencies` so opened PRs flow through the existing label-gate/release-drafter pipeline.

Not yet merged to main. Being piloted on a branch against cava-ci-test
first per the CAVA dependency-range-bump plan.
Without this, Dependabot's default versioning strategy rewrites the
manifest's lower-bound constraint to match whatever it just bumped to,
not just uv.lock -- silently collapsing every declared range down to
"whatever was last merged" and making lowest-direct floor-testing
meaningless. Confirmed via the cava-ci-test pilot (round 1 exhibited
this exact bug; round 2 verifies the fix).
- build-test-postgres.md was missing the resolution input added earlier
  to build-test-postgres.yml itself -- brings it in line with build-test.md.
- docs/index.md component table now lists templates/dependabot.yml.
- setup-new-repo.md gets a new step 4 covering when/how to widen a sibling
  dependency to a range, add Dependabot (with the required
  versioning-strategy: lockfile-only), and add the lowest-direct CI job.
  Subsequent steps renumbered 5-7.
uv sync --resolution <mode> tags the lock with that resolution mode, but
a plain `uv run <cmd>` with no --resolution flag defaults to expecting
`highest` -- it treats a lowest-direct-tagged lock as stale and silently
re-resolves everything back to highest before running the command.

Confirmed directly: after `uv sync --resolution lowest-direct` installed
ruff==0.4.0, a subsequent `uv run ruff --version` logged "Ignoring
existing lockfile due to change in resolution mode: lowest-direct vs.
highest" and ended up on a completely different ruff version.

This meant the lowest-direct job never actually tested the floor -- every
step after the initial sync silently upgraded back to highest, making it
a redundant, no-op duplicate of the regular highest job. Fixes it by
passing --resolution explicitly to the ty/ruff/pytest uv run steps too.
…ommit hook

Reassessed the compatibility-verification approach: the lowest-direct CI
job never caught a real cross-package incompatibility (only bugs in its
own scaffolding -- the versioning-strategy and --resolution propagation
issues fixed earlier), and duplicates a signal already available for free
from any regular Dependabot bump PR's normal CI run. Floor-testing matters
far more for widely-distributed public libraries than a closed internal
chain with full release control.

- build-test.yml / build-test-postgres.yml: drop the resolution input and
  all --resolution flags; install with `uv sync --frozen` instead, so CI
  tests exactly what's committed in uv.lock, no implicit re-resolution.
- Remove templates/dependabot.yml. CVE coverage now comes from the
  Dependabot security-updates repo setting alone (no dependabot.yml
  needed -- confirmed the `allow` list required for scoped version
  updates silently blocks security-update PRs for anything not listed,
  a known GitHub gotcha with no clean workaround).
- Add templates/githooks/pre-commit: keeps uv.lock in sync with
  pyproject.toml locally, before a commit is ever made. Diffs staged
  pyproject.toml for the specific dependency line(s) that changed and
  runs `uv lock --upgrade-package <name>` for just those -- confirmed
  directly this touches only the named package, never an unrelated one.
- docs: setup-new-repo.md step 4 trimmed to just the range-widening
  guidance; new step 5 documents installing the pre-commit hook;
  build-test.md/build-test-postgres.md/index.md references removed.
--frozen blindly trusts uv.lock with no validation against pyproject.toml
at all. Confirmed directly: raising a dependency floor in pyproject.toml
without updating uv.lock still passed --frozen silently (exit 0), meaning
a forgotten or bypassed pre-commit hook could leave a floor completely
untested indefinitely with no signal anywhere.

Plain uv sync is the better fit: it prefers the committed lock when still
valid (so no gratuitous bumps just because something newer shipped
upstream, confirmed separately), but re-resolves and fails loudly the
moment the lock can no longer satisfy pyproject.toml (confirmed with the
same raised-floor scenario -- "No solution found", not a silent pass).
--locked/uv lock --check were also ruled out: they fail on any staleness
at all, not just genuine inconsistency, reintroducing exactly the
forced-update-just-because-something-shipped nagging this whole design
was trying to avoid.
@gkennos
gkennos requested a review from nicoloesch August 11, 2026 02:53
@gkennos gkennos changed the title Lint imports Add import lint workflow and lock-sync hook Aug 11, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant