From a6e9bd3d4ccf5858ad160160d457fddfd2ffbc3f Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Sat, 10 Oct 2026 20:34:59 +0300 Subject: [PATCH] chore: add just test-integrations to run every integration against the checkout --- docs/agents/release.md | 5 +++++ justfile | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/docs/agents/release.md b/docs/agents/release.md index 564cdd73..cc9ee16f 100644 --- a/docs/agents/release.md +++ b/docs/agents/release.md @@ -10,6 +10,11 @@ via `uv version`; no `pyproject.toml` bump) to PyPI, then creates the GitHub Rel so a failed publish creates no Release. Pre-releases use the PEP 440 form (`2.0.0rc1`, not `2.0.0-alpha.5`). PyPI is irreversible; there is no CI gate (a tag is the commitment point). +Before tagging, run `just test-integrations` on that `main`. It runs every integration's own tests +and `ty check` against the checkout, so a change that breaks an integration shows up before PyPI +has it. CI does not run it. A failure there either goes into the release notes as a breaking +change or gets fixed in the integration first. + The Release body is GitHub's generated notes, built from the squashed PR titles since the previous tag. A conventional-commit PR title is therefore the changelog entry a reader gets, and that is where the care goes. A release wanting prose gets it after the fact with diff --git a/justfile b/justfile index 4e6e9cd4..146cecbd 100644 --- a/justfile +++ b/justfile @@ -60,6 +60,36 @@ test-docs-integrations *args: --editable . pytest pytest-asyncio sybil {{ docs_integration_extras }} $packages "$dir/venv/bin/python" -m pytest docs/integrations --docs-integrations {{ args }} +# Run each integration's own test suite and ty check against this checkout: clone its main, run its +# `just install`, then swap in this modern-di. Defaults to every page under docs/integrations/; +# pass page names (`just test-integrations grpc flask`) to pick some. Run before tagging a release. +test-integrations *names: + #!/usr/bin/env sh + set -u + root="$PWD" + dir="$(mktemp -d)" + trap 'rm -rf "$dir"' EXIT + echo "modern-di @ file://$root" > "$dir/overrides.txt" + names="{{ names }}" + [ -n "$names" ] || names="$(ls docs/integrations/*.md | sed -e 's#.*/##' -e 's#[.]md$##' | grep -vx writing-integrations)" + failed="" + for name in $names; do + repo="modern-di-$name" + log="$dir/$repo.log" + if git clone --quiet --depth 1 "https://github.com/modern-python/$repo.git" "$dir/$repo" >"$log" 2>&1 \ + && (cd "$dir/$repo" && just install \ + && uv pip install --python .venv --overrides "$dir/overrides.txt" --editable "$root" \ + && uv run --no-sync pytest -p no:cacheprovider \ + && uv run --no-sync ty check) >>"$log" 2>&1; then + echo "ok $repo" + else + echo "FAIL $repo" + tail -n 30 "$log" | sed 's#^# #' + failed="$failed $repo" + fi + done + [ -z "$failed" ] || { echo "failed:$failed"; exit 1; } + # The gated full run: 100% line and branch coverage of modern_di required. CI runs this. test-ci: uv run --no-sync pytest --cov --cov-report term-missing --cov-report xml