Skip to content

feat: Support Artifactory-hosted marketplace indexes #506

@danielmeppiel

Description

@danielmeppiel

Problem

Marketplace indexes (marketplace.json) are currently fetched exclusively via GitHub API (MarketplaceSource.host is hardcoded to "github.com"). In air-gapped or Artifactory-proxied environments, apm marketplace browse/search commands fail because they cannot reach GitHub directly.

What works today: Plugins resolved from marketplaces flow through the standard download pipeline, so PROXY_REGISTRY_URL and PROXY_REGISTRY_ONLY are respected for the actual package download. The gap is only in fetching the marketplace index itself.

Proposed Solution

Allow MarketplaceSource to use the configured registry proxy when fetching marketplace.json:

  1. Proxy-aware fetch -- When PROXY_REGISTRY_URL is set, fetch_marketplace() in client.py should construct the raw file URL through the proxy (e.g., {PROXY_REGISTRY_URL}/{owner}/{repo}/raw/{path}) instead of hitting raw.githubusercontent.com directly.

  2. Explicit Artifactory marketplace registration -- Allow apm marketplace add to accept an FQDN-prefixed repo:

    apm marketplace add skills art.example.com/artifactory/github/anthropics/skills
  3. Air-gapped enforcement -- When PROXY_REGISTRY_ONLY=1, reject marketplace fetches that would bypass the proxy.

Architecture Notes

  • MarketplaceSource in models.py needs optional host and registry_prefix fields (same pattern as DependencyReference)
  • _fetch_file() in client.py needs a proxy-aware code path using RegistryConfig.get_headers() for auth
  • Cache key should include the host to avoid collisions between GitHub and proxied versions
  • Lockfile provenance fields (discovered_via, marketplace_plugin_name) are orthogonal and need no changes

Current Behavior

Operation Direct GitHub Via Proxy Air-Gapped
marketplace browse/search Works Fails Fails
install NAME@MARKETPLACE (after resolution) Works Works Works
install from lockfile Works Works Works

Desired Behavior

Operation Direct GitHub Via Proxy Air-Gapped
marketplace browse/search Works Works Works
install NAME@MARKETPLACE Works Works Works
install from lockfile Works Works Works

References

  • Registry proxy implementation: src/apm_cli/deps/registry_proxy.py
  • Marketplace client: src/apm_cli/marketplace/client.py
  • Marketplace models: src/apm_cli/marketplace/models.py
  • Artifactory docs: docs/src/content/docs/guides/artifactory.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestmarketplaceMarketplace federation: marketplace.json publishing, sourcing, and federation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions