diff --git a/src/components/config/GitHubMirrorSettings.tsx b/src/components/config/GitHubMirrorSettings.tsx
index 9c1821f..1d6985a 100644
--- a/src/components/config/GitHubMirrorSettings.tsx
+++ b/src/components/config/GitHubMirrorSettings.tsx
@@ -377,14 +377,13 @@ export function GitHubMirrorSettings({
id="release-limit"
type="number"
min="1"
- max="100"
value={mirrorOptions.releaseLimit || 10}
onChange={(e) => {
const value = parseInt(e.target.value) || 10;
- const clampedValue = Math.min(100, Math.max(1, value));
+ const clampedValue = Math.max(1, value);
handleMirrorChange('releaseLimit', clampedValue);
}}
- className="w-16 px-2 py-1 text-xs border border-input rounded bg-background text-foreground"
+ className="w-20 px-2 py-1 text-xs border border-input rounded bg-background text-foreground"
/>
releases
diff --git a/src/lib/gitea.ts b/src/lib/gitea.ts
index ac8f686..99e9b37 100644
--- a/src/lib/gitea.ts
+++ b/src/lib/gitea.ts
@@ -2026,17 +2026,43 @@ export async function mirrorGitHubReleasesToGitea({
}
// Get release limit from config (default to 10)
- const releaseLimit = config.giteaConfig?.releaseLimit || 10;
-
- const releases = await octokit.rest.repos.listReleases({
- owner: repository.owner,
- repo: repository.name,
- per_page: releaseLimit, // Only fetch the latest N releases
- });
+ const releaseLimit = Math.max(1, Math.floor(config.giteaConfig?.releaseLimit || 10));
- console.log(`[Releases] Found ${releases.data.length} releases (limited to latest ${releaseLimit}) to mirror for ${repository.fullName}`);
+ // GitHub API max per page is 100; paginate until we reach the configured limit.
+ const releases: Awaited<
+ ReturnType
+ >["data"] = [];
+ let page = 1;
+ const perPage = Math.min(100, releaseLimit);
- if (releases.data.length === 0) {
+ while (releases.length < releaseLimit) {
+ const response = await octokit.rest.repos.listReleases({
+ owner: repository.owner,
+ repo: repository.name,
+ per_page: perPage,
+ page,
+ });
+
+ if (response.data.length === 0) {
+ break;
+ }
+
+ releases.push(...response.data);
+
+ if (response.data.length < perPage) {
+ break;
+ }
+
+ page++;
+ }
+
+ const limitedReleases = releases.slice(0, releaseLimit);
+
+ console.log(
+ `[Releases] Found ${limitedReleases.length} releases (limited to latest ${releaseLimit}) to mirror for ${repository.fullName}`
+ );
+
+ if (limitedReleases.length === 0) {
console.log(`[Releases] No releases to mirror for ${repository.fullName}`);
return;
}
@@ -2044,7 +2070,7 @@ export async function mirrorGitHubReleasesToGitea({
let mirroredCount = 0;
let skippedCount = 0;
- const getReleaseTimestamp = (release: typeof releases.data[number]) => {
+ const getReleaseTimestamp = (release: (typeof limitedReleases)[number]) => {
// Use published_at first (when the release was published on GitHub)
// Fall back to created_at (when the git tag was created) only if published_at is missing
// This matches GitHub's sorting behavior and handles cases where multiple tags
@@ -2055,10 +2081,9 @@ export async function mirrorGitHubReleasesToGitea({
};
// Capture the latest releases, then process them oldest-to-newest so Gitea mirrors keep chronological order
- const releasesToProcess = releases.data
+ const releasesToProcess = limitedReleases
.slice()
.sort((a, b) => getReleaseTimestamp(b) - getReleaseTimestamp(a))
- .slice(0, releaseLimit)
.sort((a, b) => getReleaseTimestamp(a) - getReleaseTimestamp(b));
console.log(`[Releases] Processing ${releasesToProcess.length} releases in chronological order (oldest to newest by published date)`);