Add HostedPackageBin downloader and enhance artifact handling

This commit is contained in:
crazywhalecc
2025-12-05 14:39:05 +08:00
committed by Jerry Ma
parent 52553fb5ed
commit 7fa6fd08d4
6 changed files with 111 additions and 14 deletions

View File

@@ -21,6 +21,26 @@ class GitHubRelease implements DownloadTypeInterface, ValidatorInterface
private ?string $version = null;
public function getGitHubReleases(string $name, string $repo, bool $prefer_stable = true): array
{
logger()->debug("Fetching {$name} GitHub releases from {$repo}");
$url = str_replace('{repo}', $repo, self::API_URL);
$headers = $this->getGitHubTokenHeaders();
$data2 = default_shell()->executeCurl($url, headers: $headers);
$data = json_decode($data2 ?: '', true);
if (!is_array($data)) {
throw new DownloaderException("Failed to get GitHub release API info for {$repo} from {$url}");
}
$releases = [];
foreach ($data as $release) {
if ($prefer_stable && $release['prerelease'] === true) {
continue;
}
$releases[] = $release;
}
return $releases;
}
/**
* Get the latest GitHub release assets for a given repository.
* match_asset is provided, only return the asset that matches the regex.

View File

@@ -7,6 +7,11 @@ namespace StaticPHP\Artifact\Downloader\Type;
trait GitHubTokenSetupTrait
{
public function getGitHubTokenHeaders(): array
{
return self::getGitHubTokenHeadersStatic();
}
public static function getGitHubTokenHeadersStatic(): array
{
// GITHUB_TOKEN support
if (($token = getenv('GITHUB_TOKEN')) !== false && ($user = getenv('GITHUB_USER')) !== false) {

View File

@@ -0,0 +1,63 @@
<?php
declare(strict_types=1);
namespace StaticPHP\Artifact\Downloader\Type;
use StaticPHP\Artifact\ArtifactDownloader;
use StaticPHP\Artifact\Downloader\DownloadResult;
use StaticPHP\Exception\DownloaderException;
use StaticPHP\Runtime\SystemTarget;
class HostedPackageBin implements DownloadTypeInterface
{
use GitHubTokenSetupTrait;
public const string BASE_REPO = 'static-php/package-bin';
public const array ASSET_MATCHES = [
'linux' => '{name}-{arch}-{os}-{libc}-{libcver}.txz',
'darwin' => '{name}-{arch}-{os}.txz',
'windows' => '{name}-{arch}-{os}.tgz',
];
private static array $release_info = [];
public static function getReleaseInfo(): array
{
if (empty(self::$release_info)) {
$rel = (new GitHubRelease())->getGitHubReleases('hosted', self::BASE_REPO);
if (empty($rel)) {
throw new DownloaderException('No releases found for hosted package-bin');
}
self::$release_info = $rel[0];
}
return self::$release_info;
}
public function download(string $name, array $config, ArtifactDownloader $downloader): DownloadResult
{
$info = self::getReleaseInfo();
$replace = [
'{name}' => $name,
'{arch}' => SystemTarget::getTargetArch(),
'{os}' => strtolower(SystemTarget::getTargetOS()),
'{libc}' => SystemTarget::getLibc() ?? 'default',
'{libcver}' => SystemTarget::getLibcVersion() ?? 'default',
];
$find_str = str_replace(array_keys($replace), array_values($replace), self::ASSET_MATCHES[strtolower(SystemTarget::getTargetOS())]);
foreach ($info['assets'] as $asset) {
if ($asset['name'] === $find_str) {
$download_url = $asset['browser_download_url'];
$filename = $asset['name'];
$version = ltrim($info['tag_name'], 'v');
logger()->debug("Downloading hosted package-bin {$name} version {$version} from GitHub: {$download_url}");
$path = DOWNLOAD_PATH . DIRECTORY_SEPARATOR . $filename;
$headers = $this->getGitHubTokenHeaders();
default_shell()->executeCurlDownload($download_url, $path, headers: $headers, retries: $downloader->getRetry());
return DownloadResult::archive($filename, $config, extract: $config['extract'] ?? null, version: $version);
}
}
throw new DownloaderException("No matching asset found for hosted package-bin {$name} with criteria: {$find_str}");
}
}