fix(bundles): retrieve pinned component releases when a catalog advertises a newer version - #4753
Open
muhammadumer-waheed wants to merge 1 commit into
Open
muhammadumer-waheed wants to merge 1 commit into
muhammadumer-waheed wants to merge 1 commit into
Conversation
…tises a newer version Bundle manifests pin component versions for reproducibility, but extension/preset bundle installation compared the pin against the version the catalog currently advertises and refused the install when they differed, even when the pinned release remained available at its original download URL (github#4712). Catalog entries advertise a single release, so the resolver never attempted to retrieve the pinned one. When the pin differs from the advertised version, the bundler now derives the pinned release's URL from the catalog entry's own download_url by substituting the advertised version token in the URL path (bounded token matching: a v-prefixed tag, a versioned asset filename, or a version glued to an archive suffix) and retrieves that release through the catalog's existing download pipeline (HTTPS validation, size limits, safe cache path). The catalog's SHA-256 covers only the advertised release, so a retrieved pinned release is verified against no digest; the same host and the HTTPS rule still apply. When the pinned release cannot be identified from the catalog URL, or the retrieval fails, the error names the pinned and advertised versions instead of a bare pin mismatch or network error. To expose explicit-URL retrieval without duplicating the download pipeline, the fetch stage of ExtensionCatalog.download_extension and PresetCatalog.download_pack is now download_extension_url / download_pack_url, which the ID-based methods delegate to without behavior change (a catalog entry with a null version now names the cached archive "unknown" instead of erroring). Workflows and bundled-asset installs keep their existing hard pin check: a workflow's URL install path carries an interactive untrusted-source confirmation that a derived-URL fetch would bypass, and a bundled asset has no alternative release to retrieve. New regression tests in tests/specify_cli/bundles/test_primitives.py fail on main (the pin mismatch raised before any retrieval attempt) and pass with this change, plus URL-derivation unit tests and explicit-URL download coverage in tests/test_extensions.py and tests/specify_cli/presets/test_catalog.py. Verified end-to-end with a local catalog advertising 0.5.1 while a 0.4.12 release stays available: `specify bundle install` now installs the pinned 0.4.12 release (on main it fails with the reported error). Fixes github#4712 Assisted-by: opencode (model: Qwen3.8-27B (local), autonomous)
This branch has not been deployed
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.
Fixes #4712.
Summary
Bundle manifests pin component versions for reproducibility, but
specify bundle installcompared each pin against the version the catalog currently advertises and refused the install when they differed — even when the pinned release remained available at its original download URL. Catalog entries advertise a single release, so the pinned release was never even attempted.This change makes the bundler retrieve the pinned release when a catalog entry has moved on:
download_urlby substituting the advertised version token in the URL path (bounded token matching: a v-prefixed tag, a versioned asset filename, or a version glued to an archive suffix) and retrieves that release through the catalog's existing download pipeline. When the pinned release cannot be identified from the catalog URL, or the retrieval fails, the error names the pinned and advertised versions instead of a bare pin mismatch or network error.ExtensionCatalog.download_extensionandPresetCatalog.download_packis nowdownload_extension_url/download_pack_url(HTTPS validation, size-limited fetch, optional SHA-256, archive-format detection, safe cache path), which the ID-based methods delegate to without behavior change.Intentionally out of scope: workflows keep the hard pin check (their URL install path carries an interactive untrusted-source confirmation that a derived-URL fetch would bypass), bundled assets keep the hard check (no alternative release exists), and steps perform no pin check today.
Reproduction (the issue's scenario)
A local catalog server advertising
specassay-checkv0.5.1 while the 0.4.12 release artifact stays available at its original URL; the bundle pins 0.4.12:Error: Extension 'specassay-check' is pinned to version 0.4.12 in the bundle manifest, but the resolved version is 0.5.1. Update the bundle's pinned version or the source before installing.✓ Installed 'test-bundle' (1 added, 0 already present).— the registry records version0.4.12and the installedextension.ymldeclaresversion: 0.4.12.Test plan
New regression tests fail on
main(the pin mismatch raised before any retrieval attempt) and pass with this change; the full suite is otherwise unchanged — the 10 pre-existing*_python_parity"composed" failures reproduce identically on cleanmain:uvx ruff@0.15.0 check src tests→ All checks passed.markdownlint-cli2 docs/reference/bundles.md→ 0 issues.Manual test results
Agent: n/a (CLI-level change; verified by running
specify bundle installdirectly) | OS/Shell: macOS/zshspecify bundle install <bundle.yml> --integration copilotspecify bundle install <bundle.yml>(stale pin, non-derivable catalog URL)AI disclosure
Implemented with opencode (model: Qwen3.8-27B, running locally; autonomous within the session under user direction, no human line-by-line review before this PR was opened). Extent: issue triage, source analysis, code, tests, end-to-end reproduction, and docs were all generated by the agent.