From 99ca2c401c668bfd20db699f809f4809f16a24dd Mon Sep 17 00:00:00 2001 From: Lars Gebhardt-Kusche Date: Thu, 25 Jun 2026 01:33:21 +0200 Subject: [PATCH] adsad --- config/gitea.php | 2 +- config/prod/gitea.php | 2 +- config/staging/gitea.php | 2 +- .../GiteaDeployStatusService.php | 114 ++++++++++++++++-- 4 files changed, 107 insertions(+), 13 deletions(-) diff --git a/config/gitea.php b/config/gitea.php index 55e8b2d0..d9a4a879 100644 --- a/config/gitea.php +++ b/config/gitea.php @@ -8,6 +8,6 @@ return [ 'owner' => 'private', 'repositories' => [], 'poll_idle_seconds' => 5, - 'poll_running_seconds' => 1, + 'poll_running_seconds' => 3, 'visibility' => 'admins', ]; diff --git a/config/prod/gitea.php b/config/prod/gitea.php index 55e8b2d0..d9a4a879 100644 --- a/config/prod/gitea.php +++ b/config/prod/gitea.php @@ -8,6 +8,6 @@ return [ 'owner' => 'private', 'repositories' => [], 'poll_idle_seconds' => 5, - 'poll_running_seconds' => 1, + 'poll_running_seconds' => 3, 'visibility' => 'admins', ]; diff --git a/config/staging/gitea.php b/config/staging/gitea.php index 3b653a85..6cd63359 100644 --- a/config/staging/gitea.php +++ b/config/staging/gitea.php @@ -8,6 +8,6 @@ return [ 'owner' => 'private', 'repositories' => [], 'poll_idle_seconds' => 5, - 'poll_running_seconds' => 1, + 'poll_running_seconds' => 3, 'visibility' => 'admins', ]; diff --git a/system/addons/gitea-deploy-status/GiteaDeployStatusService.php b/system/addons/gitea-deploy-status/GiteaDeployStatusService.php index aef4aabd..9e8abd62 100644 --- a/system/addons/gitea-deploy-status/GiteaDeployStatusService.php +++ b/system/addons/gitea-deploy-status/GiteaDeployStatusService.php @@ -6,6 +6,8 @@ namespace SystemAddons\GiteaDeployStatus; final class GiteaDeployStatusService { + private const REPOSITORY_CACHE_TTL = 60; + /** * @param array $config */ @@ -85,9 +87,19 @@ final class GiteaDeployStatusService try { $repositories = $this->resolveRepositories(); $runningJobs = []; + $warnings = []; 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) { if (!$this->isRunActive($run)) { @@ -122,6 +134,7 @@ final class GiteaDeployStatusService 'message' => $message, 'running_jobs' => $runningJobs, 'repositories_checked' => count($repositories), + 'warnings' => $warnings, 'diagnostics' => $this->diagnostics(), ]; } @@ -129,9 +142,14 @@ final class GiteaDeployStatusService return [ 'state' => 'idle', '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' => [], 'repositories_checked' => count($repositories), + 'warnings' => $warnings, 'diagnostics' => $this->diagnostics(), ]; } catch (\Throwable $exception) { @@ -161,6 +179,11 @@ final class GiteaDeployStatusService */ private function resolveRepositories(): array { + $cached = $this->loadRepositoryCache(); + if ($cached !== []) { + return $cached; + } + $configured = []; foreach ((array) ($this->config['repositories'] ?? []) as $entry) { $normalized = $this->normalizeRepositoryEntry($entry); @@ -170,7 +193,9 @@ final class GiteaDeployStatusService } if ($configured !== []) { - return array_values($configured); + $resolved = array_values($configured); + $this->storeRepositoryCache($resolved); + return $resolved; } $repositories = []; @@ -186,22 +211,34 @@ final class GiteaDeployStatusService foreach ($this->normalizeRepositoriesPayload($payload) as $repository) { $repositories[$repository['full_name']] = $repository; } - } catch (\Throwable) { + } catch (\RuntimeException $exception) { + if ($this->isForbiddenException($exception)) { + continue; + } + continue; } } } - $payload = $this->requestJson('/user/repos?limit=100&page=1'); - foreach ($this->normalizeRepositoriesPayload($payload) as $repository) { - $repositories[$repository['full_name']] = $repository; + try { + $payload = $this->requestJson('/user/repos?limit=100&page=1'); + foreach ($this->normalizeRepositoriesPayload($payload) as $repository) { + $repositories[$repository['full_name']] = $repository; + } + } catch (\RuntimeException $exception) { + if (!$this->isForbiddenException($exception) || $repositories === []) { + throw $exception; + } } if ($repositories === []) { 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 { - $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)) { return array_values(array_filter($payload['workflow_runs'], 'is_array')); @@ -371,7 +408,7 @@ final class GiteaDeployStatusService } 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); @@ -402,4 +439,61 @@ final class GiteaDeployStatusService return $decoded; } + + private function isForbiddenException(\RuntimeException $exception): bool + { + return str_contains($exception->getMessage(), 'HTTP 403'); + } + + /** + * @return array + */ + 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 $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'; + } }