Skip to content

Single source of truth for rebuild_lockfiles resolution (#106) - #116

Merged
leynos merged 10 commits into
mainfrom
issue-106-single-rebuild-lockfiles-resolution
Jun 11, 2026
Merged

Single source of truth for rebuild_lockfiles resolution (#106)#116
leynos merged 10 commits into
mainfrom
issue-106-single-rebuild-lockfiles-resolution

Conversation

@leynos

@leynos leynos commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #106

  • cli.bump now forwards the raw nullable rebuild_lockfiles flag; the only None-coalescing against configuration.bump.rebuild_lockfiles happens in bump._initialize_bump_context.
  • Note: the Cyclopts TOML loader may still hydrate the CLI flag from lading.toml before dispatch (use_commands_as_keys=True); cli.bump itself performs no coalescing. This is called out in a code comment and the developers' guide.
  • docs/developers-guide.md records that option defaulting is the command layer's responsibility, not the CLI adapter's.

Testing

  • New parametrised matrix test exercises the resolution through the command layer: rebuild_lockfiles ∈ {None, True, False} × configuration.bump.rebuild_lockfiles ∈ {True, False}.
  • CLI test updated to assert raw forwarding (including the cyclopts-hydration case).
  • make check-fmt, make lint, make typecheck, and make test (561 passed) all green.
  • coderabbit review --agent: 0 findings.

🤖 Generated with Claude Code

Summary by Sourcery

Centralize resolution of the nullable rebuild_lockfiles option in the bump command layer and ensure the CLI simply forwards the raw flag.

Bug Fixes:

  • Ensure rebuild_lockfiles correctly inherits from configuration only within the bump command context when the CLI flag is unset.

Enhancements:

  • Clarify ownership of option defaulting by having cli.bump forward rebuild_lockfiles without coalescing and documenting this responsibility in the developers guide.

Documentation:

  • Document that option defaulting is owned by the command layer, including how rebuild_lockfiles is resolved between CLI flags and configuration.

Tests:

  • Add integration tests covering rebuild_lockfiles resolution across combinations of CLI flag and configuration, and update CLI tests to assert raw flag forwarding behavior.

cli.bump duplicated the None-coalescing of rebuild_lockfiles against
configuration.bump.rebuild_lockfiles that
bump._initialize_bump_context already performs, giving two sources of
truth for the same decision.

Forward the raw nullable flag from the CLI and let the command own the
resolution. Note that the Cyclopts TOML loader may still hydrate the
CLI flag from lading.toml before dispatch; cli.bump itself performs no
coalescing.

Add a parametrised matrix test (flag in {None, True, False} x
configuration in {True, False}) exercising the resolution through the
command layer, update the CLI test to assert raw forwarding, and
record the option-defaulting convention in the developers' guide.

Closes #106
@coderabbitai

coderabbitai Bot commented Jun 9, 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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 23d66206-521e-4819-b961-c57e300a45a1

📥 Commits

Reviewing files that changed from the base of the PR and between 2237925 and ffc2c94.

📒 Files selected for processing (1)
  • tests/unit/test_bump_lockfile_rebuild.py
💤 Files with no reviewable changes (1)
  • tests/unit/test_bump_lockfile_rebuild.py

This PR implements a single source of truth for resolving the nullable rebuild_lockfiles option (closes #106). The CLI now forwards rebuild_lockfiles unchanged (bool | None) and resolution/coalescing against configuration.bump.rebuild_lockfiles happens exactly once in bump._initialize_bump_context; a DEBUG log was added to record raw_flag, configured_default and resolved_value.

Changes

  • Documentation
    • docs/developers-guide.md: clarifies that option defaulting is the command layer’s responsibility (bump._initialize_bump_context) and that cli.bump forwards the raw flag.
  • CLI adapter
    • lading/cli.py: module docstring updated; cli.bump forwards rebuild_lockfiles directly into BumpOptions without coalescing. Notes Cyclopts may hydrate flags from lading.toml (use_commands_as_keys=True) before dispatch.
  • Command logic
    • lading/commands/bump.py: added _log.debug in _initialize_bump_context to emit raw/configured/resolved values.
  • Tests & fixtures
    • tests/unit/test_bump_rebuild_lockfiles_resolution.py (new): unit, integration and Hypothesis property tests covering the full matrix flag ∈ {None, True, False} × configuration.bump.rebuild_lockfiles ∈ {True, False}, verifying single-point resolution and that DEBUG logging is emitted.
    • tests/unit/test_cli.py: updated to assert raw forwarding (including Cyclopts-hydrated cases); test renamed to test_bump_cli_forwards_raw_rebuild_lockfiles.
    • tests/unit/conftest.py: added autouse stub_lockfile_regeneration fixture to no-op lockfile regeneration for allowlisted bump test modules.
    • Tests reorganised: manifest-only, lockfile, and documentation tests split into focused modules:
      • tests/unit/test_bump_manifest_updates.py: focused manifest/version update tests.
      • tests/unit/test_bump_lockfile_rebuild.py (new): lockfile rebuild/skip behaviour with syrupy snapshots.
      • tests/unit/test_bump_documentation_updates.py (new): README transposition and documentation snippet updates with snapshots.
    • Snapshots updated: tests/unit/snapshots for the above modules.
  • Minor
    • Small test cleanup (stale expected_message removed).

Validation

  • make check-fmt, make lint, make typecheck, make test: all checks reported passing (561 tests).
  • Code review: CodeRabbit review — 0 findings.

Notes

  • No execplan document was added.
  • Behavioural change is limited to where and how the nullable rebuild_lockfiles flag is resolved; public APIs unchanged aside from test/fixture additions and internal logging.

Walkthrough

Forward the raw nullable rebuild_lockfiles flag from the CLI into BumpOptions; resolve and log the effective value only inside bump._initialize_bump_context. Update docs and add tests (unit, integration, Hypothesis) plus snapshots to assert and observe lockfile-regeneration behaviour.

Changes

Centralise rebuild_lockfiles resolution to command layer

Layer / File(s) Summary
CLI forwarding and documentation
lading/cli.py, docs/developers-guide.md
Module docs and cli.bump now forward rebuild_lockfiles as `bool
CLI test contract updates
tests/unit/test_cli.py
Test expectations updated to verify the CLI forwards None as the default value; test renamed and clarified to assert forwarding semantics.
Test infrastructure and stubs
tests/unit/conftest.py
Added _LOCKFILE_STUB_MODULES allowlist and autouse fixture to prevent Cargo invocation during manifest-focused tests via monkeypatching regenerate_lockfiles.
Documentation and README tests
tests/unit/test_bump_documentation_updates.py, tests/unit/__snapshots__/test_bump_documentation_updates.ambr
New tests: TOML code-fence version rewriting in documentation and workspace README transposition to per-crate paths with optional exclusion and version checks; snapshot updated to reflect 1.2.3 examples.
Lockfile rebuild tests
tests/unit/test_bump_lockfile_rebuild.py, tests/unit/__snapshots__/test_bump_lockfile_rebuild.ambr
New module tests lockfile rebuild behaviour for enabled/disabled rebuilds, configuration inheritance, dry-run reporting, and skip scenarios; use monkeypatching to observe regeneration and update snapshots.
Rebuild lockfiles resolution verification
tests/unit/test_bump_rebuild_lockfiles_resolution.py
New module containing a unit test for _initialize_bump_context, an end-to-end public-API test that captures regeneration calls, and a Hypothesis property test covering all flag/config combinations; asserts DEBUG logging when the flag is None.
Test module reorganisation and manifest snapshots
tests/unit/test_bump_manifest_updates.py, tests/unit/__snapshots__/test_bump_manifest_updates.ambr
Removed README-transposition and lockfile-skip scaffolding from the manifest module, added helpers/dataclasses, tightened assertion messages, and updated manifest bump snapshots.
Bump command logging
lading/commands/bump.py
Add DEBUG log in _initialize_bump_context recording raw option, configured default and final resolved rebuild_lockfiles value.

Sequence Diagram

sequenceDiagram
  participant CLI as lading.cli
  participant BumpInit as lading.commands.bump._initialize_bump_context
  participant Config as configuration.bump
  CLI->>BumpInit: forward rebuild_lockfiles (bool | None)
  BumpInit->>Config: consult configuration.bump.rebuild_lockfiles when flag is None
  BumpInit->>BumpInit: resolve effective rebuild_lockfiles (bool)
  BumpInit->>bump.bump_lockfiles: call regenerate_lockfiles when resolved True
Loading

Possibly related PRs

  • leynos/lading#85: Both PRs modify the rebuild_lockfiles option plumbing for lading bump, with related wiring and test changes.

Poem

From CLI's hands to command's throne,
The nullable flag finds its home.
Resolve within the bump command’s light,
Tests stand guard through day and night,
One true source now rules the fight. 🏰

Summarise the changes for reviewers as a concise checklist highlighting docs, CLI wiring, command logging, test additions, and snapshot updates.
🚥 Pre-merge checks | ✅ 20
✅ Passed checks (20 passed)
Check name Status Explanation
Title check ✅ Passed Title directly references issue #106 and accurately summarises the main change: establishing a single source of truth for rebuild_lockfiles resolution.
Description check ✅ Passed Description comprehensively explains the changes (CLI forwarding, command-layer resolution, documentation updates) and testing approach, clearly aligned with the changeset.
Linked Issues check ✅ Passed All acceptance criteria from issue #106 are met: CLI forwards raw nullable flag [#106], resolution centralised in command layer [#106], parametrised matrix tests added [#106], and developers-guide.md documents responsibility ownership [#106].
Out of Scope Changes check ✅ Passed All changes directly support issue #106 objectives: CLI forwarding logic, command-layer resolution, documentation, and comprehensive parametrised matrix tests covering all specified combinations.
Docstring Coverage ✅ Passed Docstring coverage is 85.37% which is sufficient. The required threshold is 80.00%.
Testing (Overall) ✅ Passed New functionality guarded by rigorous, non-vacuous tests. White-box tests verify resolution logic directly (6 parametrised cases: flag∈{None,True,False}×configured∈{T,F}). Black-box tests observe b...
User-Facing Documentation ✅ Passed This PR is an internal refactoring that relocates rebuild_lockfiles resolution from the CLI layer to the command layer for single source of truth, with no user-facing behaviour changes. The `rebu...
Developer Documentation ✅ Passed Developer documentation fully updated: cli.py module docstring and developers-guide.md "Bump command internals" section document the architectural change (CLI forwards raw bool | None, command laye...
Module-Level Documentation ✅ Passed All eight modified/new Python modules carry clear module-level docstrings explaining purpose and utility; main modules document relationships adequately.
Testing (Unit And Behavioural) ✅ Passed Pull request provides comprehensive test coverage for rebuild_lockfiles resolution: 2 unit tests (6 parametrised cases + logging), 2 behavioural tests (6 parametrised cases + property test via Hypo...
Testing (Property / Proof) ✅ Passed Property-based test implemented with Hypothesis covering rebuild_lockfiles invariant across 3×2 flag/configuration matrix (30 examples); complemented by parametrised tests (6 white-box, 6 black-box...
Testing (Compile-Time / Ui) ✅ Passed PR correctly applies syrupy snapshot tests for text-based output from bump command operations (manifest updates, lockfile rebuild messages, documentation patches). Snapshots capture meaningful beha...
Unit Architecture ✅ Passed PR enforces single source of truth for rebuild_lockfiles resolution: CLI forwards raw bool | None (no coalescing); command layer owns None-to-bool resolution in _initialize_bump_context with explic...
Domain Architecture ✅ Passed Domain logic properly segregated: CLI adapter forwards nullable flag unresolved; command layer owns single-source-of-truth resolution in _initialize_bump_context; configuration injected appropriate...
Observability ✅ Passed Observability provided via DEBUG logging at the resolution decision point (rebuild_lockfiles coalescing) with appropriate contextual fields and comprehensive test coverage via caplog assertion.
Security And Privacy ✅ Passed PR introduces no secrets, unsafe deserialization, injection risks, permission issues, or sensitive data exposure; debug logging safely emits only booleans at DEBUG level.
Performance And Resource Use ✅ Passed PR introduces no algorithmic regressions, unbounded allocations, or hot-path blocking. Changes are O(1): CLI forwards raw bool|None (no resolution overhead), bump._initialize_bump_context uses sing...
Concurrency And State ✅ Passed PR introduces no concurrency, locks, async execution, shared mutable state, or ordering concerns. Changes are purely synchronous option resolution refactoring with proper test isolation via functio...
Architectural Complexity And Maintainability ✅ Passed PR reduces architectural complexity by establishing single source of truth for rebuild_lockfiles resolution. CLI now forwards raw bool|None; command layer resolves in _initialize_bump_context. All...
Rust Compiler Lint Integrity ✅ Passed PR contains zero Rust source file changes; modifications are Python, Markdown, and test snapshots only. Rust compiler lint integrity checks do not apply.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📋 Issue Planner

Built with CodeRabbit's Coding Plans for faster development and fewer bugs.

View plan used: #106

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-106-single-rebuild-lockfiles-resolution

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

@sourcery-ai

sourcery-ai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Reviewer's Guide

Centralizes resolution of the nullable rebuild_lockfiles option in the bump command layer by having the CLI forward the raw flag value, updates tests to cover the new resolution behavior, and documents the responsibility split between the CLI adapter and command layer.

Sequence diagram for rebuild_lockfiles resolution in bump command

sequenceDiagram
    actor User
    participant cli_bump as cli.bump
    participant bump_cmd as bump._initialize_bump_context
    participant Config as configuration.bump

    User->>cli_bump: bump(..., rebuild_lockfiles)
    cli_bump->>bump_cmd: BumpOptions(rebuild_lockfiles, configuration)
    alt [rebuild_lockfiles is None]
        bump_cmd->>Config: read rebuild_lockfiles
        bump_cmd-->>bump_cmd: use Config.rebuild_lockfiles
    else [rebuild_lockfiles is not None]
        bump_cmd-->>bump_cmd: use BumpOptions.rebuild_lockfiles
    end
Loading

Flow diagram for rebuild_lockfiles defaulting logic

flowchart TD
    A[Start bump._initialize_bump_context] --> B[Read BumpOptions.rebuild_lockfiles]
    B --> C{rebuild_lockfiles is None?}
    C -- Yes --> D[resolved = configuration.bump.rebuild_lockfiles]
    C -- No --> E[resolved = BumpOptions.rebuild_lockfiles]
    D --> F[Proceed with resolved value]
    E --> F[Proceed with resolved value]
Loading

File-Level Changes

Change Details Files
Have cli.bump forward rebuild_lockfiles as a raw nullable flag and delegate defaulting to the bump command context initialization.
  • Replace CLI-side coalescing of rebuild_lockfiles with direct forwarding of the nullable flag to BumpOptions.
  • Add an explanatory comment clarifying that configuration-based default resolution occurs in the bump command layer, not in the CLI adapter.
lading/cli.py
Add and adjust tests to validate rebuild_lockfiles resolution is owned by the bump command layer and that the CLI only forwards the raw flag.
  • Introduce a parametrized integration test that exercises rebuild_lockfiles resolution across combinations of CLI flag values and configuration.bump.rebuild_lockfiles.
  • Update the CLI bump test to assert raw forwarding semantics, including the case where Cyclopts hydrates the flag from lading.toml.
  • Rename the CLI test to reflect forwarding behavior instead of resolution logic and adjust expectations accordingly.
tests/unit/test_bump_command_integration.py
tests/unit/test_cli.py
Document the ownership of option defaulting and rebuild_lockfiles behavior in the developers guide.
  • Clarify that option defaulting is handled in the command layer rather than the CLI adapter.
  • Document that cli.bump forwards rebuild_lockfiles as a raw bool
None and that resolution against configuration.bump.rebuild_lockfiles occurs in bump._initialize_bump_context, with a note about possible Cyclopts hydration.

Assessment against linked issues

Issue Objective Addressed Explanation
#106 Ensure rebuild_lockfiles is resolved exactly once in the command layer: the CLI forwards the raw nullable flag and performs no default-resolution.
#106 Add tests that exercise rebuild_lockfiles resolution through the command layer for all combinations of flag ∈ {None, True, False} and configuration.bump.rebuild_lockfiles ∈ {True, False}, and update CLI tests to assert raw forwarding.
#106 Document in docs/developers-guide.md that option defaulting is the responsibility of the command layer, not the CLI adapter, including the behavior for rebuild_lockfiles.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
leynos marked this pull request as ready for review June 10, 2026 12:19
sourcery-ai[bot]

This comment was marked as resolved.

@coderabbitai coderabbitai Bot added the Issue label Jun 10, 2026
coderabbitai[bot]

This comment was marked as resolved.

Update the cli module docstring to describe the current forwarding
semantics: bump forwards rebuild_lockfiles as bool | None and the command
layer (_initialize_bump_context) owns coalescing against the configuration
default. Add a CLI test case asserting a Cyclopts-hydrated True is passed
through unchanged, matching the existing hydrated-false case.

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

leynos commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

lading/cli.py (1)

9-13: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win
Align the module docstring with raw forwarding behaviour.
Update this paragraph to match the current contract: bump now forwards

rebuild_lockfiles as bool | None, and command-layer initialisation performs

the only coalescing against configuration defaults.

🤖 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 @lading/cli.py around lines 9 - 13, Update the module docstring paragraph to
reflect the current forwarding semantics: state that the bump command now
forwards the rebuild_lockfiles parameter as bool | None (not coalesced to a
concrete bool) and that any coalescing against configuration defaults is
performed during command-layer initialization rather than here; reference the
bump command and the rebuild_lockfiles parameter so readers know which symbol
implements this raw forwarding behavior.

@leynos

leynos commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

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

## Individual Comments

### Comment 1
<location path="tests/unit/test_cli.py" line_range="467-474" />
<code_context>
     ("config_body", "extra_args", "expected"),
     [
-        pytest.param("", [], True, id="default"),
+        pytest.param("", [], None, id="default"),
+        # The False here is hydrated by the Cyclopts TOML loader
+        # (use_commands_as_keys=True), not by resolution logic in cli.bump.
         pytest.param(
             "[bump]\nrebuild_lockfiles = false\n",
             [],
             False,
-            id="configuration",
+            id="configuration-hydrated-by-cyclopts",
         ),
         pytest.param(
</code_context>
<issue_to_address>
**suggestion (testing):** Add a case for configuration.bump.rebuild_lockfiles=True hydrated by Cyclopts without CLI override

Right now the parametrization only covers: (1) no config → None, (2) config with `rebuild_lockfiles = false` → hydrated `False`, and (3/4) explicit CLI overrides. Please add a matching case where the TOML config has:

```toml
[bump]
rebuild_lockfiles = true
```

with no CLI flags, to verify that a Cyclopts-hydrated `True` is also passed through unchanged by `cli.bump`.
</issue_to_address>

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Tip

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
head -30 lading/cli.py

Length of output: 1261



@leynos Yes, this is resolved. The module docstring (lines 9–16) now reads:

The CLI resolves user-interface concerns here before crossing into command internals, but it does not coalesce optional flags against configuration defaults. For example, :func:bump forwards its rebuild_lockfiles parameter as bool | None exactly as received; the command layer (lading.commands.bump._initialize_bump_context) owns resolving an unset value against configuration.bump.rebuild_lockfiles. This keeps the nullable-to-concrete defaulting in a single place rather than splitting it across the CLI adapter and the command module.

That covers every requirement: the bool | None forwarding contract, the named symbol (rebuild_lockfiles), the authoritative resolution point, and the rationale. No further changes are needed.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Tip

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n "rebuild_lockfiles" tests/unit/test_cli.py -A 3 -B 3

Length of output: 1476


🏁 Script executed:

#!/bin/bash
# Find the review comment to resolve
gh api graphql -f query='
{
  repository(owner: "leynos", name: "lading") {
    pullRequest(number: 116) {
      reviewThreads(first: 50) {
        nodes {
          id
          isResolved
          comments(first: 1) {
            nodes {
              author { login }
              body
              path
              line
            }
          }
        }
      }
    }
  }
}' | jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.comments.nodes[0].author.login == "coderabbitai" and (.comments.nodes[0].path == "tests/unit/test_cli.py")) | {id, isResolved, path: .comments.nodes[0].path, line: .comments.nodes[0].line, body: (.comments.nodes[0].body | .[0:100])}'

Length of output: 978


🏁 Script executed:

#!/bin/bash
gh api graphql -f query='
{
  repository(owner: "leynos", name: "lading") {
    pullRequest(number: 116) {
      reviewThreads(first: 50) {
        nodes {
          id
          isResolved
          comments(first: 1) {
            nodes {
              author { login }
              path
              line
              body
            }
          }
        }
      }
    }
  }
}' | jq '.data.repository.pullRequest.reviewThreads.nodes[] | {id, isResolved, author: .comments.nodes[0].author.login, path: .comments.nodes[0].path, line: .comments.nodes[0].line, body: (.comments.nodes[0].body | .[0:120])}'

Length of output: 936



@leynos Yes, this is fully resolved. The thread is already marked as resolved on GitHub.

The test param has been added at lines 477–481 of tests/unit/test_cli.py:

pytest.param(
    "[bump]\nrebuild_lockfiles = true\n",
    [],
    True,
    id="configuration-hydrated-by-cyclopts-true",
),

This covers the missing matrix cell: TOML config with rebuild_lockfiles = true, no CLI flags, expecting a Cyclopts-hydrated True forwarded unchanged by cli.bump. ✓

…variant

Address review warnings that the resolution matrix only exercised the
private _initialize_bump_context helper and lacked property-based coverage.

- Add a parametrised behavioural test exercising bump.run() across
  rebuild_lockfiles in {None, True, False} x configuration in {True, False},
  observing the resolved value through whether lockfile regeneration runs.
- Add a Hypothesis property test asserting the single-source-of-truth
  invariant over the same input domain, building a fresh workspace per
  example since each run mutates manifests.
- Keep the white-box helper test as the direct field-level counterpart and
  cross-reference the two.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response.

tests/unit/test_bump_command_integration.py

Comment on file

import dataclasses as dc
import pathlib
import tempfile

❌ New issue: Low Cohesion
This module has at least 16 different responsibilities amongst its 23 functions, threshold = 4

@coderabbitai

This comment was marked as resolved.

@leynos

leynos commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

Resolve the CodeScene low-cohesion finding (16 responsibilities across 23
functions) for tests/unit/test_bump_command_integration.py by splitting it
into four focused modules:

- test_bump_manifest_updates.py     - manifest version/dependency updates
- test_bump_lockfile_rebuild.py     - lockfile rebuild behaviour
- test_bump_rebuild_lockfiles_resolution.py - issue #106 resolution matrix
- test_bump_documentation_updates.py - README/doc transposition

Promote the shared stub_lockfile_regeneration fixture to tests/unit/conftest.py
as an autouse fixture. It is scoped by module name to the four bump-run split
modules so it never shadows test_bump_lockfiles, which exercises
regenerate_lockfiles directly and needs the real implementation. Test logic,
assertions, parametrisation, and the fixture body are unchanged; the full unit
suite still reports 569 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
codescene-delta-analysis[bot]

This comment was marked as outdated.

@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: 5

Caution

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

⚠️ Outside diff range comments (3)
tests/unit/conftest.py (1)

1-1: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the module docstring to reflect bump fixtures.

The docstring still says "Shared fixtures and helpers for publish unit tests" but the module now includes bump-related fixtures (stub_lockfile_regeneration, _LOCKFILE_STUB_MODULES). Update it to acknowledge both publish and bump fixtures.

📝 Proposed fix
-"""Shared fixtures and helpers for publish unit tests."""
+"""Shared fixtures and helpers for publish and bump unit tests."""
🤖 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/unit/conftest.py` at line 1, Update the module docstring at the top of
tests/unit/conftest.py to mention both publish and bump fixtures: change the
existing "Shared fixtures and helpers for publish unit tests." to a brief
description that includes bump-related fixtures (e.g., reference
stub_lockfile_regeneration and _LOCKFILE_STUB_MODULES) so the docstring
accurately reflects that the module provides fixtures/helpers for both publish
and bump tests.
tests/unit/test_bump_documentation_updates.py (1)

65-96: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add explanatory messages to assertions.

Lines 86, 87, 88-90, 92-95 use bare assertions. Provide failure messages to clarify test intent and improve debuggability.

✏️ Proposed fix
     crate_readme = tmp_path / "crates" / "alpha" / "README.md"
-    assert "readme file(s)" in message
-    assert "- crates/alpha/README.md (readme)" in message.splitlines()
-    assert crate_readme.read_text(encoding="utf-8") == (
+    assert "readme file(s)" in message, "bump output should report readme transposition"
+    assert "- crates/alpha/README.md (readme)" in message.splitlines(), (
+        "transposed README path should appear in output"
+    )
+    assert crate_readme.read_text(encoding="utf-8") == (
         "# Sample\n\nSee [Guide](../../docs/guide.md).\n"
-    )
+    ), "transposed README should rewrite relative paths from workspace root"
     if scenario.check_version_unchanged:
-        assert (
+        assert (
             _load_version(tmp_path / "crates" / "alpha" / "Cargo.toml", ("package",))
             == "0.1.0"
-        )
+        ), "excluded crate version should remain unchanged at 0.1.0"
🤖 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/unit/test_bump_documentation_updates.py` around lines 65 - 96, The test
test_run_transposes_workspace_readme_to_crates uses bare assertions which makes
failures unclear; update each assertion to include an explanatory failure
message. Specifically, for the assertions checking contents of message ("readme
file(s)"), presence of the "- crates/alpha/README.md (readme)" line, the
crate_readme content equality, and the version equality check that uses
_load_version, add concise messages describing the expected condition (e.g.,
"expected bump.run message to mention readme file(s)", "expected crate README
path entry in bump output", "expected crate README to rewrite relative links",
"expected crate version to remain 0.1.0 when version unchanged") so failures
point directly at the intent in test_run_transposes_workspace_readme_to_crates
and the helpers bump.run and _load_version.

Source: Coding guidelines

tests/unit/test_bump_manifest_updates.py (1)

209-361: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add explanatory messages to assertions.

Lines 253, 281-288, 332 use bare assertions. Provide failure messages to clarify test expectations and improve debuggability. As per coding guidelines, use assert …, "message" over bare asserts.

✏️ Example fix for lines 281-288
-    assert message.splitlines() == [
+    assert message.splitlines() == [
         "Dry run; would update version to 1.2.3 in 3 manifest(s):",
         "- Cargo.toml",
         "- crates/alpha/Cargo.toml",
         "- crates/beta/Cargo.toml",
-    ]
+    ], "dry-run output should list manifests that would be updated"
     for path in manifest_paths:
-        assert path.read_text(encoding="utf-8") == original_contents[path]
+        assert path.read_text(encoding="utf-8") == original_contents[path], (
+            f"dry-run should not modify {path.relative_to(tmp_path)}"
+        )
🤖 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/unit/test_bump_manifest_updates.py` around lines 209 - 361, Add
explicit failure messages to the bare assertions in the listed tests: in
test_run_reports_when_versions_already_match update the assertion "assert
message == scenario.expected_message" to include a message referencing
scenario.test_id and both expected vs actual; in
test_run_dry_run_reports_changes_without_modifying_files add messages to the
list-equality assertion on message.splitlines() and to the loop assertion that
compares path.read_text() with original_contents[path] (include the manifest
path and expected vs actual content); in
test_run_updates_workspace_dependency_sections change "assert actual_version ==
expected_version" to include the section name, manifest path and the actual vs
expected version; and in test_run_updates_workspace_dependency_prefixes add
messages to the three asserts that check alpha value, beta_entry["version"], and
beta_entry["path"] to show which field failed and the expected vs actual values.
Ensure each assert uses the comma-form "assert <cond>, <message>" and reference
the local variables message, original_contents, actual_version,
expected_version, document, and beta_entry to construct informative messages.

Source: Coding guidelines

🤖 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/unit/conftest.py`:
- Around line 18-26: Update the comment above _LOCKFILE_STUB_MODULES to
explicitly state that these specific test modules are allowlisted because they
invoke bump.run to exercise manifest updates or dependency resolution logic
without requiring Cargo to actually build or regenerate lockfiles, so the stub
prevents shelling out to Cargo while still allowing test_bump_lockfiles to use
the real regenerate_lockfiles implementation; mention the intent to scope the
stub by module name to avoid shadowing test_bump_lockfiles and clarify that the
listed tests focus on manifest/resolution behavior rather than lockfile
generation mechanics.

In `@tests/unit/test_bump_documentation_updates.py`:
- Around line 29-49: The three bare assertions in
test_run_updates_documentation_snippets (the asserts checking "documentation
file(s)" in message, "- README.md (documentation)" in message.splitlines(), and
'alpha = "1.2.3"' in updated_readme) should include descriptive failure
messages; update each assert to provide a helpful message explaining what was
expected and include the actual value (e.g., message or updated_readme) to aid
debugging when the test fails. Ensure you modify the assertions in the
test_run_updates_documentation_snippets function to use the form assert
<condition>, "<descriptive failure message with relevant variable
interpolation>" referencing the variables message and updated_readme.

In `@tests/unit/test_bump_lockfile_rebuild.py`:
- Around line 30-102: The test combines both enabled and disabled
rebuild_lockfiles behavior in test_run_rebuilds_lockfiles_by_default; split it
into two focused tests named test_run_rebuilds_lockfiles_when_enabled and
test_run_skips_lockfiles_when_disabled. For the enabled test keep the
fake_regenerate_lockfiles spy, monkeypatch
bump.bump_lockfiles.regenerate_lockfiles, call bump.run with
BumpOptions(rebuild_lockfiles=True, ...), and assert the captured calls, message
contents and lockfile lines; for the disabled test monkeypatch
regenerate_lockfiles to pytest.fail, call bump.run with
BumpOptions(rebuild_lockfiles=False, ...), and assert that the message does not
mention "lockfile". Ensure to move shared setup (tmp_path workspace/config
helpers) into each test or a small fixture and update the original test name
removal.

In `@tests/unit/test_bump_manifest_updates.py`:
- Around line 91-207: Several tests use bare assertions; update the assertion
calls to include explanatory failure messages. In
test_run_skips_excluded_crates, add messages to the three asserts that call
_load_version to indicate which crate/version check failed; in
test_run_updates_internal_dependency_versions, add messages to the assertions
checking dependency_version, dev_entry fields and build_entry fields returned by
_extract_alpha_dependency_entries to describe expected updated versions/paths;
in test_run_updates_renamed_internal_dependency_versions add a message to each
assert that inspects dependency_entry from
parse_toml(beta_manifest.read_text(...)) to state the expected version and
package; and in test_run_normalises_workspace_root and
test_run_uses_loaded_configuration_and_workspace add messages to their single
asserts referencing _load_version to clarify expected workspace package
versions. For each change, keep the same assertion expressions but pass a final
string argument that clearly describes the expectation (e.g., "expected
workspace package version X but got Y" or "expected dependency 'alpha-core'
version '^2.3.4'").
- Around line 51-89: The tests use several bare assertions in
test_run_updates_workspace_and_members (asserting message.splitlines() equals
expected list, the workspace manifest version via _load_version(tmp_path /
"Cargo.toml", ("workspace", "package")), and each crate version inside the for
loop) and in test_run_updates_root_package_section (asserting
_load_version(manifest_path, ("package",)) and _load_version(manifest_path,
("workspace", "package"))). Replace those bare asserts with assertions that
include helpful failure messages (e.g., assert message.splitlines() == expected,
f"Unexpected bump output: {message!r}" and assert _load_version(...) == "x.y.z",
f"Expected version x.y.z in <manifest identifier> but found
{_load_version(...)}"), and likewise in the loop include the crate.manifest_path
in the message to identify which crate failed.

---

Outside diff comments:
In `@tests/unit/conftest.py`:
- Line 1: Update the module docstring at the top of tests/unit/conftest.py to
mention both publish and bump fixtures: change the existing "Shared fixtures and
helpers for publish unit tests." to a brief description that includes
bump-related fixtures (e.g., reference stub_lockfile_regeneration and
_LOCKFILE_STUB_MODULES) so the docstring accurately reflects that the module
provides fixtures/helpers for both publish and bump tests.

In `@tests/unit/test_bump_documentation_updates.py`:
- Around line 65-96: The test test_run_transposes_workspace_readme_to_crates
uses bare assertions which makes failures unclear; update each assertion to
include an explanatory failure message. Specifically, for the assertions
checking contents of message ("readme file(s)"), presence of the "-
crates/alpha/README.md (readme)" line, the crate_readme content equality, and
the version equality check that uses _load_version, add concise messages
describing the expected condition (e.g., "expected bump.run message to mention
readme file(s)", "expected crate README path entry in bump output", "expected
crate README to rewrite relative links", "expected crate version to remain 0.1.0
when version unchanged") so failures point directly at the intent in
test_run_transposes_workspace_readme_to_crates and the helpers bump.run and
_load_version.

In `@tests/unit/test_bump_manifest_updates.py`:
- Around line 209-361: Add explicit failure messages to the bare assertions in
the listed tests: in test_run_reports_when_versions_already_match update the
assertion "assert message == scenario.expected_message" to include a message
referencing scenario.test_id and both expected vs actual; in
test_run_dry_run_reports_changes_without_modifying_files add messages to the
list-equality assertion on message.splitlines() and to the loop assertion that
compares path.read_text() with original_contents[path] (include the manifest
path and expected vs actual content); in
test_run_updates_workspace_dependency_sections change "assert actual_version ==
expected_version" to include the section name, manifest path and the actual vs
expected version; and in test_run_updates_workspace_dependency_prefixes add
messages to the three asserts that check alpha value, beta_entry["version"], and
beta_entry["path"] to show which field failed and the expected vs actual values.
Ensure each assert uses the comma-form "assert <cond>, <message>" and reference
the local variables message, original_contents, actual_version,
expected_version, document, and beta_entry to construct informative messages.
🪄 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: e3e55ad4-21e4-4fb6-ad85-a727774f23d9

📥 Commits

Reviewing files that changed from the base of the PR and between c54cb2d and 0842588.

📒 Files selected for processing (5)
  • tests/unit/conftest.py
  • tests/unit/test_bump_documentation_updates.py
  • tests/unit/test_bump_lockfile_rebuild.py
  • tests/unit/test_bump_manifest_updates.py
  • tests/unit/test_bump_rebuild_lockfiles_resolution.py

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 5

Caution

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

⚠️ Outside diff range comments (3)
tests/unit/conftest.py (1)

1-1: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the module docstring to reflect bump fixtures.

The docstring still says "Shared fixtures and helpers for publish unit tests" but the module now includes bump-related fixtures (stub_lockfile_regeneration, _LOCKFILE_STUB_MODULES). Update it to acknowledge both publish and bump fixtures.

📝 Proposed fix
-"""Shared fixtures and helpers for publish unit tests."""
+"""Shared fixtures and helpers for publish and bump unit tests."""
🤖 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/unit/conftest.py` at line 1, Update the module docstring at the top of
tests/unit/conftest.py to mention both publish and bump fixtures: change the
existing "Shared fixtures and helpers for publish unit tests." to a brief
description that includes bump-related fixtures (e.g., reference
stub_lockfile_regeneration and _LOCKFILE_STUB_MODULES) so the docstring
accurately reflects that the module provides fixtures/helpers for both publish
and bump tests.
tests/unit/test_bump_documentation_updates.py (1)

65-96: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add explanatory messages to assertions.

Lines 86, 87, 88-90, 92-95 use bare assertions. Provide failure messages to clarify test intent and improve debuggability.

✏️ Proposed fix
     crate_readme = tmp_path / "crates" / "alpha" / "README.md"
-    assert "readme file(s)" in message
-    assert "- crates/alpha/README.md (readme)" in message.splitlines()
-    assert crate_readme.read_text(encoding="utf-8") == (
+    assert "readme file(s)" in message, "bump output should report readme transposition"
+    assert "- crates/alpha/README.md (readme)" in message.splitlines(), (
+        "transposed README path should appear in output"
+    )
+    assert crate_readme.read_text(encoding="utf-8") == (
         "# Sample\n\nSee [Guide](../../docs/guide.md).\n"
-    )
+    ), "transposed README should rewrite relative paths from workspace root"
     if scenario.check_version_unchanged:
-        assert (
+        assert (
             _load_version(tmp_path / "crates" / "alpha" / "Cargo.toml", ("package",))
             == "0.1.0"
-        )
+        ), "excluded crate version should remain unchanged at 0.1.0"
🤖 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/unit/test_bump_documentation_updates.py` around lines 65 - 96, The test
test_run_transposes_workspace_readme_to_crates uses bare assertions which makes
failures unclear; update each assertion to include an explanatory failure
message. Specifically, for the assertions checking contents of message ("readme
file(s)"), presence of the "- crates/alpha/README.md (readme)" line, the
crate_readme content equality, and the version equality check that uses
_load_version, add concise messages describing the expected condition (e.g.,
"expected bump.run message to mention readme file(s)", "expected crate README
path entry in bump output", "expected crate README to rewrite relative links",
"expected crate version to remain 0.1.0 when version unchanged") so failures
point directly at the intent in test_run_transposes_workspace_readme_to_crates
and the helpers bump.run and _load_version.

Source: Coding guidelines

tests/unit/test_bump_manifest_updates.py (1)

209-361: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add explanatory messages to assertions.

Lines 253, 281-288, 332 use bare assertions. Provide failure messages to clarify test expectations and improve debuggability. As per coding guidelines, use assert …, "message" over bare asserts.

✏️ Example fix for lines 281-288
-    assert message.splitlines() == [
+    assert message.splitlines() == [
         "Dry run; would update version to 1.2.3 in 3 manifest(s):",
         "- Cargo.toml",
         "- crates/alpha/Cargo.toml",
         "- crates/beta/Cargo.toml",
-    ]
+    ], "dry-run output should list manifests that would be updated"
     for path in manifest_paths:
-        assert path.read_text(encoding="utf-8") == original_contents[path]
+        assert path.read_text(encoding="utf-8") == original_contents[path], (
+            f"dry-run should not modify {path.relative_to(tmp_path)}"
+        )
🤖 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/unit/test_bump_manifest_updates.py` around lines 209 - 361, Add
explicit failure messages to the bare assertions in the listed tests: in
test_run_reports_when_versions_already_match update the assertion "assert
message == scenario.expected_message" to include a message referencing
scenario.test_id and both expected vs actual; in
test_run_dry_run_reports_changes_without_modifying_files add messages to the
list-equality assertion on message.splitlines() and to the loop assertion that
compares path.read_text() with original_contents[path] (include the manifest
path and expected vs actual content); in
test_run_updates_workspace_dependency_sections change "assert actual_version ==
expected_version" to include the section name, manifest path and the actual vs
expected version; and in test_run_updates_workspace_dependency_prefixes add
messages to the three asserts that check alpha value, beta_entry["version"], and
beta_entry["path"] to show which field failed and the expected vs actual values.
Ensure each assert uses the comma-form "assert <cond>, <message>" and reference
the local variables message, original_contents, actual_version,
expected_version, document, and beta_entry to construct informative messages.

Source: Coding guidelines

🤖 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/unit/conftest.py`:
- Around line 18-26: Update the comment above _LOCKFILE_STUB_MODULES to
explicitly state that these specific test modules are allowlisted because they
invoke bump.run to exercise manifest updates or dependency resolution logic
without requiring Cargo to actually build or regenerate lockfiles, so the stub
prevents shelling out to Cargo while still allowing test_bump_lockfiles to use
the real regenerate_lockfiles implementation; mention the intent to scope the
stub by module name to avoid shadowing test_bump_lockfiles and clarify that the
listed tests focus on manifest/resolution behavior rather than lockfile
generation mechanics.

In `@tests/unit/test_bump_documentation_updates.py`:
- Around line 29-49: The three bare assertions in
test_run_updates_documentation_snippets (the asserts checking "documentation
file(s)" in message, "- README.md (documentation)" in message.splitlines(), and
'alpha = "1.2.3"' in updated_readme) should include descriptive failure
messages; update each assert to provide a helpful message explaining what was
expected and include the actual value (e.g., message or updated_readme) to aid
debugging when the test fails. Ensure you modify the assertions in the
test_run_updates_documentation_snippets function to use the form assert
<condition>, "<descriptive failure message with relevant variable
interpolation>" referencing the variables message and updated_readme.

In `@tests/unit/test_bump_lockfile_rebuild.py`:
- Around line 30-102: The test combines both enabled and disabled
rebuild_lockfiles behavior in test_run_rebuilds_lockfiles_by_default; split it
into two focused tests named test_run_rebuilds_lockfiles_when_enabled and
test_run_skips_lockfiles_when_disabled. For the enabled test keep the
fake_regenerate_lockfiles spy, monkeypatch
bump.bump_lockfiles.regenerate_lockfiles, call bump.run with
BumpOptions(rebuild_lockfiles=True, ...), and assert the captured calls, message
contents and lockfile lines; for the disabled test monkeypatch
regenerate_lockfiles to pytest.fail, call bump.run with
BumpOptions(rebuild_lockfiles=False, ...), and assert that the message does not
mention "lockfile". Ensure to move shared setup (tmp_path workspace/config
helpers) into each test or a small fixture and update the original test name
removal.

In `@tests/unit/test_bump_manifest_updates.py`:
- Around line 91-207: Several tests use bare assertions; update the assertion
calls to include explanatory failure messages. In
test_run_skips_excluded_crates, add messages to the three asserts that call
_load_version to indicate which crate/version check failed; in
test_run_updates_internal_dependency_versions, add messages to the assertions
checking dependency_version, dev_entry fields and build_entry fields returned by
_extract_alpha_dependency_entries to describe expected updated versions/paths;
in test_run_updates_renamed_internal_dependency_versions add a message to each
assert that inspects dependency_entry from
parse_toml(beta_manifest.read_text(...)) to state the expected version and
package; and in test_run_normalises_workspace_root and
test_run_uses_loaded_configuration_and_workspace add messages to their single
asserts referencing _load_version to clarify expected workspace package
versions. For each change, keep the same assertion expressions but pass a final
string argument that clearly describes the expectation (e.g., "expected
workspace package version X but got Y" or "expected dependency 'alpha-core'
version '^2.3.4'").
- Around line 51-89: The tests use several bare assertions in
test_run_updates_workspace_and_members (asserting message.splitlines() equals
expected list, the workspace manifest version via _load_version(tmp_path /
"Cargo.toml", ("workspace", "package")), and each crate version inside the for
loop) and in test_run_updates_root_package_section (asserting
_load_version(manifest_path, ("package",)) and _load_version(manifest_path,
("workspace", "package"))). Replace those bare asserts with assertions that
include helpful failure messages (e.g., assert message.splitlines() == expected,
f"Unexpected bump output: {message!r}" and assert _load_version(...) == "x.y.z",
f"Expected version x.y.z in <manifest identifier> but found
{_load_version(...)}"), and likewise in the loop include the crate.manifest_path
in the message to identify which crate failed.

---

Outside diff comments:
In `@tests/unit/conftest.py`:
- Line 1: Update the module docstring at the top of tests/unit/conftest.py to
mention both publish and bump fixtures: change the existing "Shared fixtures and
helpers for publish unit tests." to a brief description that includes
bump-related fixtures (e.g., reference stub_lockfile_regeneration and
_LOCKFILE_STUB_MODULES) so the docstring accurately reflects that the module
provides fixtures/helpers for both publish and bump tests.

In `@tests/unit/test_bump_documentation_updates.py`:
- Around line 65-96: The test test_run_transposes_workspace_readme_to_crates
uses bare assertions which makes failures unclear; update each assertion to
include an explanatory failure message. Specifically, for the assertions
checking contents of message ("readme file(s)"), presence of the "-
crates/alpha/README.md (readme)" line, the crate_readme content equality, and
the version equality check that uses _load_version, add concise messages
describing the expected condition (e.g., "expected bump.run message to mention
readme file(s)", "expected crate README path entry in bump output", "expected
crate README to rewrite relative links", "expected crate version to remain 0.1.0
when version unchanged") so failures point directly at the intent in
test_run_transposes_workspace_readme_to_crates and the helpers bump.run and
_load_version.

In `@tests/unit/test_bump_manifest_updates.py`:
- Around line 209-361: Add explicit failure messages to the bare assertions in
the listed tests: in test_run_reports_when_versions_already_match update the
assertion "assert message == scenario.expected_message" to include a message
referencing scenario.test_id and both expected vs actual; in
test_run_dry_run_reports_changes_without_modifying_files add messages to the
list-equality assertion on message.splitlines() and to the loop assertion that
compares path.read_text() with original_contents[path] (include the manifest
path and expected vs actual content); in
test_run_updates_workspace_dependency_sections change "assert actual_version ==
expected_version" to include the section name, manifest path and the actual vs
expected version; and in test_run_updates_workspace_dependency_prefixes add
messages to the three asserts that check alpha value, beta_entry["version"], and
beta_entry["path"] to show which field failed and the expected vs actual values.
Ensure each assert uses the comma-form "assert <cond>, <message>" and reference
the local variables message, original_contents, actual_version,
expected_version, document, and beta_entry to construct informative messages.
🪄 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: e3e55ad4-21e4-4fb6-ad85-a727774f23d9

📥 Commits

Reviewing files that changed from the base of the PR and between c54cb2d and 0842588.

📒 Files selected for processing (5)
  • tests/unit/conftest.py
  • tests/unit/test_bump_documentation_updates.py
  • tests/unit/test_bump_lockfile_rebuild.py
  • tests/unit/test_bump_manifest_updates.py
  • tests/unit/test_bump_rebuild_lockfiles_resolution.py
🛑 Comments failed to post (5)
tests/unit/conftest.py (1)

18-26: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Clarify the allowlist rationale.

The comment explains that the stub is scoped to avoid shadowing test_bump_lockfiles, which needs the real implementation. Strengthen the explanation by explicitly stating why those specific modules are allowlisted—they exercise bump.run without needing actual Cargo invocation because they focus on manifest or resolution logic rather than lockfile generation mechanics.

✨ Example clarification
 # Modules whose ``bump.run`` exercises must not shell out to Cargo. The stub is
-# scoped to these by name so it never shadows ``test_bump_lockfiles``, which
-# exercises ``regenerate_lockfiles`` directly and needs the real implementation.
+# scoped to these by name because they test manifest updates, documentation, or
+# resolution logic without requiring actual lockfile regeneration. The stub never
+# shadows ``test_bump_lockfiles``, which exercises ``regenerate_lockfiles``
+# directly and needs the real implementation.
 _LOCKFILE_STUB_MODULES = frozenset({
🤖 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/unit/conftest.py` around lines 18 - 26, Update the comment above
_LOCKFILE_STUB_MODULES to explicitly state that these specific test modules are
allowlisted because they invoke bump.run to exercise manifest updates or
dependency resolution logic without requiring Cargo to actually build or
regenerate lockfiles, so the stub prevents shelling out to Cargo while still
allowing test_bump_lockfiles to use the real regenerate_lockfiles
implementation; mention the intent to scope the stub by module name to avoid
shadowing test_bump_lockfiles and clarify that the listed tests focus on
manifest/resolution behavior rather than lockfile generation mechanics.
tests/unit/test_bump_documentation_updates.py (1)

29-49: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add explanatory messages to assertions.

Lines 45, 46, and 48 use bare assertions. Provide failure messages to aid debugging when tests fail.

✏️ Proposed fix
-    assert "documentation file(s)" in message
-    assert "- README.md (documentation)" in message.splitlines()
+    assert "documentation file(s)" in message, "bump output should report documentation updates"
+    assert "- README.md (documentation)" in message.splitlines(), "README.md should appear in output"
     updated_readme = readme_path.read_text(encoding="utf-8")
-    assert 'alpha = "1.2.3"' in updated_readme
+    assert 'alpha = "1.2.3"' in updated_readme, "TOML fence version should be rewritten to 1.2.3"
🤖 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/unit/test_bump_documentation_updates.py` around lines 29 - 49, The
three bare assertions in test_run_updates_documentation_snippets (the asserts
checking "documentation file(s)" in message, "- README.md (documentation)" in
message.splitlines(), and 'alpha = "1.2.3"' in updated_readme) should include
descriptive failure messages; update each assert to provide a helpful message
explaining what was expected and include the actual value (e.g., message or
updated_readme) to aid debugging when the test fails. Ensure you modify the
assertions in the test_run_updates_documentation_snippets function to use the
form assert <condition>, "<descriptive failure message with relevant variable
interpolation>" referencing the variables message and updated_readme.

Source: Coding guidelines

tests/unit/test_bump_lockfile_rebuild.py (1)

30-102: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Split the enabled and disabled cases into separate tests.

This test exercises both rebuild_lockfiles=True (lines 30-79) and rebuild_lockfiles=False (lines 81-102) in a single function. Per the single-responsibility principle, split these into test_run_rebuilds_lockfiles_when_enabled and test_run_skips_lockfiles_when_disabled. Each test would have a clearer focus and simpler assertion logic.

♻️ Proposed split
 def test_run_rebuilds_lockfiles_by_default(
     tmp_path: pathlib.Path,
     monkeypatch: MonkeyPatch,
 ) -> None:
-    """Verify regenerate_lockfiles calls.
+    """Lockfile regeneration is called when explicitly enabled."""
-
-    Lockfile regeneration is called when enabled and suppressed when disabled.
-    """
     workspace = _make_workspace(tmp_path)
     configuration = _make_config()
     nested_lockfile = tmp_path / "crates/ui/Cargo.lock"
     captured: dict[str, object] = {}
 
     def fake_regenerate_lockfiles(
         workspace_root: pathlib.Path,
         lockfile_manifests: tuple[str, ...],
         *,
         runner: object | None = None,
     ) -> tuple[pathlib.Path, ...]:
         captured["calls"] = int(captured.get("calls", 0)) + 1
         captured["workspace_root"] = workspace_root
         captured["lockfile_manifests"] = lockfile_manifests
         captured["runner"] = runner
         return (tmp_path / "Cargo.lock", nested_lockfile)
 
     monkeypatch.setattr(
         bump.bump_lockfiles,
         "regenerate_lockfiles",
         fake_regenerate_lockfiles,
     )
 
     message = bump.run(
         tmp_path,
         "1.2.3",
         options=bump.BumpOptions(
             rebuild_lockfiles=True,
             configuration=configuration,
             workspace=workspace,
         ),
     )
 
     assert captured == {
         "calls": 1,
         "workspace_root": tmp_path,
         "lockfile_manifests": (),
         "runner": None,
     }
     assert "2 lockfile(s)" in message
     assert "- Cargo.lock (lockfile)" in message.splitlines()
     assert "- crates/ui/Cargo.lock (lockfile)" in message.splitlines()
+
+
+def test_run_skips_lockfiles_when_disabled(
+    tmp_path: pathlib.Path,
+    monkeypatch: MonkeyPatch,
+) -> None:
+    """Lockfile regeneration is suppressed when explicitly disabled."""
+    workspace = _make_workspace(tmp_path)
+    configuration = _make_config()
 
-    disabled_root = tmp_path / "disabled"
-    disabled_workspace = _make_workspace(disabled_root)
-    disabled_configuration = _make_config()
     monkeypatch.setattr(
         bump.bump_lockfiles,
         "regenerate_lockfiles",
         lambda *args, **kwargs: pytest.fail(
             "regenerate_lockfiles must not be called when rebuild_lockfiles=False"
         ),
     )
 
     message = bump.run(
-        disabled_root,
+        tmp_path,
         "1.2.3",
         options=bump.BumpOptions(
             rebuild_lockfiles=False,
-            configuration=disabled_configuration,
-            workspace=disabled_workspace,
+            configuration=configuration,
+            workspace=workspace,
         ),
     )
 
     assert "lockfile" not in message
🤖 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/unit/test_bump_lockfile_rebuild.py` around lines 30 - 102, The test
combines both enabled and disabled rebuild_lockfiles behavior in
test_run_rebuilds_lockfiles_by_default; split it into two focused tests named
test_run_rebuilds_lockfiles_when_enabled and
test_run_skips_lockfiles_when_disabled. For the enabled test keep the
fake_regenerate_lockfiles spy, monkeypatch
bump.bump_lockfiles.regenerate_lockfiles, call bump.run with
BumpOptions(rebuild_lockfiles=True, ...), and assert the captured calls, message
contents and lockfile lines; for the disabled test monkeypatch
regenerate_lockfiles to pytest.fail, call bump.run with
BumpOptions(rebuild_lockfiles=False, ...), and assert that the message does not
mention "lockfile". Ensure to move shared setup (tmp_path workspace/config
helpers) into each test or a small fixture and update the original test name
removal.
tests/unit/test_bump_manifest_updates.py (2)

51-89: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add explanatory messages to assertions.

Lines 57-65, 63, 65, 87-88 use bare assertions. Provide failure messages to aid debugging when tests fail. As per coding guidelines, use assert …, "message" over bare asserts.

✏️ Example fix for lines 57-65
-    assert message.splitlines() == [
+    assert message.splitlines() == [
         "Updated version to 1.2.3 in 3 manifest(s):",
         "- Cargo.toml",
         "- crates/alpha/Cargo.toml",
         "- crates/beta/Cargo.toml",
-    ]
-    assert _load_version(tmp_path / "Cargo.toml", ("workspace", "package")) == "1.2.3"
+    ], "bump output should list all updated manifests"
+    assert _load_version(tmp_path / "Cargo.toml", ("workspace", "package")) == "1.2.3", (
+        "workspace package version should be updated to 1.2.3"
+    )
     for crate in workspace.crates:
-        assert _load_version(crate.manifest_path, ("package",)) == "1.2.3"
+        assert _load_version(crate.manifest_path, ("package",)) == "1.2.3", (
+            f"crate {crate.name} version should be updated to 1.2.3"
+        )
🤖 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/unit/test_bump_manifest_updates.py` around lines 51 - 89, The tests use
several bare assertions in test_run_updates_workspace_and_members (asserting
message.splitlines() equals expected list, the workspace manifest version via
_load_version(tmp_path / "Cargo.toml", ("workspace", "package")), and each crate
version inside the for loop) and in test_run_updates_root_package_section
(asserting _load_version(manifest_path, ("package",)) and
_load_version(manifest_path, ("workspace", "package"))). Replace those bare
asserts with assertions that include helpful failure messages (e.g., assert
message.splitlines() == expected, f"Unexpected bump output: {message!r}" and
assert _load_version(...) == "x.y.z", f"Expected version x.y.z in <manifest
identifier> but found {_load_version(...)}"), and likewise in the loop include
the crate.manifest_path in the message to identify which crate failed.

Source: Coding guidelines


91-207: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add explanatory messages to assertions.

Lines 101-104, 132-136, 175-176, 194, 206 use bare assertions. Provide failure messages to clarify test expectations and improve debuggability.

🤖 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/unit/test_bump_manifest_updates.py` around lines 91 - 207, Several
tests use bare assertions; update the assertion calls to include explanatory
failure messages. In test_run_skips_excluded_crates, add messages to the three
asserts that call _load_version to indicate which crate/version check failed; in
test_run_updates_internal_dependency_versions, add messages to the assertions
checking dependency_version, dev_entry fields and build_entry fields returned by
_extract_alpha_dependency_entries to describe expected updated versions/paths;
in test_run_updates_renamed_internal_dependency_versions add a message to each
assert that inspects dependency_entry from
parse_toml(beta_manifest.read_text(...)) to state the expected version and
package; and in test_run_normalises_workspace_root and
test_run_uses_loaded_configuration_and_workspace add messages to their single
asserts referencing _load_version to clarify expected workspace package
versions. For each change, keep the same assertion expressions but pass a final
string argument that clearly describes the expectation (e.g., "expected
workspace package version X but got Y" or "expected dependency 'alpha-core'
version '^2.3.4'").

Source: Coding guidelines

@leynos

leynos commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

Address review feedback on the bump test split:

- Expand the tests/unit/conftest.py module docstring and the
  _LOCKFILE_STUB_MODULES comment to explain that the listed modules drive
  bump.run for manifest, documentation, and rebuild_lockfiles-resolution
  behaviour without needing Cargo, and that the stub is scoped by module name
  so it never shadows test_bump_lockfiles, which exercises the real
  regenerate_lockfiles.
- Split the misleadingly named test_run_rebuilds_lockfiles_by_default (it
  tested both explicit enable and disable) into
  test_run_rebuilds_lockfiles_when_enabled and
  test_run_skips_lockfiles_when_disabled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
codescene-delta-analysis[bot]

This comment was marked as outdated.

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

🤖 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/unit/test_bump_documentation_updates.py`:
- Around line 86-95: The assertions in
tests/unit/test_bump_documentation_updates.py lack descriptive messages; update
each assert that references message, crate_readme.read_text(...), and the
_load_version(...) check (used with tmp_path, scenario) to include a clear
failure message string explaining expected vs actual (e.g., "expected 'readme
file(s)' in message", "expected README contents to equal ...", "expected version
to remain 0.1.0"). Modify the asserts on message (both contains and splitlines
checks), the crate_readme.read_text(...) equality, and the conditional
_load_version(...) equality to pass a third parameter (the assertion message) so
test failures show meaningful context.
- Around line 45-48: Each bare assert should include a concise failure message:
update the four assertions using the variables shown (message, updated_readme,
readme_path) to include descriptive strings—for example, assert "documentation
file(s)" in message, "expected summary mentioning documentation file(s) in
message"; assert "- README.md (documentation)" in message.splitlines(),
"expected README.md listed as documentation in message"; assert 'alpha =
\"1.2.3\"' in updated_readme, "expected README.md to contain the updated version
string"; and if relevant add a message for reading the file (e.g., when checking
updated_readme) so failures clearly state the expected condition and which value
failed. Ensure each assert uses the form assert <condition>, "<descriptive
message>".

In `@tests/unit/test_bump_lockfile_rebuild.py`:
- Line 104: Update the bare assertions in
tests/unit/test_bump_lockfile_rebuild.py (e.g., assert "lockfile" not in message
and the other asserts at the mentioned locations) to include descriptive failure
messages as the second argument to assert (for example: assert "lockfile" not in
message, "expected no 'lockfile' in message but found: {message}"). Locate each
assertion instance (the exact assertion expressions at the lines referenced:
assert "lockfile" not in message and the other similar asserts around lines 132,
180–186, 242–244) and add clear, specific messages that include relevant
variables (like message, result, or value) to aid debugging when the assertion
fails.
- Around line 68-76: Add descriptive assertion messages to each assert in this
test: for the dict equality assert referencing captured, append a message like
"captured dict mismatch" and for the string containment asserts referencing
message, append messages like "summary should report 2 lockfiles" and "should
list Cargo.lock" / "should list crates/ui/Cargo.lock" respectively; update all
other asserts in this module similarly so every assert uses the form assert
<expr>, "descriptive message" to make failures clear (look for symbols captured
and message in this file to locate each assertion to update).

In `@tests/unit/test_bump_manifest_updates.py`:
- Around line 87-88: Update the assertions in
tests/unit/test_bump_manifest_updates.py to include descriptive assertion
messages following the pattern used for _load_version(manifest_path,
("package",)) == "7.8.9"; for every bare assert noted (lines referenced: the
groups around _load_version, package/workspace checks and any other assertions
at the listed locations) append a second argument string describing what is
being asserted (e.g., "expected package version to be 7.8.9 from manifest_path",
or "expected workspace package version to be 7.8.9"). Locate assertions that
call _load_version, use manifest_path, or validate versions and update them to
assert <expr>, "<descriptive message>" so every assertion at the listed spots
has a clear failure message.
- Around line 57-65: Add concise failure messages to each assertion in
test_bump_manifest_updates.py so failures are descriptive: update the equality
assertion for message.splitlines() to include a message like "unexpected output
lines" referencing the variable message; add messages to the two _load_version
assertions such as "root Cargo.toml version not updated" for the tmp_path check
and "crate manifest version not updated for {crate.manifest_path}" for the loop
over workspace.crates; ensure each assert uses the form assert <condition>,
"<message>" and keep messages short and specific to the failing check.

In `@tests/unit/test_bump_rebuild_lockfiles_resolution.py`:
- Line 49: Add descriptive failure messages to the three bare asserts that check
rebuild_lockfiles: replace the assertion at "assert
context.base_options.rebuild_lockfiles is expected" and the two similar
assertions at the other locations with assertions that include a clear message
(e.g., "expected rebuild_lockfiles to be {expected} but was {actual}") so
failures show the expected vs actual; update the message text to reference
context.base_options.rebuild_lockfiles and expected for each of the three
asserts (lines shown) so test failures are informative.
🪄 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: 6e9e0434-3dc2-442d-bfea-103216dd0558

📥 Commits

Reviewing files that changed from the base of the PR and between c54cb2d and a6bc52c.

📒 Files selected for processing (5)
  • tests/unit/conftest.py
  • tests/unit/test_bump_documentation_updates.py
  • tests/unit/test_bump_lockfile_rebuild.py
  • tests/unit/test_bump_manifest_updates.py
  • tests/unit/test_bump_rebuild_lockfiles_resolution.py

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 7

🤖 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/unit/test_bump_documentation_updates.py`:
- Around line 86-95: The assertions in
tests/unit/test_bump_documentation_updates.py lack descriptive messages; update
each assert that references message, crate_readme.read_text(...), and the
_load_version(...) check (used with tmp_path, scenario) to include a clear
failure message string explaining expected vs actual (e.g., "expected 'readme
file(s)' in message", "expected README contents to equal ...", "expected version
to remain 0.1.0"). Modify the asserts on message (both contains and splitlines
checks), the crate_readme.read_text(...) equality, and the conditional
_load_version(...) equality to pass a third parameter (the assertion message) so
test failures show meaningful context.
- Around line 45-48: Each bare assert should include a concise failure message:
update the four assertions using the variables shown (message, updated_readme,
readme_path) to include descriptive strings—for example, assert "documentation
file(s)" in message, "expected summary mentioning documentation file(s) in
message"; assert "- README.md (documentation)" in message.splitlines(),
"expected README.md listed as documentation in message"; assert 'alpha =
\"1.2.3\"' in updated_readme, "expected README.md to contain the updated version
string"; and if relevant add a message for reading the file (e.g., when checking
updated_readme) so failures clearly state the expected condition and which value
failed. Ensure each assert uses the form assert <condition>, "<descriptive
message>".

In `@tests/unit/test_bump_lockfile_rebuild.py`:
- Line 104: Update the bare assertions in
tests/unit/test_bump_lockfile_rebuild.py (e.g., assert "lockfile" not in message
and the other asserts at the mentioned locations) to include descriptive failure
messages as the second argument to assert (for example: assert "lockfile" not in
message, "expected no 'lockfile' in message but found: {message}"). Locate each
assertion instance (the exact assertion expressions at the lines referenced:
assert "lockfile" not in message and the other similar asserts around lines 132,
180–186, 242–244) and add clear, specific messages that include relevant
variables (like message, result, or value) to aid debugging when the assertion
fails.
- Around line 68-76: Add descriptive assertion messages to each assert in this
test: for the dict equality assert referencing captured, append a message like
"captured dict mismatch" and for the string containment asserts referencing
message, append messages like "summary should report 2 lockfiles" and "should
list Cargo.lock" / "should list crates/ui/Cargo.lock" respectively; update all
other asserts in this module similarly so every assert uses the form assert
<expr>, "descriptive message" to make failures clear (look for symbols captured
and message in this file to locate each assertion to update).

In `@tests/unit/test_bump_manifest_updates.py`:
- Around line 87-88: Update the assertions in
tests/unit/test_bump_manifest_updates.py to include descriptive assertion
messages following the pattern used for _load_version(manifest_path,
("package",)) == "7.8.9"; for every bare assert noted (lines referenced: the
groups around _load_version, package/workspace checks and any other assertions
at the listed locations) append a second argument string describing what is
being asserted (e.g., "expected package version to be 7.8.9 from manifest_path",
or "expected workspace package version to be 7.8.9"). Locate assertions that
call _load_version, use manifest_path, or validate versions and update them to
assert <expr>, "<descriptive message>" so every assertion at the listed spots
has a clear failure message.
- Around line 57-65: Add concise failure messages to each assertion in
test_bump_manifest_updates.py so failures are descriptive: update the equality
assertion for message.splitlines() to include a message like "unexpected output
lines" referencing the variable message; add messages to the two _load_version
assertions such as "root Cargo.toml version not updated" for the tmp_path check
and "crate manifest version not updated for {crate.manifest_path}" for the loop
over workspace.crates; ensure each assert uses the form assert <condition>,
"<message>" and keep messages short and specific to the failing check.

In `@tests/unit/test_bump_rebuild_lockfiles_resolution.py`:
- Line 49: Add descriptive failure messages to the three bare asserts that check
rebuild_lockfiles: replace the assertion at "assert
context.base_options.rebuild_lockfiles is expected" and the two similar
assertions at the other locations with assertions that include a clear message
(e.g., "expected rebuild_lockfiles to be {expected} but was {actual}") so
failures show the expected vs actual; update the message text to reference
context.base_options.rebuild_lockfiles and expected for each of the three
asserts (lines shown) so test failures are informative.
🪄 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: 6e9e0434-3dc2-442d-bfea-103216dd0558

📥 Commits

Reviewing files that changed from the base of the PR and between c54cb2d and a6bc52c.

📒 Files selected for processing (5)
  • tests/unit/conftest.py
  • tests/unit/test_bump_documentation_updates.py
  • tests/unit/test_bump_lockfile_rebuild.py
  • tests/unit/test_bump_manifest_updates.py
  • tests/unit/test_bump_rebuild_lockfiles_resolution.py
🛑 Comments failed to post (7)
tests/unit/test_bump_documentation_updates.py (2)

45-48: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add descriptive assertion messages to all asserts.

The guidelines require assert …, "message" over bare asserts. Every assertion in this module lacks a descriptive failure message, which hinders debugging when tests fail. Add concise messages explaining the expected condition.

Example fixes
-    assert "documentation file(s)" in message
+    assert "documentation file(s)" in message, "Expected bump output to report documentation updates"
-    assert "- README.md (documentation)" in message.splitlines()
+    assert "- README.md (documentation)" in message.splitlines(), "Expected README.md in the updated file list"
-    assert 'alpha = "1.2.3"' in updated_readme
+    assert 'alpha = "1.2.3"' in updated_readme, "Expected TOML fence version to be rewritten to 1.2.3"
🤖 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/unit/test_bump_documentation_updates.py` around lines 45 - 48, Each
bare assert should include a concise failure message: update the four assertions
using the variables shown (message, updated_readme, readme_path) to include
descriptive strings—for example, assert "documentation file(s)" in message,
"expected summary mentioning documentation file(s) in message"; assert "-
README.md (documentation)" in message.splitlines(), "expected README.md listed
as documentation in message"; assert 'alpha = \"1.2.3\"' in updated_readme,
"expected README.md to contain the updated version string"; and if relevant add
a message for reading the file (e.g., when checking updated_readme) so failures
clearly state the expected condition and which value failed. Ensure each assert
uses the form assert <condition>, "<descriptive message>".

Source: Coding guidelines


86-95: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add descriptive assertion messages.

Apply the same fix to all assertions in this test (lines 86, 87, 88, 92-95). Descriptive messages clarify intent and aid debugging.

🤖 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/unit/test_bump_documentation_updates.py` around lines 86 - 95, The
assertions in tests/unit/test_bump_documentation_updates.py lack descriptive
messages; update each assert that references message,
crate_readme.read_text(...), and the _load_version(...) check (used with
tmp_path, scenario) to include a clear failure message string explaining
expected vs actual (e.g., "expected 'readme file(s)' in message", "expected
README contents to equal ...", "expected version to remain 0.1.0"). Modify the
asserts on message (both contains and splitlines checks), the
crate_readme.read_text(...) equality, and the conditional _load_version(...)
equality to pass a third parameter (the assertion message) so test failures show
meaningful context.

Source: Coding guidelines

tests/unit/test_bump_lockfile_rebuild.py (2)

68-76: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add descriptive assertion messages to all asserts.

This test (and all others in this module) lacks assertion messages. Follow the guideline requiring assert …, "message" for clearer test failures.

Example fixes
     assert captured == {
         "calls": 1,
         "workspace_root": tmp_path,
         "lockfile_manifests": (),
         "runner": None,
-    }
+    }, "Expected regenerate_lockfiles to be called exactly once with correct arguments"
-    assert "2 lockfile(s)" in message
+    assert "2 lockfile(s)" in message, "Expected bump output to report 2 regenerated lockfiles"
-    assert "- Cargo.lock (lockfile)" in message.splitlines()
+    assert "- Cargo.lock (lockfile)" in message.splitlines(), "Expected workspace Cargo.lock in output"
-    assert "- crates/ui/Cargo.lock (lockfile)" in message.splitlines()
+    assert "- crates/ui/Cargo.lock (lockfile)" in message.splitlines(), "Expected nested Cargo.lock in output"
🤖 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/unit/test_bump_lockfile_rebuild.py` around lines 68 - 76, Add
descriptive assertion messages to each assert in this test: for the dict
equality assert referencing captured, append a message like "captured dict
mismatch" and for the string containment asserts referencing message, append
messages like "summary should report 2 lockfiles" and "should list Cargo.lock" /
"should list crates/ui/Cargo.lock" respectively; update all other asserts in
this module similarly so every assert uses the form assert <expr>, "descriptive
message" to make failures clear (look for symbols captured and message in this
file to locate each assertion to update).

Source: Coding guidelines


104-104: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Apply assertion messages to all remaining tests.

Lines 104, 132, 180, 184-186, 242, and 244 all require descriptive failure messages per the coding guidelines.

Also applies to: 132-132, 180-186, 242-244

🤖 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/unit/test_bump_lockfile_rebuild.py` at line 104, Update the bare
assertions in tests/unit/test_bump_lockfile_rebuild.py (e.g., assert "lockfile"
not in message and the other asserts at the mentioned locations) to include
descriptive failure messages as the second argument to assert (for example:
assert "lockfile" not in message, "expected no 'lockfile' in message but found:
{message}"). Locate each assertion instance (the exact assertion expressions at
the lines referenced: assert "lockfile" not in message and the other similar
asserts around lines 132, 180–186, 242–244) and add clear, specific messages
that include relevant variables (like message, result, or value) to aid
debugging when the assertion fails.

Source: Coding guidelines

tests/unit/test_bump_manifest_updates.py (2)

57-65: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add descriptive assertion messages.

This test (and all others in this module) violates the guideline requiring assert …, "message". Add concise failure messages to aid debugging.

Example fixes
-    assert message.splitlines() == [
+    assert message.splitlines() == [
         "Updated version to 1.2.3 in 3 manifest(s):",
         "- Cargo.toml",
         "- crates/alpha/Cargo.toml",
         "- crates/beta/Cargo.toml",
-    ]
+    ], "Expected bump output to list all updated manifests"
-    assert _load_version(tmp_path / "Cargo.toml", ("workspace", "package")) == "1.2.3"
+    assert _load_version(tmp_path / "Cargo.toml", ("workspace", "package")) == "1.2.3", "Expected workspace package version to be 1.2.3"
     for crate in workspace.crates:
-        assert _load_version(crate.manifest_path, ("package",)) == "1.2.3"
+        assert _load_version(crate.manifest_path, ("package",)) == "1.2.3", f"Expected crate {crate.name} version to be 1.2.3"
🤖 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/unit/test_bump_manifest_updates.py` around lines 57 - 65, Add concise
failure messages to each assertion in test_bump_manifest_updates.py so failures
are descriptive: update the equality assertion for message.splitlines() to
include a message like "unexpected output lines" referencing the variable
message; add messages to the two _load_version assertions such as "root
Cargo.toml version not updated" for the tmp_path check and "crate manifest
version not updated for {crate.manifest_path}" for the loop over
workspace.crates; ensure each assert uses the form assert <condition>,
"<message>" and keep messages short and specific to the failing check.

Source: Coding guidelines


87-88: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Apply assertion messages across all remaining tests.

Lines 87-88, 101-104, 132-136, 175-176, 194, 206, 253, 281-288, and 332 all require descriptive messages. Apply the same pattern shown above.

Also applies to: 101-104, 132-136, 175-176, 194-194, 206-206, 253-253, 281-288, 332-332

🤖 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/unit/test_bump_manifest_updates.py` around lines 87 - 88, Update the
assertions in tests/unit/test_bump_manifest_updates.py to include descriptive
assertion messages following the pattern used for _load_version(manifest_path,
("package",)) == "7.8.9"; for every bare assert noted (lines referenced: the
groups around _load_version, package/workspace checks and any other assertions
at the listed locations) append a second argument string describing what is
being asserted (e.g., "expected package version to be 7.8.9 from manifest_path",
or "expected workspace package version to be 7.8.9"). Locate assertions that
call _load_version, use manifest_path, or validate versions and update them to
assert <expr>, "<descriptive message>" so every assertion at the listed spots
has a clear failure message.

Source: Coding guidelines

tests/unit/test_bump_rebuild_lockfiles_resolution.py (1)

49-49: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add descriptive assertion messages to all asserts.

Lines 49, 108, and 134 all lack descriptive failure messages. Apply the guideline requiring assert …, "message".

Proposed fixes
     expected = configured if flag is None else flag
-    assert context.base_options.rebuild_lockfiles is expected
+    assert context.base_options.rebuild_lockfiles is expected, f"Expected rebuild_lockfiles={expected} (flag={flag}, configured={configured})"

Apply similar messages at lines 108 and 134, adjusting context as needed.

Also applies to: 108-108, 134-134

🤖 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/unit/test_bump_rebuild_lockfiles_resolution.py` at line 49, Add
descriptive failure messages to the three bare asserts that check
rebuild_lockfiles: replace the assertion at "assert
context.base_options.rebuild_lockfiles is expected" and the two similar
assertions at the other locations with assertions that include a clear message
(e.g., "expected rebuild_lockfiles to be {expected} but was {actual}") so
failures show the expected vs actual; update the message text to reference
context.base_options.rebuild_lockfiles and expected for each of the three
asserts (lines shown) so test failures are informative.

Source: Coding guidelines

Address the review request to attach explanatory messages to the bare
assertions in the four bump test modules so failures explain intent. pytest
introspection still reports the compared values; the messages add the
"what/why" context. Messages interpolate already-bound locals (message,
updated_readme) where cheap and avoid re-reading manifests via _load_version.

Covers test_bump_manifest_updates.py, test_bump_lockfile_rebuild.py,
test_bump_documentation_updates.py, and test_bump_rebuild_lockfiles_resolution.py.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

Emit a DEBUG record at the single rebuild_lockfiles resolution point in
_initialize_bump_context, exposing the raw nullable flag, the configured
default, and the resolved value. This makes the coalescing decision visible
to operators running with debug logging. The call uses %r formatting to match
the existing _log.debug style in the module.

Add a caplog-based unit test asserting the debug record is emitted with both
the raw flag and the resolved value when the logger is at DEBUG level.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
codescene-delta-analysis[bot]

This comment was marked as outdated.

@lodyai

lodyai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai resume

Replace the inline shape assertions against bump.run()'s formatted result
string (substring `in message`, `in message.splitlines()`, `not in message`,
and inline-literal `splitlines() == [...]`) with syrupy snapshot assertions
across the manifest, lockfile-rebuild, and documentation bump test modules.
Output-format regressions are now caught automatically with human-readable
diffs, and each parametrised case produces a distinct snapshot key.

Side-effect assertions (TOML version strings, on-disk file contents, the
captured regenerate_lockfiles call, and the exact no-op expected_message
parametrisation) are retained unchanged. SnapshotAssertion is imported under
TYPE_CHECKING to satisfy the flake8-type-checking (TC) rule, matching the
existing MonkeyPatch import style. Generated __snapshots__/*.ambr files are
committed alongside.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented Jun 11, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

Replace the last inline `bump.run` output assertions in the bump
manifest and lockfile tests with syrupy snapshots. Keep the existing
side-effect assertions in place so the tests still distinguish rendered
output from filesystem behaviour.
codescene-delta-analysis[bot]

This comment was marked as outdated.

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

Caution

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

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

20-28: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Remove unused expected_message field.

The _LockfileSkipScenario.expected_message field is defined but never referenced in test_run_skips_lockfile_rebuild. The parametrised test uses only snapshot assertions (line 243), making this field dead code.

♻️ Proposed fix
 `@dc.dataclass`(frozen=True, slots=True)
 class _LockfileSkipScenario:
     """Parameters describing lockfile rebuild skip scenarios."""
 
     test_id: str
     version: str
     rebuild_lockfiles: bool
     fail_message: str
-    expected_message: str | None
🤖 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/unit/test_bump_lockfile_rebuild.py` around lines 20 - 28, The
_LockfileSkipScenario dataclass defines an unused field expected_message; remove
the expected_message attribute from the class declaration (in the
_LockfileSkipScenario dataclass) and clean up any references if present so the
test_run_skips_lockfile_rebuild parametrisation and snapshot assertions only use
test_id, version, rebuild_lockfiles, and fail_message; ensure the dataclass
import/usage remains consistent after removal.
🤖 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.

Outside diff comments:
In `@tests/unit/test_bump_lockfile_rebuild.py`:
- Around line 20-28: The _LockfileSkipScenario dataclass defines an unused field
expected_message; remove the expected_message attribute from the class
declaration (in the _LockfileSkipScenario dataclass) and clean up any references
if present so the test_run_skips_lockfile_rebuild parametrisation and snapshot
assertions only use test_id, version, rebuild_lockfiles, and fail_message;
ensure the dataclass import/usage remains consistent after removal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ee0f4b4c-b34f-4bdf-bd58-107b113c251d

📥 Commits

Reviewing files that changed from the base of the PR and between a6bc52c and 2237925.

📒 Files selected for processing (8)
  • lading/commands/bump.py
  • tests/unit/__snapshots__/test_bump_documentation_updates.ambr
  • tests/unit/__snapshots__/test_bump_lockfile_rebuild.ambr
  • tests/unit/__snapshots__/test_bump_manifest_updates.ambr
  • tests/unit/test_bump_documentation_updates.py
  • tests/unit/test_bump_lockfile_rebuild.py
  • tests/unit/test_bump_manifest_updates.py
  • tests/unit/test_bump_rebuild_lockfiles_resolution.py

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Tip

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== syrupy/snapshot usage in the three test files ==="
rg -n "syrupy|snapshot|SnapshotAssertion" \
  tests/unit/test_bump_manifest_updates.py \
  tests/unit/test_bump_lockfile_rebuild.py \
  tests/unit/test_bump_documentation_updates.py 2>/dev/null

echo ""
echo "=== snapshot files present ==="
ls tests/unit/__snapshots__/ 2>/dev/null

echo ""
echo "=== remaining inline output assertions in the three files ==="
rg -n 'assert.*in message\|assert message ==' \
  tests/unit/test_bump_manifest_updates.py \
  tests/unit/test_bump_lockfile_rebuild.py \
  tests/unit/test_bump_documentation_updates.py 2>/dev/null || echo "none found"

echo ""
echo "=== _initialize_bump_context debug logging ==="
rg -n "_log\.debug" lading/commands/bump.py -A 5 -B 5

echo ""
echo "=== caplog test for resolution logging ==="
rg -n "caplog\|rebuild_lockfiles resolution\|test_initialize_bump_context_logs" \
  tests/unit/test_bump_rebuild_lockfiles_resolution.py 2>/dev/null | head -30

Length of output: 4683


🏁 Script executed:

#!/bin/bash
echo "=== check test_bump_rebuild_lockfiles_resolution.py exists ==="
ls -la tests/unit/test_bump_rebuild_lockfiles_resolution.py 2>/dev/null || echo "FILE NOT FOUND"

echo ""
echo "=== search for caplog anywhere in tests/unit ==="
rg -rn "caplog\|test_initialize_bump_context_logs" tests/unit/ 2>/dev/null | head -20

echo ""
echo "=== list new test files ==="
ls -la tests/unit/test_bump_*.py 2>/dev/null

Length of output: 1345


🏁 Script executed:

#!/bin/bash
echo "=== full content of test_bump_rebuild_lockfiles_resolution.py ==="
cat tests/unit/test_bump_rebuild_lockfiles_resolution.py

echo ""
echo "=== _log.debug call in bump.py with context ==="
rg -n "rebuild_lockfiles resolution" lading/commands/bump.py -A 5 -B 10

Length of output: 7152



@leynos Both failed checks are now fully resolved.

Check Status Evidence
Testing – snapshot assertions ✅ Resolved All three modules (test_bump_manifest_updates.py, test_bump_lockfile_rebuild.py, test_bump_documentation_updates.py) import SnapshotAssertion from syrupy and use assert message == snapshot throughout. No inline output assertions remain. Corresponding .ambr snapshot files are committed under tests/unit/__snapshots__/.
Observability – DEBUG logging ✅ Resolved _initialize_bump_context emits _log.debug("rebuild_lockfiles resolution: raw_flag=%r, configured_default=%r, resolved=%r", ...) at lines 208–213 of lading/commands/bump.py. test_initialize_bump_context_logs_resolution in tests/unit/test_bump_rebuild_lockfiles_resolution.py uses caplog.at_level(logging.DEBUG, logger="lading.commands.bump") and asserts that a record containing "rebuild_lockfiles resolution", "raw_flag=None", and "resolved=True" is emitted.

No further work is required for these two items.

Drop the unused `_LockfileSkipScenario.expected_message` value now that
lockfile rebuild output is asserted through syrupy snapshots.
@leynos
leynos merged commit d3217a5 into main Jun 11, 2026
5 checks passed
@leynos
leynos deleted the issue-106-single-rebuild-lockfiles-resolution branch June 11, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Single source of truth for rebuild_lockfiles resolution (CLI vs command)

1 participant