Skip to content

Commit 2b1c1cc

Browse files
authored
Merge pull request #15127 from nextcloud/fix/index-api-rate-limit
fix(index): abort on GitHub API errors, pass GITHUB_TOKEN to avoid rate limiting
2 parents ef8ce84 + 6676741 commit 2b1c1cc

2 files changed

Lines changed: 42 additions & 39 deletions

File tree

.github/workflows/generate-top-index.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ jobs:
3838
uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # v2.37.1
3939

4040
- name: Generate index.html
41+
env:
42+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4143
run: |
4244
php build/build-index.php ${{ steps.branch.outputs.branches }}
4345
mv build/index.html /tmp/index.html

build/build-index.php

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,57 +21,61 @@ function get_repo_for_version(int $version): string {
2121
}
2222

2323
/**
24-
* Check if a version is officially released by querying the GitHub tag
24+
* Parse the HTTP status code from the response headers populated by file_get_contents.
25+
*
26+
* @param array $headers The $http_response_header array
2527
*/
26-
function is_version_released(int $version): bool {
28+
function parse_http_status(array $headers): int {
29+
preg_match('/HTTP\/[\d.]+ (\d+)/', $headers[0] ?? '', $matches);
30+
return (int)($matches[1] ?? 0);
31+
}
32+
33+
/**
34+
* Fetch release info for a given version from the GitHub API.
35+
*
36+
* Returns an array ['date' => int] if the release exists (HTTP 200).
37+
* Returns null if the release does not exist (HTTP 404).
38+
* Exits with code 1 on any other HTTP status (rate limit, server error, etc.)
39+
* to prevent silently generating empty or incorrect index sections.
40+
*/
41+
function fetch_release_info(int $version): ?array {
2742
$repo = get_repo_for_version($version);
2843
$url = sprintf('https://api.github.com/repos/%s/releases/tags/v%d.0.0', $repo, $version);
29-
44+
3045
$context = stream_context_create([
3146
'http' => [
3247
'header' => get_github_headers(),
33-
'timeout' => 5,
48+
'timeout' => 10,
3449
'ignore_errors' => true
3550
]
3651
]);
37-
52+
3853
$response = @file_get_contents($url, false, $context);
3954

4055
// FIXME: function_exists conditional can be dropped once we don't need to support <8.4.0
4156
if (function_exists('http_get_last_response_headers')) {
4257
/** @var array|null */
4358
$http_response_header = \http_get_last_response_headers();
4459
}
45-
46-
if (isset($http_response_header) && is_array($http_response_header)) {
47-
return strpos($http_response_header[0] ?? '', '200') !== false;
60+
61+
$status = isset($http_response_header) && is_array($http_response_header)
62+
? parse_http_status($http_response_header)
63+
: 0;
64+
65+
if ($status === 200) {
66+
$data = json_decode($response, true);
67+
$publishedAt = $data['published_at'] ?? $data['created_at'] ?? null;
68+
return ['date' => $publishedAt ? strtotime($publishedAt) : time()];
4869
}
49-
50-
return $response !== false;
51-
}
5270

53-
/**
54-
* Fetch release date for a version from GitHub API
55-
*/
56-
function get_release_date(int $version): ?int {
57-
$repo = get_repo_for_version($version);
58-
$url = sprintf('https://api.github.com/repos/%s/releases/tags/v%d.0.0', $repo, $version);
59-
60-
$context = stream_context_create([
61-
'http' => [
62-
'header' => get_github_headers(),
63-
'timeout' => 5
64-
]
65-
]);
66-
67-
$response = @file_get_contents($url, false, $context);
68-
if ($response === false) {
71+
if ($status === 404) {
6972
return null;
7073
}
71-
72-
$data = json_decode($response, true);
73-
$publishedAt = $data['published_at'] ?? $data['created_at'] ?? null;
74-
return $publishedAt ? strtotime($publishedAt) : null;
74+
75+
// Any non-200/non-404 response (403 rate limit, 429, 5xx, network failure)
76+
// must abort so we never deploy an index with empty or wrong sections.
77+
fwrite(STDERR, "GitHub API error (HTTP $status) checking v$version.0.0 — aborting to avoid deploying incorrect index\n");
78+
exit(1);
7579
}
7680

7781
// Parse and validate command-line arguments
@@ -98,17 +102,14 @@ function get_release_date(int $version): ?int {
98102
$releaseType = $releaseTime >= $oneYearAgo ? 'stable' : 'unsupported';
99103
continue;
100104
}
101-
102-
if (!is_version_released($branch)) {
105+
106+
$info = fetch_release_info($branch);
107+
if ($info === null) {
103108
fwrite(STDERR, "⏳ Version $branch is not released (tag v$branch.0.0 not found)\n");
104109
continue;
105110
}
106-
107-
$releaseTime = get_release_date($branch);
108-
if ($releaseTime === null) {
109-
$releaseTime = time();
110-
}
111-
111+
112+
$releaseTime = $info['date'];
112113
$released_branches[$branch] = $releaseTime;
113114
if ($releaseTime < $oneYearAgo) {
114115
fwrite(STDOUT, "🛑 Version $branch is unsupported (released on " . date('Y-m-d', $releaseTime) . ")\n");

0 commit comments

Comments
 (0)