Add support for ghcr.io (#6134)

Signed-off-by: Jean-Yves <7360784+docjyJ@users.noreply.github.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
Co-authored-by: Simon L. <szaimen@e.mail.de>
This commit is contained in:
Jean-Yves 2025-03-13 12:55:18 +01:00 committed by GitHub
parent a6246f9544
commit e97d4b0a3e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 183 additions and 103 deletions

View file

@ -0,0 +1,62 @@
<?php
namespace AIO\Docker;
use GuzzleHttp\Client;
readonly class GitHubContainerRegistryManager
{
private Client $guzzleClient;
public function __construct()
{
$this->guzzleClient = new Client();
}
public function GetLatestDigestOfTag(string $name, string $tag): ?string
{
$cacheKey = 'ghcr-manifest-' . $name . $tag;
$cachedVersion = apcu_fetch($cacheKey);
if ($cachedVersion !== false && is_string($cachedVersion)) {
return $cachedVersion;
}
// If one of the links below should ever become outdated, we can still upgrade the mastercontainer via the webinterface manually by opening '/api/docker/getwatchtower'
try {
$authTokenRequest = $this->guzzleClient->request(
'GET',
'https://ghcr.io/token?scope=repository:' . $name . ':pull'
);
$body = $authTokenRequest->getBody()->getContents();
$decodedBody = json_decode($body, true);
if (isset($decodedBody['token'])) {
$authToken = $decodedBody['token'];
$manifestRequest = $this->guzzleClient->request(
'HEAD',
'https://ghcr.io/v2/' . $name . '/manifests/' . $tag,
[
'headers' => [
'Accept' => 'application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.docker.distribution.manifest.v2+json',
'Authorization' => 'Bearer ' . $authToken,
],
]
);
$responseHeaders = $manifestRequest->getHeader('docker-content-digest');
if (count($responseHeaders) === 1) {
$latestVersion = $responseHeaders[0];
apcu_add($cacheKey, $latestVersion, 600);
return $latestVersion;
}
}
error_log('Could not get digest of container ' . $name . ':' . $tag);
return null;
} catch (\Exception $e) {
error_log('Could not get digest of container ' . $name . ':' . $tag . ' ' . $e->getMessage());
return null;
}
}
}