Skip to content

[BUG] apm pack omits per-plugin version for INTERNAL/private github.com repos (raw.githubusercontent.com 404, no REST fallback) #1847

Description

@rgarciapariente

Describe the bug
apm pack does not emit the per-plugin version field in the generated Claude marketplace.json when the marketplace packages are remote git-subdir references to a GitHub.com repository with INTERNAL (or private) visibility.

Root cause: the per-plugin version is sourced from a best-effort "metadata enrichment" fetch of each resolved package's remote apm.yml(marketplace/builder.py::_fetch_remote_metadata). For hosts classified as github.com, APM fetches it from https://raw.githubusercontent.com/.... For INTERNAL/enterprise repos, raw.githubusercontent.com returns HTTP 404 even with a valid token, while the GitHubREST /contents API serves the file correctly. APM only falls back to the REST API for GHES/GHE-Cloud hosts, never for github.com. Because the fetch fails, version is silently omitted.

This is not a permissions problem: APM resolves and sends a valid token (source=gh-auth-token), and the same 404 happens both locally and in CI.

Secondary factor: the root apm.yml marketplace entries pin a semver range (version: "^1.0.0"), which _is_display_version() deliberately rejects, so version depends exclusively on the remote fetch that is failing.

To Reproduce
Steps to reproduce the behavior:

  1. Have a marketplace repo on github.com with INTERNAL (or private) visibility, whose root apm.yml declares marketplace.packages[] as remote git-subdir entries (source: <owner>/<repo> + subdir: + version: "^1.0.0"), with versioning.strategy: tag_pattern.2. Ensure the referenced packages are tagged ({name}-v{version}) so resolution succeeds, and that you are authenticated (gh auth login/ a valid token).
  2. Run command: apm pack -m claude --marketplace-path claude=build/marketplace.json
  3. Inspect the output: every entry under .plugins[] has name, description, and source, but no version field.
  4. Run with APM_LOG_LEVEL=DEBUG and observe, for every entry:
    DEBUG apm_cli.marketplace.builder Resolved GitHub token for metadata fetch (source=gh-auth-token)
    DEBUG apm_cli.marketplace.builder Could not fetch remote metadata for <name>
        urllib.error.HTTPError: HTTP Error 404: Not Found   (builder.py:975)
    
  5. Confirm the endpoint mismatch directly (replace <sha>):
    # raw CDN — fails even WITH a token
    curl -s -m 5 -o /dev/null -w "%{http_code}\n" \
      -H "Authorization: token $(gh auth token)" \
      https://raw.githubusercontent.com/<owner>/<repo>/<sha>/<subdir>/apm.yml
    # -> 404
    
    # REST contents API — works
    gh api repos/<owner>/<repo>/contents/<subdir>/apm.yml?ref=<sha> --jq .name
    # -> apm.yml

Expected behavior
apm pack should populate the per-plugin version for remote entries on INTERNAL/private github.com repositories — e.g. by falling back to the GitHub REST /contents API (which works with the token) when raw.githubusercontent.com returns 404, instead of silently droppingthe version field. Metadata enrichment should not depend on a CDN that does not serve INTERNAL-visibility repos.

Environment (please complete the following information):

  • OS: Windows (MINGW64_NT-10.0)
  • Python Version: 3.12.10
  • APM Version: 0.20.0
  • VSCode Version (if relevant): N/A

Logs

DEBUG apm_cli.marketplace.builder Resolved GitHub token for metadata fetch (source=gh-auth-token)
DEBUG apm_cli.marketplace.builder Could not fetch remote metadata for foundations-core
  File ".../apm_cli/marketplace/builder.py", line 975, in _fetch_remote_metadata
urllib.error.HTTPError: HTTP Error 404: Not Found

(identical 404 for all 12 marketplace entries)

Reproduced endpoint behavior:

  • raw.githubusercontent.com/.../apm.yml (with Authorization: token): HTTP 404
  • gh api repos/.../contents/.../apm.yml?ref=<sha>: returns the file (200)

Additional context

  • Relevant code: marketplace/builder.py::_fetch_remote_metadata (host branch: github.com → raw CDN; else → REST API) and marketplace/output_mappers.py (_is_display_version rejects semver ranges, so version relies solely on the remote-metadata fetch).
  • Affects both local runs and CI; independent of token/permissions.
  • Workaround on the consumer side: post-process the generated marketplace.json to inject each entry's version read from the local leafapm.yml (the single source of truth), avoiding the remote fetch entirely.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/distributionInstallers (curl/PowerShell/Brew/Scoop), self-update, devcontainer, codespaces.area/marketplacemarketplace.json schema, federation, authoring suite, source parity.status/acceptedHuman scope approval; verify the issue's approval record and review contact before work.status/triagedAutomated advice completed; deduplication only. Not human approval; silence is not approval.theme/portabilityOne manifest, every target. Multi-target deploy, marketplace, packaging, install.type/bugSomething does not work as documented.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions