Repository navigation
feat(bundles): select exact bundle catalog releases - #4849
Conversation
Add the bundle catalog slice of github#4719. A bundle catalog entry may now advertise historical releases in an optional `releases` mapping, following the extension, preset, workflow and step slices. - `bundle install/add <id> --version <v>` installs an exact catalog release from the winning source; the historical download URL, digest and manifest ID/version checks flow through the existing download path. - `bundle info <id> --versions` lists the current and historical releases (text and JSON) without downloading a manifest. - Release history is validated lazily; `requires`, `provides` and `verified` are never inherited by historical releases. - Lookup never falls through to a lower-priority source, and discovery-only sources stay non-installable. Assisted-by: GitHub Copilot CLI (model: GPT-5.6 Terra, autonomous) Assisted-by: GitHub Copilot CLI (model: Claude Opus 5.5, autonomous) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Catalog validation and manifest version matching still have unresolved correctness issues.
Review effort: Balanced
Findings: 1
Open (2)
What changed in this PR
Adds exact bundle-release selection to Specify CLI’s catalog support for #4719, without changing bundle component pins.
Changes:
- Adds
--versionto bundle install/add. - Adds release-history validation and
info --versions. - Documents the format and adds focused regression coverage.
AI disclosure: GitHub Copilot (model unknown, autonomous review) prepared this review for the requester.
| File | Description |
|---|---|
tests/specify_cli/bundles/test_command_install.py |
Tests invalid option combinations. |
tests/specify_cli/bundles/test_command_install_version.py |
Covers historical installs and verification failures. |
tests/specify_cli/bundles/test_command_info.py |
Tests version listings and errors. |
tests/specify_cli/bundles/test_command_add.py |
Checks version-option forwarding. |
tests/specify_cli/bundles/test_catalog_versions.py |
Tests release validation and selection. |
tests/specify_cli/bundles/test_catalog_stack.py |
Covers precedence and lazy validation. |
src/specify_cli/bundles/command_install.py |
Supports exact-release installation. |
src/specify_cli/bundles/command_info.py |
Displays available releases. |
src/specify_cli/bundles/command_add.py |
Forwards exact-version requests. |
src/specify_cli/bundles/catalogs.py |
Preserves raw release metadata. |
src/specify_cli/bundles/catalog_versions.py |
Validates, selects, and lists releases. |
src/specify_cli/bundles/catalog_stack.py |
Resolves versions from the winning source. |
docs/reference/bundles.md |
Documents release history and CLI options. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Please address Copilot feedback and fix test & lint errors |
Reject duplicate JSON keys before decoding bundle catalogs, validate release history as catalog entries load, and compare catalog and manifest versions semantically. Assisted-by: OpenCode (model: github-copilot/gpt-5.6-terra, autonomous)
|
Review-fix round for @markuswondrak: pushed The change rejects duplicate JSON keys before bundle catalog decoding, validates Verification: AI disclosure: posted on behalf of Markus Wondrak by OpenCode using |
|
Follow-up context for the review findings: the two issues came from inconsistent behavior across catalog slices. Presets and workflow steps reject duplicate JSON object keys during decoding with For manifest identity, extensions and presets compare parsed versions, while the original bundle release selection used parsed equality but compared the selected catalog version and manifest version as raw strings. This fix uses AI disclosure: posted on behalf of Markus Wondrak by OpenCode using |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
Static inspection found no blocking defects, and the supplied regression coverage addresses release selection, integrity, and source policy.
Review effort: Balanced
Findings: None
Resolved since last review (2)
|
Please address Copilot feedback. If not applicable, please explain why |
- is_semver() now uses fullmatch(), so a trailing newline in a release key or version is rejected instead of passing the `$`-anchored regex. - Bundle _require_https() delegates to is_https_or_localhost_http(), so catalog validation and download enforce the same URL policy (e.g. http://127.0.0.2 and expanded IPv6 loopback are accepted consistently). Assisted-by: OpenCode (model: github-copilot/claude-sonnet-5.5, autonomous)
|
AI-generated comment, posted on behalf of @markuswondrak by OpenCode (model: github-copilot/claude-sonnet-5.5, supervised by the contributor; code generation and test updates). Addressed both findings in 069ef3f:
The new tests fail without the source changes and pass with them; |
|
Thank you! |


Description
Part of #4719. This is the Bundle catalog slice: a bundle catalog entry can advertise historical releases under one catalog ID.
What changes
specify bundle install|add <id> --version <v>selects the exact release from the winning catalog source. Historical artifacts use their own download URL and SHA-256 digest through the existing secure download path.specify bundle info <id> --versionslists current and historical releases without downloading a manifest.releasesmapping makes the consulted source fail forinstall,info,update, andsearch. Resolution stops at the first source listing an ID, whilesearchloads every source.same_versionaccepts equivalent spellings such asv1.1.0/1.1.0and1.0.0-rc.1/1.0.0-rc1; the catalog key spelling is display-only.bundle updatecontinues to select the current release.Non-goal: component version pins inside bundle manifests (#4712, handled by #4753).
Testing
file://URLs, HTTP responses, and packaged snapshots.uv sync --extra test..venv/bin/python -m pytest tests/specify_cli/bundles tests/contract/test_firstparty_bundle_catalog_consistency.py -q: 578 passed.uvx ruff@0.15.0 check src tests.tests/integration/test_preset_update_workflow.py::test_preset_update_cli_contract, whose expected Typer/Click missing-argument text differs from the installed dependency output; the isolated file result was 1 failed, 3 passed.AI Disclosure
github-copilot/gpt-5.6-terra, autonomous, implemented the duplicate-key, eager-validation, normalized-version, test, documentation, and PR-description updates.Assisted-by:trailer.