• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

visavi / rotor / 28980764164

08 Jul 2026 10:41PM UTC coverage: 32.95% (+0.2%) from 32.784%
28980764164

push

github

visavi
Улучшена установка, добавлены проверки на существование таблиц, добавлен сброс кеша

32 of 40 new or added lines in 2 files covered. (80.0%)

1864 of 5657 relevant lines covered (32.95%)

3.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.43
/app/Services/GithubService.php
1
<?php
2

3
namespace App\Services;
4

5
use Illuminate\Support\Facades\Cache;
6
use Illuminate\Support\Facades\Http;
7
use RuntimeException;
8
use Throwable;
9

10
class GithubService
11
{
12
    protected string $baseUrl = 'https://api.github.com/repos/visavi/rotor/';
13
    protected int $defaultCacheTtl = 3600;
14

15
    /**
16
     * Получает последние коммиты
17
     */
18
    public function getLatestCommits(): array
×
19
    {
NEW
20
        return $this->cachedFetch('commits', fn () => $this->fetchGitHubData(
×
NEW
21
            endpoint: 'commits',
×
NEW
22
            params: ['per_page' => 100]
×
NEW
23
        ));
×
24
    }
25

26
    /**
27
     * Get last release
28
     */
29
    public function getLatestRelease(): array
1✔
30
    {
31
        return $this->getLatestReleases()[0] ?? [];
1✔
32
    }
33

34
    /**
35
     * Get last version
36
     */
37
    public function getLatestVersion(): string
1✔
38
    {
39
        $release = $this->getLatestRelease();
1✔
40

41
        return $release['tag_name'] ?? '';
1✔
42
    }
43

44
    /**
45
     * Get last version
46
     */
47
    public function getLatestVersionClean(): string
1✔
48
    {
49
        $version = $this->getLatestVersion();
1✔
50
        $clean = ltrim($version, 'v');
1✔
51

52
        return str_replace(['-alpha', '-beta', '-rc'], '', $clean);
1✔
53
    }
54

55
    /**
56
     * Получает последние релизы
57
     */
58
    public function getLatestReleases(): array
1✔
59
    {
60
        return $this->cachedFetch('releases', fn () => $this->fetchGitHubData(
1✔
61
            endpoint: 'releases',
1✔
62
            params: ['per_page' => 10]
1✔
63
        ));
1✔
64
    }
65

66
    /**
67
     * Отдаёт данные из кэша сразу (даже протухшие), протухший кэш обновляет
68
     * после отправки ответа. Синхронный запрос к GitHub — только на холодном
69
     * кэше, чтобы страница не подвисала на каждом промахе.
70
     */
71
    protected function cachedFetch(string $key, callable $fetcher): array
1✔
72
    {
73
        $cached = Cache::get($key);
1✔
74

75
        // Холодный кэш: тянем синхронно, иначе данных вообще не будет
76
        if (! is_array($cached)) {
1✔
77
            return $this->store($key, $fetcher);
1✔
78
        }
79

80
        // Протухло: отдаём старое, обновляем в фоне после ответа
NEW
81
        if (($cached['cached_at'] ?? 0) < now()->getTimestamp() - $this->defaultCacheTtl) {
×
NEW
82
            dispatch(fn () => $this->store($key, $fetcher))->afterResponse();
×
83
        }
84

NEW
85
        return $cached['data'] ?? [];
×
86
    }
87

88
    /**
89
     * Запрашивает данные и кладёт в кэш вместе с меткой времени
90
     */
91
    protected function store(string $key, callable $fetcher): array
1✔
92
    {
93
        $data = $fetcher();
1✔
94

95
        Cache::forever($key, [
1✔
96
            'data'      => $data,
1✔
97
            'cached_at' => now()->getTimestamp(),
1✔
98
        ]);
1✔
99

100
        return $data;
1✔
101
    }
102

103
    /**
104
     * Обращается к GitHub API
105
     */
106
    protected function fetchGitHubData(string $endpoint, array $params = []): array
1✔
107
    {
108
        $headers = [
1✔
109
            'Accept' => 'application/vnd.github+json',
1✔
110
        ];
1✔
111

112
        try {
113
            $response = Http::withHeaders($headers)
1✔
114
                ->timeout(3)
1✔
115
                ->retry(3, 100)
1✔
116
                ->get($this->baseUrl . $endpoint, $params);
1✔
117

118
            if ($response->failed()) {
1✔
119
                throw new RuntimeException(
×
120
                    'GitHub API error: ' . $response->body(),
×
121
                    $response->status()
×
122
                );
×
123
            }
124

125
            return $response->json() ?? [];
1✔
126
        } catch (Throwable) {
×
127
            return [];
×
128
        }
129
    }
130
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc