Skip to content

Add scheduled mutation testing to generated repos - #52

Open
leynos wants to merge 13 commits into
mainfrom
add-mutation-testing-template
Open

Add scheduled mutation testing to generated repos#52
leynos wants to merge 13 commits into
mainfrom
add-mutation-testing-template

Conversation

@leynos

@leynos leynos commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Summary

Adds template/.github/workflows/mutation-testing.yml so newly generated Rust repositories get scheduled mutation testing by default, matching the pattern already rolled out across the estate (for example leynos/mapsplice).

The workflow is a thin caller of the shared reusable workflow leynos/shared-actions/.github/workflows/mutation-cargo.yml. Caller guide: https://github.com/leynos/shared-actions/blob/main/docs/mutation-cargo-workflow.md.

Details:

  • Triggers: daily schedule plus workflow_dispatch. The default cron is 15 9 * * *; the estate already occupies the 03:05–09:05 UTC slots, and an inline comment tells maintainers of generated repositories to stagger their slot to avoid concurrent runs across the estate.
  • Root permissions: {}; the mutation job opts in to contents: read and id-token: write (OIDC workflow-source resolution).
  • Concurrency group mutation-testing-${{ github.ref }} with cancel-in-progress: false, so dispatches queue behind scheduled runs rather than racing or cancelling.
  • extra-args: "--all-features" mirrors the template CI test baseline (make test runs with --all-targets --all-features). Workspace-related inputs are omitted because the generated project is a single root crate.
  • The file is plain YAML rather than Jinja-templated, matching ci.yml and act-validation.yml, as it needs no template variables; this also sidesteps the ${{ }} Jinja/Actions syntax collision.
  • The generated docs/repository-layout.md is updated to list the new workflow.
  • Rendered tooling-contract tests now parse the generated mutation-testing.yml and assert its contract: root permissions grant no scopes, the mutation job calls the shared mutation-cargo reusable workflow, the job permissions stay scoped to contents: read and id-token: write, extra-args mirrors the CI --all-features baseline, and the setup-commands install clang, lld, and mold. The pinned reusable-workflow SHA is deliberately not asserted, as Dependabot owns and bumps that reference.

Validation

  • copier copy --defaults renders cleanly and the workflow is copied verbatim.
  • actionlint passes on the rendered file.
  • make test: 50 passed, 1 skipped (includes the new mutation-workflow contract assertions).

References

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @leynos, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a generated GitHub Actions workflow for scheduled or manually dispatched mutation testing through a shared reusable workflow. Documents the workflow and extends generated tooling contracts to validate permissions, inputs, wiring, pins, and setup commands.

Changes

Mutation testing workflow and contracts

