Skip to content

Add infrahubctl marketplace CLI for downloading schemas and collections#952

Draft
minitriga wants to merge 4 commits intostablefrom
knotty-dibble
Draft

Add infrahubctl marketplace CLI for downloading schemas and collections#952
minitriga wants to merge 4 commits intostablefrom
knotty-dibble

Conversation

@minitriga
Copy link
Copy Markdown
Contributor

@minitriga minitriga commented Apr 21, 2026

Summary

Adds a new infrahubctl marketplace sub-app with a download command that pulls schemas and collections from the public Infrahub Marketplace (marketplace.infrahub.app) into a local directory.

infrahubctl marketplace download acme/network-base           # any item, auto-detected
infrahubctl marketplace download acme/network-base -v 1.2.0  # pin a schema version
infrahubctl marketplace download acme/starter-pack           # collection resolved automatically
infrahubctl marketplace download acme/foo -o ./infra/schemas # custom destination

What the command does

  • REST-based — talks to the public marketplace REST API (/api/v1/schemas/..., /api/v1/collections/...); no GraphQL involved.
  • Auto-detect schema vs collection — probes both endpoints in parallel. One command handles either item type without the caller needing to know which it is. On a rare namespace/name collision, schema wins with a warning; --collection forces the other path.
  • Version pinning--version <semver> pins the download to a specific published schema version; default is whatever the marketplace resolves as latest (echoed back on success).
  • Custom destination--output-dir (default ./schemas) controls where files land; missing parent directories are created.
  • Marketplace override--marketplace-url / infrahubctl.toml marketplace_url / INFRAHUB_MARKETPLACE_URL env var let you point at staging or a local instance.
  • Clean error taxonomy — four distinct failure classes (invalid input, not found, version not found, network) with exit code 1 for deterministic failures and 2 for transient/network so CI can branch on it. No tracebacks on an unwritable output directory, a missing schema, or a connection refused.

Options

Option Default Purpose
IDENTIFIER (positional) required namespace/name — a schema or collection
-v, --version TEXT latest Pin to a specific published schema version
-c, --collection auto-detect Force the collection code path
-o, --output-dir PATH ./schemas Where to write files
--marketplace-url TEXT https://marketplace.infrahub.app Override the marketplace host

Behaviour notes

  • Output lines state the resolved item type (Downloaded schema … / Downloaded collection …) so the user can detect an unintended match in a collision case.
  • Passing --version alongside a collection identifier prints a warning and proceeds with the collection download, rather than failing.
  • A missing version on an existing schema reports "no published version ''" with a hint to drop --version, distinct from "schema not found".

Out of scope

No --load convenience flag. download is write-only — chain with infrahubctl schema load <dir> to push the result into a running Infrahub.

Test plan

  • uv run pytest tests/unit/ctl/test_marketplace_app.py — 17 tests covering auto-detect, collision, error classes, --version, --output-dir, --marketplace-url, --collection override.
  • uv run invoke lint — ruff, yamllint, mypy, markdownlint, vale all clean.
  • uv run invoke docs-generate + docs-validate — generated reference page in sync.
  • End-to-end smoke test against the live marketplace: infrahubctl marketplace download nonexistent/nonexistent returns the expected not-found message with exit 1.
  • Smoke-test against the live marketplace with a real published schema + collection pair (see specs/001-marketplace-api-update/quickstart.md for the full scenario list).

Artefacts

Full spec, plan, research, contracts, quickstart, and task breakdown under specs/001-marketplace-api-update/ for reviewers who want the design rationale (auto-detect strategy evaluation, error taxonomy decisions, collision precedence).

🤖 Generated with Claude Code

minitriga and others added 2 commits April 21, 2026 11:46
- Probe schema and collection endpoints in parallel so
  `infrahubctl marketplace download <ns>/<name>` no longer requires
  the user to pass `--collection` up front. Collision between the two
  resolves to schema with a warning (pass `--collection` to force the
  other path). `_detect_item_type` returns the winning 200 response so
  the download helper reuses it instead of re-fetching.
- Remove the `--load` convenience flag; `download` is write-only.
  Users who want to push into Infrahub chain with `infrahubctl schema
  load`.
- Introduce a four-class error taxonomy (invalid-input, not-found,
  network) with exit codes 1 vs 2, distinguishing "version not found"
  from "schema not found" when `--version` is passed.
- Surface filesystem failures (unwritable `--output-dir`) cleanly
  rather than as a traceback.
- Regenerate `infrahubctl-marketplace.mdx`; no longer advertises
  `--load`.
- Add spec, plan, research, contract, quickstart, tasks, and
  checklist artifacts under `specs/001-marketplace-api-update/`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@minitriga minitriga requested a review from a team as a code owner April 21, 2026 12:29
@github-actions github-actions Bot added the type/documentation Improvements or additions to documentation label Apr 21, 2026
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Apr 21, 2026

Deploying infrahub-sdk-python with  Cloudflare Pages  Cloudflare Pages

Latest commit: 979b472
Status: ✅  Deploy successful!
Preview URL: https://49084c61.infrahub-sdk-python.pages.dev
Branch Preview URL: https://knotty-dibble.infrahub-sdk-python.pages.dev

