100 lines
3.8 KiB
JavaScript
100 lines
3.8 KiB
JavaScript
import { config } from '../config.js'
|
||
import { giteaFetch, splitRepo } from './giteaClient.js'
|
||
|
||
const DAY_MS = 24 * 60 * 60 * 1000
|
||
// Sicherheitsnetz fuer listRecentPushes: sollte Gitea "page" ignorieren und immer dieselbe
|
||
// volle, noch im Fenster liegende Seite liefern, blaettert die Schleife nicht endlos weiter
|
||
// (40 x 50 = 2000 Eintraege).
|
||
const MAX_FEED_PAGES = 40
|
||
|
||
/**
|
||
* Baut aus Gitea-1.25-Aktivitaeten-Feed-Eintraegen (`GET .../activities/feeds`) Push-Objekte
|
||
* im selben Zuschnitt wie der Push-Webhook (siehe `server/routes/webhook/gitea.js` und
|
||
* `createGitPushWorksheet`). Nur `op_type === 'commit_repo'`-Eintraege ab `since` mit
|
||
* mindestens einem Commit zaehlen. Der erste Push auf einen neuen Branch (Eintrag mit leerem
|
||
* `content`) und andere Aktivitaeten (z. B. `create_repo`) werden uebersprungen; ein nicht
|
||
* parsbarer `content` ebenso. Ergebnis aufsteigend nach `pushedAt` sortiert (aelteste
|
||
* zuerst), unabhaengig von der Reihenfolge im Feed.
|
||
*
|
||
* @param {object[]} feed Feed-Eintraege wie von Gitea geliefert.
|
||
* @param {{since: Date}} options
|
||
* @returns {Array<{branch: string, commitSha: string, pushedAt: Date,
|
||
* pusher: {login: string, username: string, full_name: string},
|
||
* commits: Array<{id: string, message: string, author: {name: string}}>}>}
|
||
*/
|
||
export function pushesFromFeed(feed, { since } = {}) {
|
||
const pushes = []
|
||
|
||
for (const entry of feed || []) {
|
||
if (entry?.op_type !== 'commit_repo') continue
|
||
if (!(new Date(entry.created) >= since)) continue
|
||
|
||
let parsed
|
||
try {
|
||
parsed = JSON.parse(entry.content)
|
||
} catch {
|
||
continue
|
||
}
|
||
|
||
const rawCommits = parsed?.Commits
|
||
if (!Array.isArray(rawCommits) || rawCommits.length === 0) continue
|
||
|
||
const actUser = entry.act_user || {}
|
||
|
||
pushes.push({
|
||
branch: String(entry.ref_name || '').replace('refs/heads/', ''),
|
||
commitSha: parsed.HeadCommit?.Sha1 || rawCommits[0].Sha1,
|
||
pushedAt: new Date(entry.created),
|
||
pusher: {
|
||
login: actUser.login,
|
||
username: actUser.login,
|
||
full_name: actUser.full_name || '',
|
||
},
|
||
commits: rawCommits.map((c) => ({
|
||
id: c.Sha1,
|
||
message: c.Message,
|
||
author: { name: c.AuthorName },
|
||
})),
|
||
})
|
||
}
|
||
|
||
return pushes.sort((a, b) => a.pushedAt - b.pushedAt)
|
||
}
|
||
|
||
/**
|
||
* Liest die Push-Historie eines Repos der letzten `days` Tage aus dem Gitea-Aktivitaeten-Feed
|
||
* (`GET /repos/{owner}/{repo}/activities/feeds`, seitenweise mit 50 pro Seite, neueste zuerst).
|
||
* Blaettert nur so weit wie noetig: stoppt bei einer leeren Seite, einer Seite mit weniger als
|
||
* 50 Eintraegen, oder sobald der aelteste Eintrag einer Seite vor `since` liegt. Bricht
|
||
* zusaetzlich nach `MAX_FEED_PAGES` Seiten ab (mit einer Konsolen-Warnung), falls keine dieser
|
||
* Bedingungen je eintritt.
|
||
*
|
||
* @param {string} repoFullName "owner/repo"
|
||
* @param {{days?: number, now?: Date}} [options]
|
||
* @returns {Promise<ReturnType<typeof pushesFromFeed>>}
|
||
*/
|
||
export async function listRecentPushes(repoFullName, { days = config.gitea.backfillDays, now = new Date() } = {}) {
|
||
const [owner, repo] = splitRepo(repoFullName)
|
||
const since = new Date(now - days * DAY_MS)
|
||
const limit = 50
|
||
const collected = []
|
||
let page = 1
|
||
|
||
while (true) {
|
||
const items = await giteaFetch(`/repos/${owner}/${repo}/activities/feeds?limit=${limit}&page=${page}`)
|
||
if (!Array.isArray(items) || items.length === 0) break
|
||
collected.push(...items)
|
||
if (items.length < limit) break
|
||
if (new Date(items[items.length - 1].created) < since) break
|
||
if (page >= MAX_FEED_PAGES) {
|
||
console.warn(
|
||
`[pushHistory] ${repoFullName}: mehr als ${MAX_FEED_PAGES} Seiten Aktivitäten – ältere Pushes im Zeitraum werden nicht nachgetragen`
|
||
)
|
||
break
|
||
}
|
||
page += 1
|
||
}
|
||
|
||
return pushesFromFeed(collected, { since })
|
||
}
|