Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-test-postgres.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
python-version: ${{ inputs.python-version }}

- name: Install dependencies
run: uv sync --all-extras --dev
run: uv sync --frozen --all-extras --dev

- name: Run setup commands
if: inputs.setup-commands != ''
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
python-version: ${{ inputs.python-version }}

- name: Install dependencies
run: uv sync --all-extras --dev
run: uv sync --frozen --all-extras --dev

- name: Run setup commands
if: inputs.setup-commands != ''
Expand Down
43 changes: 40 additions & 3 deletions docs/guides/setup-new-repo.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,44 @@ Copy `templates/release-drafter.yml` from this repo to `.github/release-drafter.

---

## 4. Delete old files
## 4. Dependency ranges on sibling packages (if applicable)

Skip this step if the repo has no dependency on another CAVA package (e.g. `oa-configurator`, which is a base/leaf package with no siblings of its own).

If this repo depends on one or more CAVA sibling packages, prefer a semver range over an exact pin once the sibling has itself migrated to this centralised CI/CD (its releases are label-gated, so MAJOR only happens on a `breaking`-labelled PR):

```toml
dependencies = [
"oa-configurator>=0.1.2,<1.0.0", # not =="0.1.2"
]
```

CI installs with `uv sync --frozen`, so it always tests exactly what's committed in `uv.lock` — see [Keeping `uv.lock` in sync](#keeping-uvlock-in-sync) below for how that stays consistent with `pyproject.toml`. Enable **Dependabot security updates** in the repo's settings (Advanced Security) for CVE coverage; no `dependabot.yml` file is needed for that.

---

## 5. Keeping `uv.lock` in sync

`ci.yml` installs with `uv sync --frozen`, meaning CI tests *exactly* what's committed in `uv.lock` — no implicit re-resolution, no drift-catching safety net. That makes it important that `uv.lock` actually reflects `pyproject.toml` at all times, without relying on someone remembering to run `uv lock` after every dependency edit.

Install the canonical pre-commit hook:

```bash
mkdir -p .githooks
cp <path-to-cava-devops>/templates/githooks/pre-commit .githooks/pre-commit
chmod +x .githooks/pre-commit
git config core.hooksPath .githooks
```

`git config core.hooksPath` is a one-time, per-clone setting (not committed), so each contributor needs to run it once after cloning.

What it does: when `pyproject.toml` is part of a commit, the hook diffs it to find exactly which dependency line(s) changed, then runs `uv lock --upgrade-package <name>` for just those -- not a blanket `uv lock`. This touches only the package(s) you actually edited (plus whatever *that* package's new version transitively requires), never an unrelated dependency that merely happens to have a newer release available. Confirmed directly: `uv lock --upgrade-package certifi` moved only `certifi`, leaving every other locked package untouched.

This runs locally, before the commit is created -- by the time a PR is opened, `uv.lock` is already correct, and CI's `--frozen` install just confirms it.

---

## 6. Delete old files

Remove these files if present in the repo:

Expand All @@ -161,7 +198,7 @@ Remove these files if present in the repo:

---

## 5. GitHub configuration
## 7. GitHub configuration

### Merge settings

Expand Down Expand Up @@ -225,7 +262,7 @@ This creates five labels: `breaking`, `feature`, `fix`, `dependencies` (bump lab

---

## 6. First release after cutover
## 8. First release after cutover

Merge all migration changes via a PR labelled `chore`. `merge.yml` triggers and release-drafter creates a draft. What to do next depends on whether the repo has existing tags.

Expand Down
37 changes: 37 additions & 0 deletions templates/githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
# Canonical CAVA pre-commit hook: keeps uv.lock in sync with pyproject.toml.
#
# If pyproject.toml is staged, finds the specific dependency line(s) that
# changed (added, removed, or had their version spec edited) and refreshes
# only those packages in uv.lock via `uv lock --upgrade-package`. Does not
# touch any other package -- this is a targeted sync, not a blanket
# `uv lock`, so it never pulls in an unrelated upstream release.
set -euo pipefail

if ! git diff --cached --name-only | grep -q '^pyproject\.toml$'; then
exit 0
fi

if ! command -v uv >/dev/null 2>&1; then
echo "pre-commit: uv not found on PATH, skipping uv.lock sync" >&2
exit 0
fi

changed_names=$(git diff --cached -- pyproject.toml \
| grep -E '^[+-]\s*"[A-Za-z0-9][A-Za-z0-9._-]*' \
| sed -E 's/^[+-]\s*"([A-Za-z0-9][A-Za-z0-9._-]*).*/\1/' \
| sort -u)

if [ -z "$changed_names" ]; then
exit 0
fi

upgrade_args=()
while IFS= read -r name; do
upgrade_args+=(--upgrade-package "$name")
done <<< "$changed_names"

echo "pre-commit: syncing uv.lock for changed dependencies:"
echo "$changed_names" | sed 's/^/ - /'
uv lock "${upgrade_args[@]}"
git add uv.lock