feat(wizard): annotate submodule/vendored lockfiles in discovery - #295
Closed
vpetersson wants to merge 3 commits into
Closed
feat(wizard): annotate submodule/vendored lockfiles in discovery#295vpetersson wants to merge 3 commits into
vpetersson wants to merge 3 commits into
Conversation
Lockfiles that live inside a git submodule (declared in .gitmodules) or a vendored clone (a directory with its own .git) belong to another repository and are better tracked from there. The discover screen now annotates those rows with the enclosing repo path and leaves them deselected by default, with a note explaining why. Detection parses .gitmodules directly (works without a git binary and for declared-but-uninitialized submodules) and checks ancestors for a .git entry — a file for submodule checkouts, a directory for vendored clones. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR improves the wizard’s lockfile discovery UX by detecting when discovered lockfiles live inside a nested repository (git submodule or vendored clone) and surfacing that context in the discover screen so users don’t accidentally configure SBOM generation for “someone else’s repo”.
Changes:
- Extend
DiscoveredLockfilewith optionalnested_repo/nested_repo_kindmetadata to represent an enclosing submodule/vendored repo. - Add discovery-time detection for submodules (via
.gitmodules) and nested repos (via ancestor.gitentries) with memoization. - Update the discover screen to annotate nested-repo rows and default-deselect them; add test coverage for discovery + Textual UI behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
tests/test_wizard_textual.py |
Adds a Textual pilot test to verify nested-repo rows are annotated and deselected by default, and that the explanatory note appears. |
tests/test_wizard_discovery.py |
Adds unit tests for submodule parsing (including quoted paths) and .git-based vendored repo detection. |
sbomify_action/cli/wizard/state.py |
Adds NestedRepoKind and optional nested-repo fields to DiscoveredLockfile while keeping defaults None for compatibility. |
sbomify_action/cli/wizard/screens/discover.py |
Annotates nested-repo lockfiles in the list and changes default selection behavior + adds an explanatory note. |
sbomify_action/cli/wizard/discovery.py |
Implements .gitmodules parsing and ancestor-based nested repo detection with caching; plumbs results into DiscoveredLockfile. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
An attest-build-provenance signature carries the Sigstore identity of the workflow that ran it. For lockfiles inside a submodule or vendored checkout, that identity is the parent repo — but the SBOM describes code owned by another repository, so the attestation would fail verification against the repo the code actually comes from. When attestation is enabled, every matrix row now carries an 'attest' boolean and the attest step is gated on it; nested-repo rows get attest: false. This is also the per-entry hook the upcoming attach-or-backfill submodule flow will need. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment on lines
+59
to
+61
| if lf.nested_repo: | ||
| kind = "submodule" if lf.nested_repo_kind == "submodule" else "vendored repo" | ||
| label += f" [#F4B57F]({kind}: {lf.nested_repo})[/]" |
Each attest: false row now carries an explicit 'Deliberately NOT signed' comment naming the nested repo and why, so the generated YAML documents the decision where it takes effect, not only at the attest step. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment on lines
+68
to
+70
| - ``submodule`` — under a path declared in ``.gitmodules``. | ||
| - ``vendored`` — under a directory with its own ``.git`` (a checked-in | ||
| clone that isn't a registered submodule). |
Comment on lines
+233
to
+236
| A directory counts if it is declared in ``.gitmodules`` (submodule) | ||
| or has its own ``.git`` entry — a file for submodule checkouts, a | ||
| directory for vendored clones. Results are memoised per directory | ||
| since sibling lockfiles share ancestors. |
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lockfiles that live inside a git submodule or a vendored repo checkout belong to another repository — you likely want to set up SBOM generation there instead of bundling them into this repo's workflow. The wizard's discover screen now makes that visible:
extern/lib/Cargo.lock (rust) (submodule: extern/lib).Detection
.gitmodulesis parsed directly forpath =entries (handles quoted paths) — no git binary needed, and declared-but-uninitialized submodules are covered too..gitentry — a file for submodule checkouts, a directory for committed-wholesale clones.DiscoveredLockfilegainsnested_repo/nested_repo_kindfields (both defaultNone, so existing call sites are unaffected).Tests
.git-dir and.git-file shapes, quoted.gitmodulespaths with spaces.ruff check/ruff format --checkclean; wizard suites pass (145 tests).🤖 Generated with Claude Code