View logs

Spell out 'semver' and replace 'config/env' with the full words so
vale's spelling and word-swap rules pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 21, 2026

Codecov Report

❌ Patch coverage is 88.42975% with 14 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
infrahub_sdk/ctl/marketplace.py 88.13% 10 Missing and 4 partials ⚠️
@@            Coverage Diff             @@
##           stable     #952      +/-   ##
==========================================
+ Coverage   80.77%   80.80%   +0.03%     
==========================================
  Files         132      120      -12     
  Lines       10999    10457     -542     
  Branches     1681     1569     -112     
==========================================
- Hits         8884     8450     -434     
+ Misses       1566     1479      -87     
+ Partials      549      528      -21     
Flag Coverage Δ
integration-tests 41.58% <27.27%> (-1.18%) ⬇️
python-3.10 52.27% <88.42%> (-1.30%) ⬇️
python-3.11 52.25% <88.42%> (-1.32%) ⬇️
python-3.12 52.25% <88.42%> (-1.32%) ⬇️
python-3.13 52.27% <88.42%> (-1.28%) ⬇️
python-3.14 53.95% <88.42%> (-1.22%) ⬇️
python-filler-3.12 23.77% <0.82%> (+1.18%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
infrahub_sdk/ctl/cli_commands.py 72.00% <100.00%> (+0.22%) ⬆️
infrahub_sdk/ctl/config.py 67.85% <100.00%> (+0.58%) ⬆️
infrahub_sdk/ctl/marketplace.py 88.13% <88.13%> (ø)

... and 15 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@minitriga minitriga changed the title Auto-detect marketplace items; drop --load from download Add infrahubctl marketplace CLI for downloading schemas and collections Apr 21, 2026
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 12 files

You’re at about 95% of the monthly review limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="specs/001-marketplace-api-update/quickstart.md">

<violation number="1" location="specs/001-marketplace-api-update/quickstart.md:69">
P2: Update the schema success example to include the resolved type (`schema`) so it matches the documented requirement and new CLI behavior.</violation>
</file>

<file name="infrahub_sdk/ctl/marketplace.py">

<violation number="1" location="infrahub_sdk/ctl/marketplace.py:99">
P1: Partial probe failures are misclassified as not-found. A transport failure on either endpoint (when no 200 winner exists) should return a network error, not deterministic not-found.</violation>

<violation number="2" location="infrahub_sdk/ctl/marketplace.py:243">
P1: Network/HTTP errors during the actual download path can still exit with code 1 because uncaught `httpx` exceptions are handled by the default decorator exit code.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

else:
item_type = "schema"

if item_type == "collection":
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Network/HTTP errors during the actual download path can still exit with code 1 because uncaught httpx exceptions are handled by the default decorator exit code.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At infrahub_sdk/ctl/marketplace.py, line 243:

<comment>Network/HTTP errors during the actual download path can still exit with code 1 because uncaught `httpx` exceptions are handled by the default decorator exit code.</comment>

<file context>
@@ -0,0 +1,248 @@
+        else:
+            item_type = "schema"
+
+        if item_type == "collection":
+            if version:
+                console.print("[yellow]Warning: --version is ignored when downloading a collection.")
</file context>
Fix with Cubic

return True
return isinstance(r, httpx.Response) and r.status_code >= 500

if is_transport_failure(schema_resp) and is_transport_failure(collection_resp):
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Partial probe failures are misclassified as not-found. A transport failure on either endpoint (when no 200 winner exists) should return a network error, not deterministic not-found.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At infrahub_sdk/ctl/marketplace.py, line 99:

<comment>Partial probe failures are misclassified as not-found. A transport failure on either endpoint (when no 200 winner exists) should return a network error, not deterministic not-found.</comment>

<file context>
@@ -0,0 +1,248 @@
+            return True
+        return isinstance(r, httpx.Response) and r.status_code >= 500
+
+    if is_transport_failure(schema_resp) and is_transport_failure(collection_resp):
+        raise _fail(
+            "network",
</file context>
Fix with Cubic

For a schema:

```text
Downloaded acme/network-base v1.2.0 -> schemas/network-base.yml
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Update the schema success example to include the resolved type (schema) so it matches the documented requirement and new CLI behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At specs/001-marketplace-api-update/quickstart.md, line 69:

<comment>Update the schema success example to include the resolved type (`schema`) so it matches the documented requirement and new CLI behavior.</comment>

<file context>
@@ -0,0 +1,103 @@
+For a schema:
+
+```text
+Downloaded acme/network-base v1.2.0 -> schemas/network-base.yml
+```
+
</file context>
Suggested change
Downloaded acme/network-base v1.2.0 -> schemas/network-base.yml
Downloaded schema acme/network-base v1.2.0 -> schemas/network-base.yml
Fix with Cubic

CI runs markdownlint v0.40.0 which flags MD060 (table-column-style)
when the separator row uses compact pipes while the data rows are
padded. Match the repo's existing style (docs/python-sdk/introduction.mdx)
by padding the separator rows too.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@minitriga minitriga marked this pull request as draft April 21, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant