Surface lockfile discovery failures via typed exceptions (#79) - #131
Surface lockfile discovery failures via typed exceptions (#79)#131leynos wants to merge 9 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
Summary
WalkthroughLockfile discovery now raises typed exceptions for non-Git workspaces and Git command failures. Publish freshness validation uses a dedicated repository port and policy module. Subprocesses now enforce the C locale. ChangesLockfile discovery and publish preflight
Sequence Diagram(s)sequenceDiagram
participant PublishPreflight
participant LockfilePreflight
participant CargoLockfileInspectionRepository
participant Git
PublishPreflight->>LockfilePreflight: validate lockfile freshness
LockfilePreflight->>CargoLockfileInspectionRepository: discover tracked lockfiles
CargoLockfileInspectionRepository->>Git: run git ls-files
Git-->>CargoLockfileInspectionRepository: return paths or failure
CargoLockfileInspectionRepository-->>LockfilePreflight: return paths or typed exception
LockfilePreflight-->>PublishPreflight: return or raise preflight result
Possibly related PRs
Suggested labels: Poem
Merge Risk: 🟡 Moderate · up to The change exposes non-Git workspaces through a typed error while preserving publish behavior, but a test helper passes the wrong argument type to that error and can fail static type checking; merge should wait for this correction. Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error, 1 warning, 8 inconclusive)
✅ Passed checks (10 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning Your free Security trial is over. An organization admin can upgrade to Advanced for continuous pull request security review or dismiss this notice. Comment |
Reviewer's GuideRefactors lockfile discovery to surface non-git workspaces via a typed exception instead of a silent skip, moves the skip policy to the publish preflight caller, and adds integration and unit tests that exercise discovery against real git repositories and assert the new error-handling behavior. Sequence diagram for lockfile discovery error propagation and skip policysequenceDiagram
participant PublishPreflight
participant discover_tracked_lockfiles
participant runner
participant _raise_git_ls_files_failure
PublishPreflight->>discover_tracked_lockfiles: discover_tracked_lockfiles(workspace_root, runner_with_env)
discover_tracked_lockfiles->>runner: runner(("git", "ls-files", "**/Cargo.lock", "Cargo.lock"), cwd=workspace_root)
runner-->>discover_tracked_lockfiles: exit_code, stdout, stderr
alt exit_code != 0
discover_tracked_lockfiles->>_raise_git_ls_files_failure: _raise_git_ls_files_failure(exit_code, stdout, stderr, workspace_root)
alt ["not a git repository" in detail]
_raise_git_ls_files_failure-->>PublishPreflight: raise NotAGitRepositoryError
PublishPreflight->>PublishPreflight: LOGGER.warning("Skipping lockfile freshness validation...")
PublishPreflight-->>PublishPreflight: return
else other git failure
_raise_git_ls_files_failure-->>PublishPreflight: raise LockfileDiscoveryError
end
else exit_code == 0
discover_tracked_lockfiles-->>PublishPreflight: tracked_lockfiles
end
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
3739c1e to
c6ad97d
Compare
c6ad97d to
f3ce412
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f3ce4128fe
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
f3ce412 to
65ba834
Compare
65ba834 to
df0684d
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/developers-guide.md`:
- Around line 586-597: Add a brief descriptive caption immediately before the
shim inventory table in the documentation, ensuring it clearly identifies the
table’s contents and satisfies the requirement to caption every table.
In `@lading/commands/lockfile.py`:
- Around line 67-75: Update NotAGitRepositoryError to accept and store the
failed workspace_root as a structured exception attribute, preserving it for
callers to access directly without parsing the exception message. Ensure every
construction site in the lockfile discovery flow, including the additional
occurrence, passes the workspace path when raising this error.
- Around line 92-95: Update the command execution in the lockfile discovery flow
around command_detail so the injected command environment forces a deterministic
locale while preserving the existing pre-flight environment values. Classify
non-Git workspaces using the locale-stable Git result rather than matching the
English diagnostic text, and retain the NotAGitRepositoryError path. Add a unit
test covering non-English stderr that still raises NotAGitRepositoryError.
🪄 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: ac5ed76a-32d5-4709-b328-0ce0fd3cd5e2
📒 Files selected for processing (8)
docs/developers-guide.mddocs/lading-design.mdlading/commands/lockfile.pylading/commands/publish_lockfile_preflight.pylading/commands/publish_preflight.pytests/integration/test_lockfile_discovery.pytests/unit/publish/test_preflight_lockfile_validation.pytests/unit/test_lockfile.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/cmd-mox(auto-detected)leynos/cuprum(auto-detected)leynos/shared-actions(auto-detected)
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/integration/test_lockfile_discovery.py`:
- Around line 78-79: Update the assertions in the lockfile discovery test,
including the corresponding assertions around lines 92–93, to include
descriptive failure messages. Clearly state the expected tracked and untracked
lockfiles and the required exclusion of target from the results, while
preserving the existing assertion conditions.
🪄 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: 13ce0c25-3990-4193-92b3-f494ce94a218
📒 Files selected for processing (9)
docs/developers-guide.mddocs/lading-design.mdlading/commands/bump_lockfile_manifests.pylading/commands/lockfile.pylading/commands/publish_lockfile_preflight.pylading/commands/publish_preflight.pytests/integration/test_lockfile_discovery.pytests/unit/publish/test_preflight_lockfile_validation.pytests/unit/test_lockfile.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/cmd-mox(auto-detected)leynos/cuprum(auto-detected)leynos/shared-actions(auto-detected)
df0684d to
38a03d0
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
discover_tracked_lockfiles hid a non-git workspace behind a warning and a silent empty tuple, so callers could not distinguish "no tracked lockfiles" from "discovery never ran". Filesystem access was also mixed into the function rather than confined to a port. Raise a typed NotAGitRepositoryError (subclass of LockfileDiscoveryError) for non-git workspaces and keep LockfileDiscoveryError for other git failures. The skip policy moves to the caller: publish pre-flight catches NotAGitRepositoryError, warns, and continues, preserving existing operator behaviour while making the condition explicit at the API. Filesystem access is now documented as confined to the injected manifest_exists port and git access to the injected runner; the function performs no direct I/O of its own. Replace the silent-skip unit test with a typed-exception assertion, add a caller-policy test for the pre-flight skip, and add integration tests that exercise discovery against real git repositories in temporary directories through the real subprocess runner (tracked versus untracked lockfiles, target/ exclusion, manifest adjacency, and the non-git error). Extract the lockfile freshness policy (_validate_lockfile_freshness, _collect_stale_lockfiles, _build_stale_lockfile_message) into the colocated module publish_lockfile_preflight. Adding the skip branch took publish_preflight past the repository's 400-line file limit, and the freshness policy is a coherent unit: it depends only on the LockfileInspectionRepository port, while publish_preflight retains the cargo and git command orchestration and stays the composition root that binds the adapter. Apply the same caller-owned skip policy on the bump side. Since #160, bump discovers tracked lockfiles through bump_lockfile_manifests.merge_discovered_manifests, whose documented contract is that a non-git workspace returns the configured manifests unchanged. That relied on discovery's silent empty tuple, so the typed error would otherwise abort `lading bump` outside git control; the merge helper now catches NotAGitRepositoryError, warns, and returns the configured tuple. Address review feedback. NotAGitRepositoryError now carries the failing workspace_root as a structured attribute, matching CommandSpawnError and WorkspaceDependencyCycleError, so callers need not parse the message. Add a bounded lockfile.discovery.failed counter (reason=not_git|git_error) and log the unexpected-failure branch at the failure boundary; success volume stays on lockfile.discovered so quiet runs stay quiet. Discovery classifies a non-git workspace by matching git's English text, which a localized machine would translate and silently misclassify. Pin the C locale in subprocess_runner, the single adapter that spawns processes, via the new lading.utils.process.c_locale_env helper. Test doubles bypass it, so no double needs widening, and cargo's output is covered too. Classifying on the exit status instead is not possible: git ls-files exits 128 for every fatal condition. Move the LockfileInspectionRepository port and its adapter into lockfile_repository, with their tests, keeping lockfile.py inside the 400-line limit and separating the hexagonal boundary from the domain operations. Restore the inline-code exclusion in typos.local.toml. Regenerating typos.toml from the shared authority had dropped it, so the spelling gate flagged identifiers such as `normalise_workspace_root` that must keep their source spelling. Closes #79
The df12 lint gate merged in #220 flags absolute paths in syrupy snapshots. The stale-lockfile snapshots embedded the synthetic /ws workspace root, tripping the snapshot-posix-path rule on main. Render the fixture paths through syrupy's documented <tmp-file-path> placeholder and keep the nested case at a single directory segment, so the snapshots stay machine-independent and the scanner's allowlist covers them. The added quoting around the manifest path is emitted by the production shlex.quote path and is a faithful record of user-facing output. Validated with make check-fmt, make test, make typecheck, and make lint.
38a03d0 to
7789463
Compare
`make spelling` regenerates typos.toml from the shared en-GB-oxendict authority merged with typos.local.toml. The branch pins the inline-code exclusion in typos.local.toml so regeneration cannot drop it; refresh the tracked generated file to match that output, keeping the working tree clean after the spelling gate runs.
Correct the user guide: bump regenerates the lockfiles adjacent to the configured manifests, not the manifests themselves. Build the NotAGitRepositoryError message in a local variable before calling super(), matching the sibling CommandSpawnError pattern. Render c_locale_env's Examples section as doctest prompts so it follows the doctest convention used by every other Examples block in the module and its expected output stays machine-checkable. Pass workspace_root directly when the pre-flight test double raises NotAGitRepositoryError, so the exception's structured attribute holds the recorded Path instead of a formatted string.
The markdownlint target swept every *.md under the working tree with find, so gitignored agent-infrastructure files (.vtcode/, .pytest_cache/) and any untracked scratch Markdown broke the gate with violations that never exist in a fresh checkout. List the files with git ls-files instead, matching the spelling target directly below, which already restricts itself to tracked files. Also ignore memories/, the scratch directory sub-agents write session progress into, extending the agent-artefact ignore list from b8291b9.
The contract pinned the literal find exclusions (-not -path) that the markdownlint target no longer uses. Keep guarding the property the contract exists for — generated uv cache and tool documentation must stay out of lint scope — by asserting the target lists files through git ls-files and that both directories remain gitignored, which excludes them from lint scope by construction.
Placing the table caption before the table it names matches the convention used by the regenerate_lockfiles figure caption and reads as a title rather than a footnote.
mdformat's reflow split the [`[bump]`](#bump) inline-code link across lines, which markdownlint then rejected as MD039 (spaces inside link text), so every `make fmt` run ended in a lint error. Refer to the section in prose so the paragraph survives rewrapping and the gate stays idempotent.
`make fmt` rewraps these paragraphs on every run because earlier edits left them outside mdformat's current wrap width; commit the output so the formatting gate leaves a clean tree, matching the precedent set by the generated-spelling commit 7ad8f6a.
Summary
Closes #79
discover_tracked_lockfilespreviously hid a non-git workspace behind a warning and a silent empty tuple. It now raises a typedNotAGitRepositoryError(subclass ofLockfileDiscoveryError) for non-git workspaces; other git failures keep raisingLockfileDiscoveryError.NotAGitRepositoryError, warns, and continues — preserving operator behaviour while making the condition explicit at the API.runner, filesystem access through the injectedmanifest_existsadapter; the function performs no direct I/O of its own (documented in the docstring).Testing
tests/integration/test_lockfile_discovery.pyexercises discovery against real git repositories in temporary directories through the real subprocess runner, without stubbing internals: tracked vs untracked lockfiles,target/exclusion, manifest adjacency, and the non-git typed error.make check-fmt,make lint,make typecheck, andmake test(565 passed) all green after rebasing onto currentmain.coderabbit review --agent: 0 findings.🤖 Generated with Claude Code
Summary by Sourcery
Make lockfile discovery failures explicit while preserving non-Git workspace handling at publish and bump boundaries.
New Features:
NotAGitRepositoryErrorexception.Bug Fixes:
Enhancements:
Build:
Documentation:
Tests:
Chores:
References