From fe1da5e1003f1bf2e8d36467c40803b3ae5c8e85 Mon Sep 17 00:00:00 2001 From: Byron Williams Date: Thu, 3 Sep 2026 04:42:01 -0700 Subject: [PATCH] fix(ci): restore default-branch template validation and cruft updates Two independent default-branch CI failures, both reproducible on main. 1. ruff stabilised PLR0917 (too-many-positional-arguments), which fires on three call surfaces that predate the rule. validate-template.yml installs ruff unpinned, so the new rule landed on main without a code change and broke "Validate Cookiecutter Template / validate (3.10-3.14)" plus "Test Template / Integration Tests (api-service)" and "Test Summary" on every open PR. Fixed at the source rather than suppressed: the affected helpers now take keyword-only arguments, which is ruff's documented remedy for PLR0917. - hooks/post_gen_project.py: _collect_optional_features (11 positional) and _print_developer_tool_integrations (7 positional); both call sites updated to keyword form. - generated project middleware: RateLimitMiddleware.__init__ tuning parameters (5 positional). The only in-template call site already used keyword arguments, so generated projects are unaffected. Verified locally with ruff 0.16.5 (the version CI resolved): ruff check and ruff format --check pass on hooks/, basedpyright passes on hooks/, and all seven fixture configurations generate and pass ruff check. 2. cruft-update.yml installed into the runner's system interpreter with uv pip install --system. Ubuntu 24.04 images mark that interpreter externally managed (PEP 668), so uv refuses and the scheduled job has failed daily. Both jobs now build a dedicated uv venv under RUNNER_TEMP and prepend it to PATH. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/cruft-update.yml | 20 ++++++++-- hooks/post_gen_project.py | 38 ++++++++++--------- .../middleware/security.py | 1 + 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/.github/workflows/cruft-update.yml b/.github/workflows/cruft-update.yml index 0dbbb51b..8c060973 100644 --- a/.github/workflows/cruft-update.yml +++ b/.github/workflows/cruft-update.yml @@ -53,11 +53,17 @@ jobs: enable-cache: true - name: Set up Python - run: uv python install 3.12 + # Ubuntu runner images ship an externally managed system interpreter + # (PEP 668), which uv refuses to install into. Build a dedicated venv + # and put it first on PATH so later `python` calls resolve to it. + run: | + uv python install 3.12 + uv venv --python 3.12 "${RUNNER_TEMP}/cruft-venv" + echo "${RUNNER_TEMP}/cruft-venv/bin" >> "${GITHUB_PATH}" - name: Install dependencies run: | - uv pip install --system cruft pyyaml + uv pip install --python "${RUNNER_TEMP}/cruft-venv/bin/python" cruft pyyaml - name: Configure Git run: | @@ -109,11 +115,17 @@ jobs: enable-cache: true - name: Set up Python - run: uv python install 3.12 + # Ubuntu runner images ship an externally managed system interpreter + # (PEP 668), which uv refuses to install into. Build a dedicated venv + # and put it first on PATH so later `python` calls resolve to it. + run: | + uv python install 3.12 + uv venv --python 3.12 "${RUNNER_TEMP}/cruft-venv" + echo "${RUNNER_TEMP}/cruft-venv/bin" >> "${GITHUB_PATH}" - name: Install dependencies run: | - uv pip install --system cruft pyyaml + uv pip install --python "${RUNNER_TEMP}/cruft-venv/bin/python" cruft pyyaml - name: Configure Git run: | diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index f3d35858..e0c087af 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -781,6 +781,7 @@ def setup_claude_user_settings() -> None: def _collect_optional_features( + *, include_background_jobs: str, include_frontend: str, include_docker: bool, @@ -914,6 +915,7 @@ def _print_infrastructure_integrations( def _print_developer_tool_integrations( + *, include_semantic_release: bool, include_coderabbit: bool, include_linear: bool, @@ -1005,17 +1007,17 @@ def print_success_message() -> None: print("=" * 60) optional_features = _collect_optional_features( - include_background_jobs, - include_frontend, - include_docker, - include_sentry, - include_health_checks, - include_caching, - include_load_testing, - include_semantic_release, - include_coderabbit, - include_linear, - include_supply_chain, + include_background_jobs=include_background_jobs, + include_frontend=include_frontend, + include_docker=include_docker, + include_sentry=include_sentry, + include_health_checks=include_health_checks, + include_caching=include_caching, + include_load_testing=include_load_testing, + include_semantic_release=include_semantic_release, + include_coderabbit=include_coderabbit, + include_linear=include_linear, + include_supply_chain=include_supply_chain, ) if optional_features: print("\n✨ Optional features included:") @@ -1027,13 +1029,13 @@ def print_success_message() -> None: include_docker, include_background_jobs, include_load_testing, include_sentry ) _print_developer_tool_integrations( - include_semantic_release, - include_coderabbit, - include_linear, - include_supply_chain, - include_frontend, - frontend_package_manager, - include_docker, + include_semantic_release=include_semantic_release, + include_coderabbit=include_coderabbit, + include_linear=include_linear, + include_supply_chain=include_supply_chain, + include_frontend=include_frontend, + frontend_package_manager=frontend_package_manager, + include_docker=include_docker, ) print("\n" + "=" * 60) diff --git a/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/middleware/security.py b/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/middleware/security.py index b4b5640a..f27b87b0 100644 --- a/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/middleware/security.py +++ b/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/middleware/security.py @@ -124,6 +124,7 @@ class RateLimitMiddleware(BaseHTTPMiddleware): def __init__( self, app: ASGIApp, + *, requests_per_minute: int = 60, burst_size: int = 10, max_tracked_ips: int = 10000,