adsad
This commit is contained in:
@@ -8,6 +8,6 @@ return [
|
|||||||
'owner' => 'private',
|
'owner' => 'private',
|
||||||
'repositories' => [],
|
'repositories' => [],
|
||||||
'poll_idle_seconds' => 5,
|
'poll_idle_seconds' => 5,
|
||||||
'poll_running_seconds' => 1,
|
'poll_running_seconds' => 3,
|
||||||
'visibility' => 'admins',
|
'visibility' => 'admins',
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ return [
|
|||||||
'owner' => 'private',
|
'owner' => 'private',
|
||||||
'repositories' => [],
|
'repositories' => [],
|
||||||
'poll_idle_seconds' => 5,
|
'poll_idle_seconds' => 5,
|
||||||
'poll_running_seconds' => 1,
|
'poll_running_seconds' => 3,
|
||||||
'visibility' => 'admins',
|
'visibility' => 'admins',
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ return [
|
|||||||
'owner' => 'private',
|
'owner' => 'private',
|
||||||
'repositories' => [],
|
'repositories' => [],
|
||||||
'poll_idle_seconds' => 5,
|
'poll_idle_seconds' => 5,
|
||||||
'poll_running_seconds' => 1,
|
'poll_running_seconds' => 3,
|
||||||
'visibility' => 'admins',
|
'visibility' => 'admins',
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ namespace SystemAddons\GiteaDeployStatus;
|
|||||||
|
|
||||||
final class GiteaDeployStatusService
|
final class GiteaDeployStatusService
|
||||||
{
|
{
|
||||||
|
private const REPOSITORY_CACHE_TTL = 60;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $config
|
* @param array<string, mixed> $config
|
||||||
*/
|
*/
|
||||||
@@ -85,9 +87,19 @@ final class GiteaDeployStatusService
|
|||||||
try {
|
try {
|
||||||
$repositories = $this->resolveRepositories();
|
$repositories = $this->resolveRepositories();
|
||||||
$runningJobs = [];
|
$runningJobs = [];
|
||||||
|
$warnings = [];
|
||||||
|
|
||||||
foreach ($repositories as $repository) {
|
foreach ($repositories as $repository) {
|
||||||
$runs = $this->listActionRuns((string) $repository['owner'], (string) $repository['repo']);
|
try {
|
||||||
|
$runs = $this->listActionRuns((string) $repository['owner'], (string) $repository['repo']);
|
||||||
|
} catch (\RuntimeException $exception) {
|
||||||
|
if ($this->isForbiddenException($exception)) {
|
||||||
|
$warnings[] = sprintf('403 fuer %s uebersprungen.', (string) $repository['full_name']);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($runs as $run) {
|
foreach ($runs as $run) {
|
||||||
if (!$this->isRunActive($run)) {
|
if (!$this->isRunActive($run)) {
|
||||||
@@ -122,6 +134,7 @@ final class GiteaDeployStatusService
|
|||||||
'message' => $message,
|
'message' => $message,
|
||||||
'running_jobs' => $runningJobs,
|
'running_jobs' => $runningJobs,
|
||||||
'repositories_checked' => count($repositories),
|
'repositories_checked' => count($repositories),
|
||||||
|
'warnings' => $warnings,
|
||||||
'diagnostics' => $this->diagnostics(),
|
'diagnostics' => $this->diagnostics(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -129,9 +142,14 @@ final class GiteaDeployStatusService
|
|||||||
return [
|
return [
|
||||||
'state' => 'idle',
|
'state' => 'idle',
|
||||||
'poll_seconds' => $idleSeconds,
|
'poll_seconds' => $idleSeconds,
|
||||||
'message' => sprintf('Kein laufendes Gitea-Deployment in %d Repositories.', count($repositories)),
|
'message' => sprintf(
|
||||||
|
'Kein laufendes Gitea-Deployment in %d Repositories.%s',
|
||||||
|
count($repositories),
|
||||||
|
$warnings !== [] ? ' ' . implode(' ', array_slice($warnings, 0, 3)) : ''
|
||||||
|
),
|
||||||
'running_jobs' => [],
|
'running_jobs' => [],
|
||||||
'repositories_checked' => count($repositories),
|
'repositories_checked' => count($repositories),
|
||||||
|
'warnings' => $warnings,
|
||||||
'diagnostics' => $this->diagnostics(),
|
'diagnostics' => $this->diagnostics(),
|
||||||
];
|
];
|
||||||
} catch (\Throwable $exception) {
|
} catch (\Throwable $exception) {
|
||||||
@@ -161,6 +179,11 @@ final class GiteaDeployStatusService
|
|||||||
*/
|
*/
|
||||||
private function resolveRepositories(): array
|
private function resolveRepositories(): array
|
||||||
{
|
{
|
||||||
|
$cached = $this->loadRepositoryCache();
|
||||||
|
if ($cached !== []) {
|
||||||
|
return $cached;
|
||||||
|
}
|
||||||
|
|
||||||
$configured = [];
|
$configured = [];
|
||||||
foreach ((array) ($this->config['repositories'] ?? []) as $entry) {
|
foreach ((array) ($this->config['repositories'] ?? []) as $entry) {
|
||||||
$normalized = $this->normalizeRepositoryEntry($entry);
|
$normalized = $this->normalizeRepositoryEntry($entry);
|
||||||
@@ -170,7 +193,9 @@ final class GiteaDeployStatusService
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($configured !== []) {
|
if ($configured !== []) {
|
||||||
return array_values($configured);
|
$resolved = array_values($configured);
|
||||||
|
$this->storeRepositoryCache($resolved);
|
||||||
|
return $resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
$repositories = [];
|
$repositories = [];
|
||||||
@@ -186,22 +211,34 @@ final class GiteaDeployStatusService
|
|||||||
foreach ($this->normalizeRepositoriesPayload($payload) as $repository) {
|
foreach ($this->normalizeRepositoriesPayload($payload) as $repository) {
|
||||||
$repositories[$repository['full_name']] = $repository;
|
$repositories[$repository['full_name']] = $repository;
|
||||||
}
|
}
|
||||||
} catch (\Throwable) {
|
} catch (\RuntimeException $exception) {
|
||||||
|
if ($this->isForbiddenException($exception)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$payload = $this->requestJson('/user/repos?limit=100&page=1');
|
try {
|
||||||
foreach ($this->normalizeRepositoriesPayload($payload) as $repository) {
|
$payload = $this->requestJson('/user/repos?limit=100&page=1');
|
||||||
$repositories[$repository['full_name']] = $repository;
|
foreach ($this->normalizeRepositoriesPayload($payload) as $repository) {
|
||||||
|
$repositories[$repository['full_name']] = $repository;
|
||||||
|
}
|
||||||
|
} catch (\RuntimeException $exception) {
|
||||||
|
if (!$this->isForbiddenException($exception) || $repositories === []) {
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($repositories === []) {
|
if ($repositories === []) {
|
||||||
throw new \RuntimeException('Keine Repositories fuer den Gitea-Status gefunden.');
|
throw new \RuntimeException('Keine Repositories fuer den Gitea-Status gefunden.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_values($repositories);
|
$resolved = array_values($repositories);
|
||||||
|
$this->storeRepositoryCache($resolved);
|
||||||
|
return $resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -296,7 +333,7 @@ final class GiteaDeployStatusService
|
|||||||
*/
|
*/
|
||||||
private function listActionRuns(string $owner, string $repo): array
|
private function listActionRuns(string $owner, string $repo): array
|
||||||
{
|
{
|
||||||
$payload = $this->requestJson('/repos/' . rawurlencode($owner) . '/' . rawurlencode($repo) . '/actions/runs?limit=10&page=1');
|
$payload = $this->requestJson('/repos/' . rawurlencode($owner) . '/' . rawurlencode($repo) . '/actions/runs?limit=1&page=1');
|
||||||
|
|
||||||
if (is_array($payload['workflow_runs'] ?? null)) {
|
if (is_array($payload['workflow_runs'] ?? null)) {
|
||||||
return array_values(array_filter($payload['workflow_runs'], 'is_array'));
|
return array_values(array_filter($payload['workflow_runs'], 'is_array'));
|
||||||
@@ -371,7 +408,7 @@ final class GiteaDeployStatusService
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($status >= 400) {
|
if ($status >= 400) {
|
||||||
throw new \RuntimeException('Gitea-API antwortet mit HTTP ' . $status . '.');
|
throw new \RuntimeException('Gitea-API antwortet mit HTTP ' . $status . ' fuer ' . $path . '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$decoded = json_decode($raw, true);
|
$decoded = json_decode($raw, true);
|
||||||
@@ -402,4 +439,61 @@ final class GiteaDeployStatusService
|
|||||||
|
|
||||||
return $decoded;
|
return $decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function isForbiddenException(\RuntimeException $exception): bool
|
||||||
|
{
|
||||||
|
return str_contains($exception->getMessage(), 'HTTP 403');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{owner: string, repo: string, full_name: string}>
|
||||||
|
*/
|
||||||
|
private function loadRepositoryCache(): array
|
||||||
|
{
|
||||||
|
$cacheFile = $this->repositoryCacheFile();
|
||||||
|
if (!is_file($cacheFile)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$mtime = filemtime($cacheFile);
|
||||||
|
if ($mtime === false || ($mtime + self::REPOSITORY_CACHE_TTL) < time()) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$raw = file_get_contents($cacheFile);
|
||||||
|
if (!is_string($raw) || trim($raw) === '') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoded = json_decode($raw, true);
|
||||||
|
if (!is_array($decoded)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->normalizeRepositoriesPayload($decoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, array{owner: string, repo: string, full_name: string}> $repositories
|
||||||
|
*/
|
||||||
|
private function storeRepositoryCache(array $repositories): void
|
||||||
|
{
|
||||||
|
$cacheFile = $this->repositoryCacheFile();
|
||||||
|
$directory = dirname($cacheFile);
|
||||||
|
|
||||||
|
if (!is_dir($directory)) {
|
||||||
|
@mkdir($directory, 0775, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@file_put_contents($cacheFile, json_encode(array_values($repositories), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function repositoryCacheFile(): string
|
||||||
|
{
|
||||||
|
$owner = trim((string) ($this->config['owner'] ?? ''));
|
||||||
|
$scope = $owner !== '' ? $owner : 'user';
|
||||||
|
$safeScope = preg_replace('/[^a-z0-9._-]+/i', '-', $scope) ?: 'user';
|
||||||
|
|
||||||
|
return sys_get_temp_dir() . '/desktop-gitea-repositories-' . $safeScope . '.json';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user