Layer / File(s) Summary
Mutation-testing workflow definition
template/.github/workflows/mutation-testing.yml
Add cron and manual triggers, restricted permissions, per-ref concurrency, shared mutation-cargo.yml invocation, --all-features, and installation of clang, lld, and mold.
Generated documentation
template/docs/*.jinja, docs/*.md
Document the generated workflow, repository layout, scheduling, mutation behaviour, permissions, and reusable-workflow pinning.
Workflow contract validation
tests/helpers/tooling_contracts/*.py, tests/test_template/test_tooling_contracts.py, tests/test_helpers.py
Parse workflow steps, enforce full SHA pins, validate mutation-specific settings, wire the rendered workflow into orchestration, and test shell-package extraction and Hypothesis strategies.

Sequence Diagram(s)

sequenceDiagram
  participant Trigger as GitHub schedule or dispatch
  participant Caller as mutation-testing.yml
  participant Shared as mutation-cargo workflow
  participant Runner as cargo-mutants
  Trigger->>Caller: start workflow
  Caller->>Shared: pass --all-features and setup commands
  Shared->>Runner: execute mutation testing
Loading

Possibly related issues

  • leynos/shared-actions#342: Covers mutation-testing workflow execution and reporting in the shared reusable workflow invoked here.

Possibly related PRs

Poem

At nine-fifteen, mutations start,
With clang and mold to play their part,
Locked-down tokens guard the flow,
All features march in neat tableau,
One ref at a time, from code to chart. 🐇⚙️


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 1 inconclusive)

Check name Status Explanation Resolution
Testing (Overall) ❌ Error Mutation workflow tests only check that the target cron appears; they still accept extra schedule entries or fields, so the new schedule contract is under-tested. Assert schedule == [{'cron': _MUTATION_CRON}] and add negative tests for extra schedule items and extra keys in each schedule entry.
Unit Architecture ❓ Inconclusive Placeholder pending evidence. Need to inspect the modified workflow and test helpers for boundary violations before deciding.
✅ Passed checks (18 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: it adds scheduled mutation testing to generated repositories.
Description check ✅ Passed The description is directly about the mutation-testing workflow, docs, and contract tests in the PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
User-Facing Documentation ✅ Passed docs/users-guide.md and template/docs/users-guide.md.jinja both add a Scheduled Mutation Testing section covering purpose, triggers, usage, and permissions.
Developer Documentation ✅ Passed Document the new mutation workflow and tooling in docs/developers-guide.md; no execplan or ADR gap appears for this scope.
Module-Level Documentation ✅ Passed PASS: each touched Python module begins with a clear module docstring describing its role and ties to the related tooling-contract helpers/tests.
Testing (Unit And Behavioural) ✅ Passed The new tests cover local edge cases, error paths, and the rendered workflow boundary; no behavioural check is left to private seams alone.
Testing (Property / Proof) ✅ Passed Hypothesis tests now cover the new range-based invariants in _extract_apt_install_packages and ref-pinning helpers, so property testing is appropriately recommended and present.
Testing (Compile-Time / Ui) ✅ Passed No Rust/TS compile-time surface exists; the new structured workflow output is covered by parsed contract tests and property tests.
Domain Architecture ✅ Passed PASS: The PR only touches template workflows, docs, and test helpers; no domain-layer code or boundary leakage was introduced.
Observability ✅ Passed Rely on the GitHub Actions job logs for this scheduled workflow; the PR only adds a thin caller and docs, with no service boundary, metrics, tracing, or alerts to add.
Security And Privacy ✅ Passed PASS: the new workflow keeps permissions minimal, pins the reusable workflow by full SHA, and adds no secrets or user-controlled command construction.
Performance And Resource Use ✅ Passed PASS: New loops parse bounded workflow text and render-time tests; no hot-path, unbounded collection, or repeated I/O regressions are introduced.
Concurrency And State ✅ Passed PASS: the workflow makes ordering explicit with concurrency.group and cancel-in-progress: false, and it adds no shared mutable state or async lifetimes.
Architectural Complexity And Maintainability ✅ Passed PASS: The new helpers are narrow, explicit, and directly exercised; they factor real workflow-contract seams without hidden hooks or speculative layers.
Rust Compiler Lint Integrity ✅ Passed No Rust source was changed; the only .rs file is an untouched stub, and the patch adds no lint suppressions, artificial references, or suspicious clones.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-mutation-testing-template

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5cb3aa8dbe

ℹ️ 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".

Comment thread template/.github/workflows/mutation-testing.yml Outdated
@leynos

leynos commented Jul 7, 2026

Copy link
Copy Markdown
Owner Author

Review feedback addressed in facc38a: the generated .cargo/config.toml links Linux dev targets with clang and -fuse-ld=mold, so the mutants jobs would have failed to link on a bare ubuntu-latest runner.

  • Bumped the shared workflow pin to 0c8bd605f8966a004decb0b54f717a745f51bc57, which introduces the setup-commands input.
  • Added setup-commands installing clang lld mold exactly as the generated ci.yml does (same apt-get invocation and comment).
  • Kept the install unconditional and the file plain-copied: ci.yml itself installs these packages regardless of the dev_target chosen at generation time (the mold config in .cargo/config.toml is conditional on a Linux dev_target, but the workflow convention is not), so no Jinja conversion was needed.

Re-validated: copier copy --defaults renders for both the default Linux dev_target and aarch64-apple-darwin (workflow identical and verbatim in both), actionlint passes on the rendered file, and the contract suite shows the same 3 pre-existing failures tracked in #53, with no new failures (47 passed, 1 skipped).

@pandalump

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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/.github/workflows/mutation-testing.yml`:
- Around line 1-47: The workflow contract for mutation testing is not covered by
assertions, so changes to the pinned reusable-workflow SHA, the setup package
list, or the job permissions could slip through. Extend the existing
tooling-contract tests around mutation-testing.yml to verify the job uses the
expected pinned ref in the mutation job, the setup-commands installs the
required packages, and the mutation job permissions remain scoped to contents:
read and id-token: write.
🪄 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: 27643c2a-2103-4b4a-9c4f-1d5db8d3a601

📥 Commits

Reviewing files that changed from the base of the PR and between 7d7eb00 and facc38a.

📒 Files selected for processing (2)
  • template/.github/workflows/mutation-testing.yml
  • template/docs/repository-layout.md.jinja

Comment thread template/.github/workflows/mutation-testing.yml
@leynos

leynos commented Jul 7, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@leynos

leynos commented Jul 16, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

coderabbitai[bot]

This comment was marked as resolved.

@pandalump

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/tooling_contracts/workflows.py`:
- Around line 354-371: Update the apt-get install extraction loop to skip lines
whose trimmed content begins with “#”, so commented commands are never treated
as installs. In the existing shlex.split error handler, stop extraction by
raising or otherwise propagating the parsing failure instead of falling back to
segment.split(); preserve normal token filtering for valid shell commands.
- Around line 381-395: Update the mutation-testing workflow assertions in the
contract test to require a schedule entry with cron exactly "15 9 * * *" and
require concurrency.group to equal "mutation-testing-${{ github.ref }}". Keep
the existing checks for schedule presence, workflow_dispatch, and
cancel-in-progress unchanged.
- Around line 27-31: Replace the text-search regexes in
tests/helpers/tooling_contracts/workflows.py lines 27-31 with full-reference
patterns suitable for re.fullmatch(), then update the checks at lines 244-247,
286-289, and 443-446 to parse the relevant job steps and validate each actual
uses: value via re.fullmatch(). Ensure comments or mutable refs cannot satisfy
the setup-rust, setup-python, or upload-artifact contract checks.
🪄 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: 16167a73-1adb-4c69-929e-403a112dae5e

📥 Commits

Reviewing files that changed from the base of the PR and between d59179a and 593679c.

📒 Files selected for processing (10)
  • docs/developers-guide.md
  • docs/users-guide.md
  • template/.github/workflows/mutation-testing.yml
  • template/docs/developers-guide.md.jinja
  • template/docs/repository-layout.md.jinja
  • template/docs/users-guide.md.jinja
  • tests/helpers/tooling_contracts/orchestration.py
  • tests/helpers/tooling_contracts/workflows.py
  • tests/test_helpers.py
  • tests/test_template/test_tooling_contracts.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • leynos/whitaker (auto-detected)

Comment thread tests/helpers/tooling_contracts/workflows.py Outdated
Comment thread tests/helpers/tooling_contracts/workflows.py Outdated
Comment thread tests/helpers/tooling_contracts/workflows.py
@pandalump

Copy link
Copy Markdown
Collaborator

@coderabbitai review

leynos and others added 9 commits July 24, 2026 23:06
Add a mutation-testing caller workflow to the template so newly
generated Rust projects run scheduled mutation testing by default. The
workflow is a thin caller of the shared mutation-cargo reusable
workflow in leynos/shared-actions, pinned to a full commit SHA in line
with the template's action-pinning convention.

The workflow runs daily at 09:15 UTC with a comment advising
maintainers to stagger the slot per repository, and supports manual
dispatch. It defaults the token to no scopes, with the job opting in to
contents: read and id-token: write. The extra-args input mirrors the
CI test baseline (--all-features); workspace inputs are omitted as the
generated project is a single crate.

The file is plain YAML rather than Jinja-templated, matching ci.yml
and act-validation.yml, as it needs no template variables. The
generated repository-layout document is updated to list the new
workflow.
The generated .cargo/config.toml links Linux dev targets with clang
and -fuse-ld=mold, and the generated ci.yml installs mold before any
cargo command, but the mutation workflow's mutants jobs had no way to
install it, so the cargo-mutants baseline would fail to link on a bare
ubuntu-latest runner.

Bump the shared workflow pin to 0c8bd605f8966a004decb0b54f717a745f51bc57,
which introduces the setup-commands input, and use it to install clang,
lld, and mold exactly as the generated ci.yml does. The install is
unconditional, matching ci.yml's own convention: CI always runs on
Linux runners, and ci.yml installs the packages regardless of the
dev_target chosen at generation time, so the workflow stays a plain
copied file rather than becoming Jinja-templated.
The mutation-testing.yml caller shipped without any contract coverage, so
a regression to the reusable-workflow reference, the setup-command package
list, or the mutation job's permission scope could slip through review.

Extend the rendered tooling-contract suite to parse mutation-testing.yml
and assert that: root permissions grant no scopes; the mutation job calls
the shared mutation-cargo reusable workflow; the job permissions stay
scoped to contents: read and id-token: write; extra-args mirrors the CI
--all-features baseline; and the setup-commands install clang, lld, and
mold via apt-get.

The pinned reusable-workflow SHA is deliberately not asserted, as
Dependabot owns and bumps that reference independently of this contract.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
repository-layout listed the generated mutation-testing.yml workflow, but
neither user guide explained what it does or how it affects a generated
project, leaving adopters without guidance.

Add a "Scheduled Mutation Testing" section to both the template-rendered
user guide (template/docs/users-guide.md.jinja) and the parent-repository
user guide (docs/users-guide.md). The section explains that generated
projects run cargo-mutants via the shared mutation-cargo reusable workflow
on a daily schedule plus manual dispatch, what surviving mutants mean, that
scheduled runs mutate only recently changed files while dispatch runs cover
the whole crate, and that the runs are informational rather than gating
pull requests. It also tells adopters to stagger the cron slot and notes
the least-privilege token scope.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The mutation-testing contract only checked root/job permissions, the
reusable-workflow path prefix, extra-args, and substring package matches,
so several workflow regressions could still pass: an un-pinned reusable
ref, a dropped schedule or manual dispatch, a flipped cancel-in-progress,
or a package name appearing only in a comment.

Extend `_assert_mutation_workflow_contracts` to also require:

- an `on.schedule` cron trigger and `workflow_dispatch` support;
- `concurrency.group` present with `cancel-in-progress: false`, so queued
  runs wait rather than cancelling;
- the mutation job's `uses` ref pinned to a full 40-character commit SHA
  (format only; the specific SHA is owned by Dependabot and not hard-coded,
  so the contract survives dependency bumps);
- clang, lld, and mold present as complete `apt-get install` arguments,
  parsed from the extracted install command rather than substring-matched
  against the whole setup script.

Collapse the helper's docstring to a single-line summary matching its
sibling `_assert_*` workflow validators.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The user guides describe the scheduled mutation-testing workflow, but the
developer guides omitted it, leaving contributors without pointers to how
it is tested or maintained.

Add a note to the parent developer guide (docs/developers-guide.md)
recording that the template renders the mutation-testing workflow into
generated projects, that its rendered contract is asserted by
`_assert_mutation_workflow_contracts`, and that Dependabot owns the pinned
reusable-workflow SHA (so the test asserts the pin format, not a hard-coded
value). Add a companion note to the generated-project developer guide
(template/docs/developers-guide.md.jinja) explaining that the scheduled
workflow runs cargo-mutants via the shared reusable workflow, is
informational rather than a pull-request gate, has its pinned SHA kept
current by Dependabot, and that surviving mutants should be promoted into
new tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dependabot bumps the pinned GitHub Actions commit SHAs in the template's
workflow files, but it cannot update the contract tests, so hard-coding
those SHAs in assertions made the suite drift and fail on every bump.

Assert action pins by format instead of by value. Two helpers,
`_assert_pinned_to_commit_sha` (for a parsed `uses` field) and
`_assert_pinned_action_in_text` (for a whole-workflow substring search),
require each action reference to target its expected path pinned to a full
40-character commit SHA, without naming the SHA. Apply them to the shared
coverage, setup-rust, setup-python, upload-artifact, and mutation-cargo
references, and route the mutation-job pin check through the shared helper.
Replace the `_ci_workflow` fixture's real SHA with a 40-zero placeholder.

The release workflow's `CROSS_REVISION` pin is left asserted verbatim: it
is a `cargo install cross --rev` git revision, not a GitHub Actions `uses:`
SHA, and Dependabot does not manage it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The mutation-testing and pinned-action contract checks were satisfiable by
non-runnable or mutable inputs: comment-only or malformed apt installs
passed the package check, text-searched action pins could match a commented
or otherwise non-step reference, and the schedule/concurrency checks only
confirmed a cron and group existed rather than the exact daily per-ref
behaviour.

Parse the actual workflow steps and validate each `uses:` value with
`re.fullmatch` via a new `_assert_pinned_step_uses` helper (plus
`_iter_job_steps` for cross-job release steps), replacing the raw-text
searches for the setup-rust, setup-python, and upload-artifact pins so a
comment or mutable tag can no longer satisfy them. Make
`_extract_apt_install_packages` skip commented lines and raise on `shlex`
parse failures instead of masking malformed shell as a valid install.
Assert the exact cron (`15 9 * * *`) and concurrency group
(`mutation-testing-${{ github.ref }}`) for the mutation-testing workflow.

Add focused unit tests for the tightened apt-install parser covering
normal extraction, comment skipping, and malformed-shell rejection.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rebasing onto main brought in the scheduled dependency-audit workflow
contract (`_assert_audit_workflow_contracts` and its `_is_pinned_action`
helper), which referenced the `_SETUP_RUST_USES_TEXT_RE` constant that this
branch had renamed to `_SETUP_RUST_USES_RE` when switching the pinned-action
checks to parse job steps and `re.fullmatch`. Point the audit contract at
the renamed constant so both the audit and mutation-testing contracts share
one setup-rust pattern.

Also tidy merge artefacts: sort the workflows helper imports, drop a
duplicate module docstring stranded in the test module by the three-way
merge, and apply `ruff format` so `make check-fmt` passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lodyai
lodyai Bot force-pushed the add-mutation-testing-template branch from 18d169c to 52d1927 Compare July 24, 2026 21:20
@buzzybee-df12

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/test_helpers.py (1)

173-201: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Split the multi-branch ref generator.

Extract the four kind branches into focused helpers or predicates; this conditional exceeds the two-branch limit.

🤖 Prompt for 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.

In `@tests/test_helpers.py` around lines 173 - 201, Refactor _non_sha_refs so it
no longer contains the four-way kind match. Extract the short, long, uppercased,
and branch generation paths into focused helper strategies or predicates, then
compose them in _non_sha_refs while preserving the guarantee that generated refs
are not 40-character lowercase-hex SHAs.

Source: Path instructions

🤖 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/tooling_contracts/workflows.py`:
- Around line 508-516: Update the mutation-testing workflow contract assertions
around require_mapping so the trigger mapping contains exactly the schedule and
workflow_dispatch keys, rejecting any additional push or pull-request triggers
while preserving the existing cron and manual-dispatch checks.

---

Outside diff comments:
In `@tests/test_helpers.py`:
- Around line 173-201: Refactor _non_sha_refs so it no longer contains the
four-way kind match. Extract the short, long, uppercased, and branch generation
paths into focused helper strategies or predicates, then compose them in
_non_sha_refs while preserving the guarantee that generated refs are not
40-character lowercase-hex SHAs.
🪄 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: 6e28f6ee-2f29-49ca-97a8-a97f7090e1b3

📥 Commits

Reviewing files that changed from the base of the PR and between d59179a and 52d1927.

📒 Files selected for processing (10)
  • docs/developers-guide.md
  • docs/users-guide.md
  • template/.github/workflows/mutation-testing.yml
  • template/docs/developers-guide.md.jinja
  • template/docs/repository-layout.md.jinja
  • template/docs/users-guide.md.jinja
  • tests/helpers/tooling_contracts/orchestration.py
  • tests/helpers/tooling_contracts/workflows.py
  • tests/test_helpers.py
  • tests/test_template/test_tooling_contracts.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • leynos/whitaker (auto-detected)

Comment thread tests/helpers/tooling_contracts/workflows.py
leynos and others added 2 commits July 26, 2026 04:15
Tighten the mutation-testing workflow contract to require the trigger
mapping to be exactly {schedule, workflow_dispatch}, so an added push or
pull-request trigger is rejected rather than silently accepted; the exact
cron and manual-dispatch checks are preserved. This mirrors the audit
workflow contract's trigger assertion.

Refactor the `_non_sha_refs` Hypothesis strategy to drop its four-way
`match kind` block. Extract focused strategies for too-short and too-long
hex refs, branch names, and uppercased 40-character hex refs, then compose
them with `st.one_of`, preserving the guarantee that generated refs are
never a 40-character lowercase-hex commit SHA.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The `_extract_apt_install_packages` shell parser handled many input shapes
(flags in any position, comment lines, backslash continuations) but was
only exercised by example tests, leaving its invariant implicit.

Add Hypothesis strategies for shell-safe package and flag tokens and three
property tests: one asserts the parser returns exactly the non-flag
arguments in order for an install line of interleaved flags and packages
(with varied indentation and optional sudo); one asserts a commented
install line never contributes packages; and one asserts packages split
onto a backslash-continued line are still recovered. The prior example
tests, including the exact-template form and the malformed-shell rejection,
remain as concrete anchors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@leynos

leynos commented Jul 26, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

tests/test_helpers.py (1)

173-201: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Split the multi-branch ref generator.
Extract the four kind branches into focused helpers or predicates; this conditional exceeds the two-branch limit.

🤖 Detailed instructions

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @tests/test_helpers.py around lines 173 - 201, Refactor _non_sha_refs so it
no longer contains the four-way kind match. Extract the short, long, uppercased,
and branch generation paths into focused helper strategies or predicates, then
compose them in _non_sha_refs while preserving the guarantee that generated refs
are not 40-character lowercase-hex SHAs.

Source: Path instructions

@leynos

leynos commented Jul 26, 2026

Copy link
Copy Markdown
Owner Author

@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)

Check name Status Explanation Resolution
Testing (Overall) ❌ Error The mutation-workflow contract still accepts extra triggers, so a stray push/pull_request trigger would slip through. Assert the trigger keys are exactly {'schedule','workflow_dispatch'} (and the cron list only contains 15 9 * * *), so added triggers fail.
Testing (Property / Proof) ⚠️ Warning Add Hypothesis coverage for _extract_apt_install_packages; the new shell parser spans many input shapes, but only example tests are present. Add property tests for the shell parser, or constrain it to the exact template form so the invariant is explicit and not left to examples.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline tests/test_helpers.py --items all --type function --match 'non_sha|ref' || true
printf '\n--- _non_sha_refs references ---\n'
rg -n -C 5 '\b_non_sha_refs\b' tests/test_helpers.py
printf '\n--- requested source range ---\n'
sed -n '150,225p' tests/test_helpers.py

Length of output: 4806


@leynos Mark this finding as resolved.

_non_sha_refs no longer contains the four-way kind branch. It now composes focused strategies for short hex refs, long hex refs, named branch refs, and 40-character refs containing a guaranteed uppercase hex letter. The existing Hypothesis property still verifies that every generated value is rejected as a pinned SHA ref.

Static verification completed; no repository tests were executed in this inspection environment.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Recent commits =='
git log --oneline -12

printf '%s\n' '== Workflows helper outline =='
ast-grep outline tests/helpers/tooling_contracts/workflows.py --items all --type function

printf '%s\n' '== Relevant workflow contract implementation =='
rg -n -A100 -B20 \
  'def _assert_mutation_workflow_contracts\b|def _extract_apt_install_packages\b' \
  tests/helpers/tooling_contracts/workflows.py

printf '%s\n' '== Helper-test outline =='
ast-grep outline tests/test_helpers.py --items all --type function --match 'extract|non_sha'

printf '%s\n' '== Parser tests and property-test evidence =='
rg -n -A40 -B15 \
  'extract_apt_install_packages|`@given`|hypothesis|non_sha_refs' \
  tests/test_helpers.py tests

printf '%s\n' '== Current mutation workflow =='
cat -n template/.github/workflows/mutation-testing.yml

Length of output: 84073


@leynos partially resolved.

Check Status Evidence
Testing (Overall) Still requires work tests/helpers/tooling_contracts/workflows.py Line 509 now rejects extra trigger keys, so stray push and pull_request triggers fail. However, Lines 513-517 use any(...) for the cron assertion, so a second, unintended schedule entry still passes. Assert the schedule sequence is exactly one entry: [{ "cron": "15 9 * * *" }].
Testing (Property / Proof) Resolved Commit 39978b4 adds Hypothesis coverage in tests/test_helpers.py Lines 637-679. It exercises flag filtering/order, commented-out commands, and backslash continuations using bounded shell-safe package and flag tokens.
Prior _non_sha_refs maintainability finding Resolved tests/test_helpers.py Lines 173-199 now composes focused short, long, uppercased, and branch-ref strategies rather than using a four-way conditional.

Use this prompt for the remaining work:

Update PR `#52` in leynos/agent-template-rust to finish the mutation-workflow trigger contract.

Problem:
`_assert_mutation_workflow_contracts` in `tests/helpers/tooling_contracts/workflows.py` now rejects extra trigger keys, but it still accepts extra cron entries because it uses `any(...)` over `on.schedule`.

Requirements:
1. Keep the exact trigger-key assertion:
   `set(triggers) == {"schedule", "workflow_dispatch"}`.
2. Tighten the schedule assertion so it accepts exactly one schedule item and that item is exactly the expected cron mapping:
   `[{ "cron": "15 9 * * *" }]`.
   Reject:
   - multiple schedule entries, even if one is the expected cron;
   - an incorrect cron;
   - additional keys in the schedule entry.
3. Add focused negative contract tests that prove an extra cron entry and a schedule entry with extra fields fail. Preserve the valid rendered-workflow test.
4. Keep changes limited to the mutation-workflow contract and its tests. Do not alter the generated workflow unless required by the stricter contract.
5. Run the targeted helper/contract tests and the relevant template tooling-contract test; report results and any pre-existing failures separately.

No GitHub issue is needed: the remaining change is in scope and narrowly scoped to this PR.

@pandalump

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
tests/helpers/tooling_contracts/workflows.py (3)

457-471: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Reduce private helper docstrings to one-line summaries.

  • tests/helpers/tooling_contracts/workflows.py#L457-L471: Replace the structured _extract_apt_install_packages docstring with a concise summary.
  • tests/helpers/tooling_contracts/workflows.py#L635-L643: Replace the explanatory _assert_pinned_step_uses docstring with a concise summary.

As per path instructions, “Use a single-line summary for private functions and methods.”

🤖 Prompt for 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.

In `@tests/helpers/tooling_contracts/workflows.py` around lines 457 - 471, Shorten
the private helper docstrings to single-line summaries: replace the structured
docstring for _extract_apt_install_packages in
tests/helpers/tooling_contracts/workflows.py at lines 457-471 with one concise
description, and do the same for _assert_pinned_step_uses at lines 635-643.
Preserve each helper’s purpose while removing parameter, return-value, and
explanatory sections.

Source: Path instructions


513-517: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Require exactly the documented schedule entry.

Replace the existential check with equality to [{ "cron": _MUTATION_CRON }]. The current assertion accepts extra schedules or extra entry fields, so the daily trigger contract can drift while remaining green.

Proposed fix
-    assert any(
-        isinstance(entry, dict) and entry.get("cron") == _MUTATION_CRON
-        for entry in schedule
-    ), f"expected mutation-testing workflow to schedule cron {_MUTATION_CRON!r}"
+    assert schedule == [{"cron": _MUTATION_CRON}], (
+        "expected mutation-testing workflow to contain exactly the documented "
+        f"schedule cron {_MUTATION_CRON!r}"
+    )
🤖 Prompt for 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.

In `@tests/helpers/tooling_contracts/workflows.py` around lines 513 - 517, Update
the schedule assertion in the workflow contract test to compare schedule
directly with a single-entry list containing only {"cron": _MUTATION_CRON},
replacing the any-based existential check. Preserve the existing
require_sequence lookup and failure message context while rejecting extra
schedules or fields.

472-498: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Parse an actual apt-get install command.

Tokenize the complete logical command and require optional sudo followed by exact apt-get, install tokens before extracting packages. line.find() accepts text such as echo "apt-get install clang lld mold", allowing the contract to pass without a runnable installation command. Add that negative case.

🤖 Prompt for 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.

In `@tests/helpers/tooling_contracts/workflows.py` around lines 472 - 498, Update
the setup-command parsing logic around the apt-get marker to tokenize each
complete logical shell command, then require the command structure to be
optional sudo followed by exact apt-get and install tokens before extracting
package names. Do not match embedded text such as echo arguments, and add a
negative test covering an echo containing “apt-get install” without an actual
installation command.
🤖 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/test_helpers.py`:
- Around line 175-198: Annotate the module-level Hypothesis strategy aliases
with explicit SearchStrategy types: update _non_sha_refs at
tests/test_helpers.py lines 175-198 and _apt_package_tokens, _apt_flag_tokens,
and _apt_install_tokens at lines 618-634. Use the appropriate element type for
each strategy so all aliases remain statically type-checked without changing
their generated values.

---

Outside diff comments:
In `@tests/helpers/tooling_contracts/workflows.py`:
- Around line 457-471: Shorten the private helper docstrings to single-line
summaries: replace the structured docstring for _extract_apt_install_packages in
tests/helpers/tooling_contracts/workflows.py at lines 457-471 with one concise
description, and do the same for _assert_pinned_step_uses at lines 635-643.
Preserve each helper’s purpose while removing parameter, return-value, and
explanatory sections.
- Around line 513-517: Update the schedule assertion in the workflow contract
test to compare schedule directly with a single-entry list containing only
{"cron": _MUTATION_CRON}, replacing the any-based existential check. Preserve
the existing require_sequence lookup and failure message context while rejecting
extra schedules or fields.
- Around line 472-498: Update the setup-command parsing logic around the apt-get
marker to tokenize each complete logical shell command, then require the command
structure to be optional sudo followed by exact apt-get and install tokens
before extracting package names. Do not match embedded text such as echo
arguments, and add a negative test covering an echo containing “apt-get install”
without an actual installation command.
🪄 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: 01c4af09-cd83-46ef-892d-af84fe09899c

📥 Commits

Reviewing files that changed from the base of the PR and between 52d1927 and 39978b4.

📒 Files selected for processing (2)
  • tests/helpers/tooling_contracts/workflows.py
  • tests/test_helpers.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • leynos/whitaker (auto-detected)

Comment thread tests/test_helpers.py Outdated
leynos and others added 2 commits July 27, 2026 14:52
Rework `_extract_apt_install_packages` so it recognises a real install
command rather than any line containing the substring "apt-get install".
Each logical line is tokenised with shlex, split on shell control operators
(`&&`, `||`, `;`, `|`, `&`), and a command counts only when its tokens are
an optional `sudo` followed by exactly `apt-get install`. Embedded text such
as an `echo "... apt-get install ..."` argument is now ignored. Add a
negative test covering that case.

Also address adjacent review points:

- Assert the mutation-testing `on.schedule` equals exactly
  `[{"cron": _MUTATION_CRON}]`, rejecting extra schedule entries or fields,
  instead of an existential any() check.
- Reduce the `_extract_apt_install_packages` and `_assert_pinned_step_uses`
  docstrings to single-line summaries, matching the sibling helpers.
- Annotate the module-level Hypothesis strategy aliases with explicit
  `SearchStrategy` element types so they stay statically checked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The mutation-testing schedule assertion already requires
`schedule == [{"cron": _MUTATION_CRON}]`, but nothing proved the contract
actually rejects a non-conforming schedule, leaving the invariant asserted
only against the canonical rendered workflow.

Add two focused unit tests that drive `_assert_mutation_workflow_contracts`
with hand-built workflows and confirm it raises: one with a second schedule
entry beyond the sanctioned cron, and one with an extra key smuggled into
the single schedule entry. A small fixture builder populates just the
fields inspected before the schedule check so the assertion is exercised in
isolation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants