fix: marketplace build respects GITHUB_HOST for GHE repos#1009
fix: marketplace build respects GITHUB_HOST for GHE repos#1009sergio-sisternes-epam wants to merge 1 commit intomainfrom
Conversation
Thread the existing default_host() / build_https_clone_url() / AuthResolver pattern (used by apm install) through the marketplace build pipeline. Changes: - RefResolver: accept optional host parameter, use build_https_clone_url() instead of hardcoded github.com for git ls-remote URLs - MarketplaceBuilder: resolve tokens against configured host, use REST API for metadata fetch on GHES/GHE Cloud (raw.githubusercontent.com is github.com-only), skip metadata for non-GitHub hosts - Fix AuthResolver import scoping so classify_host() works when auth_resolver is pre-injected - Add GHE Cloud early-exit when no token (avoids pointless 401) Tests: - Update URL assertions to use urlparse (test convention) - Add 4 RefResolver GHE host tests - Add 3 metadata fetch path tests (GHES REST API, non-GitHub skip, GHE Cloud no-token skip) - Add builder host env test Docs: - CHANGELOG: Fixed entry under [Unreleased] - marketplace-authoring guide: GHES section - apm-usage authentication skill: marketplace build example Closes #1008 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
APM Review Panel VerdictDisposition: APPROVE (two minor pre-merge suggestions; neither is a blocker) Per-persona findingsPython Architect: This is a routine bug-fix PR: two existing classes ( OO / class diagram classDiagram
direction LR
class MarketplaceBuilder {
<<Builder>>
+_host: str
+_host_info: Optional[object]
+_github_token: Optional[str]
+_get_resolver() RefResolver
+_resolve_github_token() Optional[str]
+_fetch_remote_metadata(pkg) Optional[Dict]
+build() BuildResult
}
class RefResolver {
<<Service>>
+_host: str
+list_remote_refs(owner_repo) List[RemoteRef]
+resolve_ref_sha(owner_repo, ref) str
}
class AuthResolver {
<<Strategy>>
+classify_host(host) HostInfo
+resolve(host) AuthContext
}
class HostInfo {
<<ValueObject>>
+kind: str
+api_base: str
}
class AuthContext {
<<ValueObject>>
+token: str
+source: str
}
class default_host {
<<Pure>>
+default_host() str
+build_https_clone_url(host, repo) str
}
class ResolvedPackage {
<<ValueObject>>
+source_repo: str
+sha: str
+subdir: Optional[str]
}
MarketplaceBuilder *-- RefResolver : creates lazily
MarketplaceBuilder ..> AuthResolver : classify_host and resolve
MarketplaceBuilder ..> HostInfo : stores as _host_info
MarketplaceBuilder ..> ResolvedPackage : reads in _fetch_remote_metadata
MarketplaceBuilder ..> default_host : reads host at init
RefResolver ..> default_host : reads host at init
AuthResolver ..> HostInfo : returns
AuthResolver ..> AuthContext : returns
class MarketplaceBuilder:::touched
class RefResolver:::touched
classDef touched fill:#fff3b0,stroke:#d47600
Execution flow diagram flowchart TD
A["apm marketplace build\ncli.py"] --> B["MarketplaceBuilder.__init__()\nbuilder.py\n_host = default_host() or 'github.com'"]
B --> C["_prefetch_metadata(resolved)\nbuilder.py:589"]
C --> D["_resolve_github_token()\nbuilder.py:547\nsets _host_info AND _github_token"]
D --> E["[NET] AuthResolver.classify_host(self._host)\nsrc/apm_cli/core/auth.py:134\nreturns HostInfo(kind, api_base)"]
D --> F["[NET] resolver.resolve(self._host)\nreturns AuthContext.token"]
F --> G["pool.submit(_fetch_remote_metadata, pkg)\nbuilder.py:553\nfor each resolved package"]
G --> H{"host_kind?"}
H -->|"not github/ghe_cloud/ghes"| I["logger.debug skip\nreturn None"]
H -->|"ghe_cloud and no token"| J["logger.debug skip\nreturn None"]
H -->|"self._host == 'github.com'"| K["[NET] raw.githubusercontent.com\n/{source_repo}/{sha}/{path}/apm.yml\nurllib.request.urlopen"]
H -->|"ghes or ghe_cloud+token"| L["[NET] {api_base}/repos/{source_repo}\n/contents/{file}?ref={sha}\nAccept: application/vnd.github.raw\nurllib.request.urlopen"]
K --> M["yaml.safe_load(raw) -> dict"]
L --> M
M --> N["return metadata dict"]
Design patterns
CLI Logging Expert: All new log calls use DevX UX Expert: This is a silent behavior fix -- no new flags, no command surface changes. The key UX property preserved: Supply Chain Security Expert: Reviewed against the threat model:
No new supply-chain surface opened. Auth Expert: Activated -- the PR changes
OSS Growth Hacker: This fix completes APM's GHES story: CEO arbitrationSpecialists agree: this is a correct, well-tested, well-documented bug fix from an external contributor. The two minor suggestions (move Required actions before merge
Optional follow-ups
|
Description
apm marketplace buildhardcodedgithub.comin four places, soGITHUB_HOSThad no effect on ref resolution, token lookup, or metadata fetch. This PR threads the existingdefault_host()/build_https_clone_url()/AuthResolverpattern (already used byapm install) through the marketplace build pipeline.Fixes #1008
Changes
ref_resolver.py--RefResolveraccepts an optionalhostparameter (defaults toGITHUB_HOSTorgithub.com). Bothlist_remote_refs()andresolve_ref_sha()usebuild_https_clone_url()instead of hardcodedgithub.com.builder.py--MarketplaceBuilderstores a normalised host andHostInfo:_resolve_github_token()resolves against the configured host, not"github.com"_fetch_remote_metadata()uses the GitHub REST API for GHES/GHE Cloud (sinceraw.githubusercontent.comis github.com-only), skips metadata for non-GitHub hosts, and short-circuits tokenless GHE Cloud requestsAuthResolverimport moved to top oftryblock to fix a scoping issue whenauth_resolveris pre-injectedTests -- 8 new tests covering GHE host resolution, metadata fetch paths (GHES REST API, non-GitHub skip, GHE Cloud no-token skip), and builder host env. Existing URL assertions updated to use
urlparse.Docs -- CHANGELOG entry, marketplace-authoring guide GHES section, apm-usage skill resource update.
Type of change
Testing