Improve GitHub source retrieval by using latest release endpoint and enhancing version handling

This commit is contained in:
crazywhalecc
2026-04-30 11:05:49 +08:00
parent abfdae256a
commit 0588401ee3

View File

@@ -98,6 +98,21 @@ class Downloader
{ {
logger()->debug("finding {$name} source from github {$type} tarball"); logger()->debug("finding {$name} source from github {$type} tarball");
$source['query'] ??= ''; $source['query'] ??= '';
// Use /releases/latest when possible: it returns the semantically latest stable
// release regardless of publish order, avoiding issues with concurrent release branches.
if ($type === 'releases' && empty($source['query']) && !($source['match'] ?? null)) {
$data = json_decode(self::curlExec(
url: "https://api.github.com/repos/{$source['repo']}/releases/latest",
hooks: [[CurlHook::class, 'setupGithubToken']],
retries: self::getRetryAttempts()
), true, 512, JSON_THROW_ON_ERROR);
if (!is_array($data) || empty($data['tarball_url'])) {
throw new DownloaderException("failed to find {$name} source");
}
$url = $data['tarball_url'];
$version = $data['tag_name'] ?? $data['name'] ?? null;
} else {
$data = json_decode(self::curlExec( $data = json_decode(self::curlExec(
url: "https://api.github.com/repos/{$source['repo']}/{$type}{$source['query']}", url: "https://api.github.com/repos/{$source['repo']}/{$type}{$source['query']}",
hooks: [[CurlHook::class, 'setupGithubToken']], hooks: [[CurlHook::class, 'setupGithubToken']],
@@ -105,6 +120,7 @@ class Downloader
), true, 512, JSON_THROW_ON_ERROR); ), true, 512, JSON_THROW_ON_ERROR);
$url = null; $url = null;
$version = null;
foreach ($data as $rel) { foreach ($data as $rel) {
if (($rel['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) { if (($rel['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) {
continue; continue;
@@ -114,16 +130,19 @@ class Downloader
} }
if (!($source['match'] ?? null)) { if (!($source['match'] ?? null)) {
$url = $rel['tarball_url'] ?? null; $url = $rel['tarball_url'] ?? null;
$version = $rel['tag_name'] ?? $rel['name'] ?? null;
break; break;
} }
if (preg_match('|' . $source['match'] . '|', $rel['tarball_url'])) { if (preg_match('|' . $source['match'] . '|', $rel['tarball_url'])) {
$url = $rel['tarball_url']; $url = $rel['tarball_url'];
$version = $rel['tag_name'] ?? $rel['name'] ?? null;
break; break;
} }
} }
if (!$url) { if (!$url) {
throw new DownloaderException("failed to find {$name} source"); throw new DownloaderException("failed to find {$name} source");
} }
}
$headers = self::curlExec( $headers = self::curlExec(
url: $url, url: $url,
method: 'HEAD', method: 'HEAD',
@@ -134,7 +153,7 @@ class Downloader
if ($matches) { if ($matches) {
$filename = $matches['filename']; $filename = $matches['filename'];
} else { } else {
$filename = "{$name}-" . ($type === 'releases' ? $data['tag_name'] : $data['name']) . '.tar.gz'; $filename = "{$name}-" . ($version ?? 'latest') . '.tar.gz';
} }
return [$url, $filename]; return [$url, $filename];