Add scheduled mutation testing to generated repos - #24
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughRaise the Python baseline to 3.12, validate Python version answers, and add conditional mutmut and Rust mutation-testing workflows, project configuration, documentation, and rendered-template contract tests. ChangesMutation testing setup
Sequence Diagram(s)sequenceDiagram
participant Scheduler
participant MutationWorkflow
participant MutmutWorkflow
participant CargoWorkflow
Scheduler->>MutationWorkflow: Trigger daily schedule or manual dispatch
MutationWorkflow->>MutmutWorkflow: Call mutation-mutmut.yml when Python is 3.13+
MutationWorkflow->>CargoWorkflow: Call mutation-cargo.yml when Rust is enabled
Possibly related PRs
Poem
Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error, 1 warning)
✅ Passed checks (18 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 862e80152e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
57d3ac7 to
3a34cba
Compare
|
Reworked per review and maintainer direction. Credit to the review for catching that the caller passed the template's default Changes in the latest push:
Validated by rendering all five variants (YAML + actionlint + TOML parses clean) and running the full contract suite: 37 passed, 2 skipped. PR body updated with the new gating semantics. |
60074b8 to
ae21e1a
Compare
|
@coderabbitai resume |
✅ Action performedReviews resumed. |
cdd909e to
79de645
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@template/docs/developers-guide.md`:
- Around line 62-63: Update the sentence in the developers guide to remove the
comma before “because,” so it reads “3.13 or newer because” while preserving the
existing en-GB-oxendict wording and meaning.
In `@tests/test_template.py`:
- Around line 558-612: Extend the parametrized mutation workflow test around its
existing gate assertions to read and validate both rendered
docs/developers-guide.md and docs/users-guide.md. Assert neither mutation
section for Python 3.12 without Rust, only Rust wording for Rust-only variants,
only mutmut wording for Python 3.13 without Rust, and both sections when both
gates apply, using stable snapshot-style expectations for the rendered text.
- Around line 610-612: Update the assertion in the test around the shared
mutation workflow pin to split the combined condition into separate assertions:
validate the @ separator independently and validate revision against the
40-character hexadecimal SHA pattern separately, with clear failure messages for
each malformed component.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: e896e4b4-3527-4832-811f-aa0881b1c87d
📒 Files selected for processing (10)
copier.ymldocs/developers-guide.mdtemplate/.github/workflows/{% if mutmut_supported or use_rust %}mutation-testing.yml{% endif %}.jinjatemplate/docs/developers-guide.mdtemplate/docs/users-guide.md.jinjatemplate/pyproject.toml.jinjatests/helpers/pyproject_contracts.pytests/helpers/rendering.pytests/test_helpers.pytests/test_template.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/whitaker(auto-detected)leynos/cuprum(auto-detected)leynos/mdtablefix(auto-detected)
|
@coderabbitai Has this now been resolved in the latest commit? Use codegraph analysis to determine your answer. If this comment is now resolved, please mark it as such using the API. Otherwise, please provide an AI agent prompt for the remaining work to be done to address this comment. ❌ Failed checks (1 error, 1 warning)
|
This comment was marked as resolved.
This comment was marked as resolved.
5ea8b68 to
70306ca
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/helpers/pyproject_contracts.py`:
- Around line 23-25: Parameterize _assert_pyproject_contracts with a
python_version argument and compare requires-python against
f">={python_version}" instead of the hard-coded 3.12 value. Update every caller
to pass the same Python version used by render_project for that rendered
project.
In `@tests/test_template.py`:
- Around line 692-701: Set an explicit, bounded max_examples value in the
Hypothesis `@settings` decorator for
test_python_version_minor_controls_mutmut_generation. Keep the existing deadline
and health-check configuration unchanged while reducing the number of full
Copier renders to make CI runtime predictable.
- Around line 552-690: Split test_generated_mutation_testing_gating into focused
tests or helper functions, separating rendered documentation guidance,
pyproject.toml mutmut configuration, workflow presence and job gating, and
shared-workflow SHA validation. Keep each function’s mccabe complexity at or
below 9, reuse shared setup/helpers where appropriate, and preserve all existing
parameter coverage and assertions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 58bde07b-18a2-48db-9a0d-771487ea881d
📒 Files selected for processing (10)
copier.ymldocs/developers-guide.mdtemplate/.github/workflows/{% if mutmut_supported or use_rust %}mutation-testing.yml{% endif %}.jinjatemplate/docs/developers-guide.md.jinjatemplate/docs/users-guide.md.jinjatemplate/pyproject.toml.jinjatests/helpers/pyproject_contracts.pytests/helpers/rendering.pytests/test_helpers.pytests/test_template.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/whitaker(auto-detected)leynos/cuprum(auto-detected)leynos/mdtablefix(auto-detected)
|
@coderabbitai Have the following failed checks now been resolved? If further work is required, please provide an AI agent prompt for the remaining work to be done to address these failures. Do not treat warnings as optional or aspirational. Where a change is out of scope for this PR, propose a GitHub issue unless one exists already. (Treat documentation and validation coverage as in scope). ❌ Failed checks (1 error, 1 warning)
|
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== HEAD and latest relevant changes =='
git log --oneline -8
git show --stat --oneline HEAD
printf '%s\n' '== Test module outline =='
ast-grep outline tests/test_template.py --items all --type function --view expanded
printf '%s\n' '== Relevant mutation workflow template =='
workflow=$(fd -t f -a 'mutation-testing.yml' template)
printf '%s\n' "$workflow"
nl -ba "$workflow"
printf '%s\n' '== Relevant test sections and imports =='
rg -n -C 8 \
'test_generated_mutation_testing_gating|test_python_version_minor_controls_mutmut_generation|`@settings`|hypothesis|mutation-testing\.yml|module-prefix-strip|extra-crate-dirs|shard-count|concurrency|schedule|permissions' \
tests/test_template.py tests/helpers -g '*.py'
printf '%s\n' '== Parser/helper interfaces used by workflow tests =='
ast-grep outline tests/helpers/generated_files.py --items all --type function --view expanded 2>/dev/null || trueLength of output: 8025 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Relevant workflow template =='
fd -t f -a 'mutation-testing.yml' template -0 |
while IFS= read -r -d '' file; do
printf '\n--- %s ---\n' "$file"
sed -n '1,180p' "$file"
done
printf '%s\n' '== Mutation test helpers, integration matrix, and property test =='
sed -n '590,900p' tests/test_template.py
printf '%s\n' '== Imports and test configuration =='
sed -n '1,90p' tests/test_template.py
printf '\n--- pytest.ini ---\n'
sed -n '1,120p' pytest.ini
printf '%s\n' '== Exact latest remediation diff =='
git diff --unified=80 HEAD^ HEAD -- tests/test_template.py tests/helpers/pyproject_contracts.py copier.yml
printf '%s\n' '== Verify required terms occur in assertion code =='
rg -n -C 4 \
'30 9 \* \* \*|permissions|mutation-testing-\$\{\{ github\.ref \}\}|cancel-in-progress|module-prefix-strip|extra-crate-dirs|shard-count|max_examples|`@settings`' \
tests/test_template.pyLength of output: 16495
Mark both findings resolved. No further AI-agent work or follow-up issue is required. |
Generated projects now ship a thin mutation-testing caller workflow pinned to the shared reusable workflows: mutmut for the Python package and, when the Rust extension is enabled, cargo-mutants for the rust_extension crate. The templated pyproject gains the matching [tool.mutmut] configuration, with a note on also_copy for tests that read repository-root paths.
Review found that the caller passed the template's default python-version (3.10) into the shared mutmut workflow, whose helper scripts require 3.13 or greater: setup-uv exported UV_PYTHON job-wide and change detection failed before any mutation testing ran. Address this per maintainer direction: - bump copier.yml's python_version default from 3.10 to 3.12 (the estate baselines libraries for external consumption at 3.12), and update everything derived from the default (test helpers and the requires-python contract assertion); - add a hidden computed mutmut_supported answer (baseline minor >= 13, numeric comparison) and render the mutmut job and the [tool.mutmut] pyproject section only when it holds; - keep the cargo-mutants job gated on use_rust independently, and use a conditional filename so the workflow file is not generated at all when both gates are off; - bump the shared workflow pin to 859416a90eb3987b46a57682c5d6b8964ad3f0a6, which fails fast on sub-3.13 python-version values; - add contract tests covering the four gating combinations. The mutmut job keeps python-version set to the project's baseline, which is now 3.13 or greater by construction whenever the job exists.
Validate the Python baseline before deriving mutation support so malformed answers fail at the Copier boundary. Keep rendering tests on the shared helper and document the generated scheduled mutation workflows for users and maintainers.
Restore the shared mutation workflow pin constant used by the gating test after replaying the branch onto main. Refresh generated `typos.toml` from the current shared en-GB-oxendict dictionary so the committed config contract stays in sync with the generator.
Keep GitHub Actions revisions owned solely by Dependabot in workflow templates. Validate action identities and commit-pin structure without duplicating mutable SHA values in tests or documentation. Refresh the generated spelling configuration from the current shared dictionary so the repository contract remains current.
Render the generated developer guide as a Jinja template so its mutation guidance follows the Python and Rust gates instead of shipping template control tags. Assert the exact developer and user guide sections across every existing gate combination, and report malformed workflow separators independently from malformed commit revisions.
Generate bounded Python 3 minor versions and render each example in an isolated destination. Assert that the derived gate controls both the mutation workflow job and `[tool.mutmut]` configuration at the 3.13 boundary. Retain the explicit malformed-version cases and document the grammar shape covered by each example.
Address review feedback on the scheduled mutation-testing template tests. - Parameterise `_assert_pyproject_contracts` with `python_version` and thread it through `assert_generated_tooling_contracts` so the `requires-python` check matches the version each caller renders, rather than a hard-coded `>=3.12`. - Split `test_generated_mutation_testing_gating` into focused helpers for documentation guidance, `[tool.mutmut]` configuration, workflow metadata, job gating and inputs, and shared-workflow SHA validation. - Assert the previously unchecked workflow surface: the `30 9 * * *` schedule, empty top-level `permissions`, per-ref `concurrency` with `cancel-in-progress: false`, the mutmut job `paths`/`module-prefix-strip` inputs, and the cargo-mutants job `paths`/`extra-crate-dirs`/`shard-count` inputs. - Cap the `test_python_version_minor_controls_mutmut_generation` property test at `max_examples=25` to keep CI runtime predictable while retaining the explicit boundary examples. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1398fa5 to
0896a56
Compare
Summary
This branch rolls the estate-wide scheduled mutation-testing pattern into the Copier template so newly generated repositories receive the applicable shared workflow by default.
Python projects with a 3.13 or newer baseline receive mutmut configuration and a scheduled mutmut job. Rust-enabled projects receive cargo-mutants independently of the Python baseline. Projects with neither capability do not render a mutation-testing workflow. The default Python baseline moves from 3.10 to 3.12, and malformed baseline answers now fail at the Copier boundary before the hidden mutation-support answer is derived.
Review walkthrough
copier.ymlfor the Python 3.12 default, strict3.Xvalidation, and defensivemutmut_supportedcomputation.leynos/shared-actions@859416a90eb3987b46a57682c5d6b8964ad3f0a6.template/pyproject.toml.jinjafor the gated mutmut configuration.tests/test_template.pyand the shared rendering helper for rendering-gate, malformed-input, workflow, TOML and actionlint coverage.Gating and scheduling
[tool.mutmut]section render only for Python 3.13 or newer because the shared workflow helpers require Python 3.13 or newer.use_rustand targetsrust_extension/throughextra-crate-dirsbecause generated repositories have no rootCargo.toml.30 9 * * *(09:30 UTC), with guidance to stagger it per repository.shard-count: 1confines the failing root target to one leg while the extension target still runs.Validation
make check-fmt: passed; 19 files checked.make lint: passed; Ruff clean and interrogate coverage 100%.make typecheck: passed.make test: passed; 41 passed, 2 skipped and 3 snapshots passed.cargo test --manifest-path rust_extension/Cargo.tomlpassed with 1 test.References