Skip to content
docsv0.13.1

GitHubDownloader

Downloads plugin releases from GitHub. Uses GitHub REST API v3 (no auth required for public repos). Optionally uses GITHUB_TOKEN env var for private repos or rate limits. Transport is a seam. With no PSR-18 client injected it goes over `file_get_contents()` with a stream context, exactly as it always has — nothing a host has to change. Injecting one is what makes everything above the transport reachable from a test: version listing, constraint resolution, the zipball download and its fallback tag were all unreachable while the only way in was the network. The same seam `milpa/ai-gateway` and `milpa/mcp-client` already carry. GitHub is one source of plugins, not the only conceivable one: what the installer actually depends on is {@see PluginDownloaderInterface}. The two public methods beyond that port — {@see self::listVersions()} and {@see self::getRepoInfo()} — are GitHub facts, and stay off it.

GitHubDownloader::__construct()

public function __construct(?string $token = null, ?Psr\Http\Client\ClientInterface $httpClient = null, ?Psr\Http\Message\RequestFactoryInterface $requestFactory = null):

Parameters

Parameters of __construct()
NameTypeDescription
$token?string
$httpClient?Psr\Http\Client\ClientInterface
$requestFactory?Psr\Http\Message\RequestFactoryInterface

GitHubDownloader::parseSource()

public function parseSource(string $source): array

Parse a source string into owner, repo, and optional version constraint. Formats: "acme/mail-plugin" → owner=acme, repo=mail-plugin, constraint=null "acme/mail-plugin:^2.0" → owner=acme, repo=mail-plugin, constraint=^2.0 "https://github.com/acme/mail-plugin" → owner=acme, repo=mail-plugin, constraint=null

Parameters

Parameters of parseSource()
NameTypeDescription
$sourcestring

Throws

\InvalidArgumentException

GitHubDownloader::listVersions()

public function listVersions(string $owner, string $repo): array

List available versions (releases + tags) from GitHub. Filters to valid semver only.

Parameters

Parameters of listVersions()
NameTypeDescription
$ownerstring
$repostring

Returns

Sorted descending (newest first)

GitHubDownloader::resolveVersion()

public function resolveVersion(string $owner, string $repo, ?string $constraint = null): Milpa\ValueObjects\SemanticVersion

Find the best matching version for a constraint.

Parameters

Parameters of resolveVersion()
NameTypeDescription
$ownerstring
$repostring
$constraint(string | null)Semver constraint (e.g., "^2.0", ">=1.5"). If null, returns latest stable.

Throws

\RuntimeException If no matching version found

GitHubDownloader::download()

public function download(string $owner, string $repo, Milpa\ValueObjects\SemanticVersion $version): string

Download and extract a specific version to a temporary directory.

Parameters

Parameters of download()
NameTypeDescription
$ownerstring
$repostring
$versionMilpa\ValueObjects\SemanticVersion

Returns

Path to the extracted plugin directory

Throws

\RuntimeException On download or extraction failure

GitHubDownloader::getRepoInfo()

public function getRepoInfo(string $owner, string $repo): ?array

Get repository info from GitHub API.

Parameters

Parameters of getRepoInfo()
NameTypeDescription
$ownerstring
$repostring

GitHubDownloader::cleanup()

public function cleanup(string $path): void

Clean up a temporary directory recursively.

Parameters

Parameters of cleanup()
NameTypeDescription
$pathstring