Push-Historie: Obergrenze beim Blättern, Test für HeadCommit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e409c11d5c
commit
51c4852488
2 files changed
+49
-3
No files matched your search
@@ -2,6 +2,10 @@ import { config } from '../config.js'
|
|||||||
import { giteaFetch, splitRepo } from './giteaClient.js'
|
import { giteaFetch, splitRepo } from './giteaClient.js'
|
||||||
|
|
||||||
const DAY_MS = 24 * 60 * 60 * 1000
|
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
|
* Baut aus Gitea-1.25-Aktivitaeten-Feed-Eintraegen (`GET .../activities/feeds`) Push-Objekte
|
||||||
@@ -61,7 +65,9 @@ export function pushesFromFeed(feed, { since } = {}) {
|
|||||||
* Liest die Push-Historie eines Repos der letzten `days` Tage aus dem Gitea-Aktivitaeten-Feed
|
* 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).
|
* (`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
|
* 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.
|
* 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 {string} repoFullName "owner/repo"
|
||||||
* @param {{days?: number, now?: Date}} [options]
|
* @param {{days?: number, now?: Date}} [options]
|
||||||
@@ -80,6 +86,12 @@ export async function listRecentPushes(repoFullName, { days = config.gitea.backf
|
|||||||
collected.push(...items)
|
collected.push(...items)
|
||||||
if (items.length < limit) break
|
if (items.length < limit) break
|
||||||
if (new Date(items[items.length - 1].created) < since) 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
|
page += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,10 +68,26 @@ function manyPushes(base) {
|
|||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mehr als 40*50 Eintraege, alle nur Minuten auseinander und damit weit innerhalb jedes
|
||||||
|
* 30-Tage-Fensters - fuer den Test der Blaetter-Obergrenze (die Seite wird nie leer/kurz,
|
||||||
|
* und der "aeltester Eintrag vor since"-Stopp greift nie).
|
||||||
|
*/
|
||||||
|
function packedPushes(base, count) {
|
||||||
|
const entries = []
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
entries.push(pushEntry({ sha: `p${i}`, at: new Date(base.getTime() - i * 60000).toISOString() }))
|
||||||
|
}
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
fake = await startFakeGitea({
|
fake = await startFakeGitea({
|
||||||
repos: [{ full_name: 'knso/viel' }],
|
repos: [{ full_name: 'knso/viel' }, { full_name: 'knso/endlos' }],
|
||||||
feeds: { 'knso/viel': manyPushes(now) },
|
feeds: {
|
||||||
|
'knso/viel': manyPushes(now),
|
||||||
|
'knso/endlos': packedPushes(now, 2005),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
Object.assign(process.env, {
|
Object.assign(process.env, {
|
||||||
GITEA_BASE_URL: fake.baseUrl,
|
GITEA_BASE_URL: fake.baseUrl,
|
||||||
@@ -99,6 +115,10 @@ test('HeadCommit bestimmt commitSha', () => {
|
|||||||
const [p] = pushesFromFeed([pushEntry({ commits: ['c2', 'c1'], head: 'c2' })], { since: new Date(0) })
|
const [p] = pushesFromFeed([pushEntry({ commits: ['c2', 'c1'], head: 'c2' })], { since: new Date(0) })
|
||||||
assert.equal(p.commitSha, 'c2'); assert.equal(p.commits.length, 2)
|
assert.equal(p.commitSha, 'c2'); assert.equal(p.commits.length, 2)
|
||||||
})
|
})
|
||||||
|
test('HeadCommit hat Vorrang vor dem ersten Commit', () => {
|
||||||
|
const [p] = pushesFromFeed([pushEntry({ commits: ['c1', 'c2'], head: 'c2' })], { since: new Date(0) })
|
||||||
|
assert.equal(p.commitSha, 'c2')
|
||||||
|
})
|
||||||
test('ohne HeadCommit gilt der erste Commit', () => {
|
test('ohne HeadCommit gilt der erste Commit', () => {
|
||||||
const [p] = pushesFromFeed([pushEntry({ commits: ['c2', 'c1'], head: null })], { since: new Date(0) })
|
const [p] = pushesFromFeed([pushEntry({ commits: ['c2', 'c1'], head: null })], { since: new Date(0) })
|
||||||
assert.equal(p.commitSha, 'c2')
|
assert.equal(p.commitSha, 'c2')
|
||||||
@@ -118,3 +138,17 @@ test('listRecentPushes blättert nur so weit wie nötig', async () => {
|
|||||||
assert.equal(r.length, 90)
|
assert.equal(r.length, 90)
|
||||||
assert.equal(fake.calls.filter((c) => c.path.includes('/activities/feeds')).length, 2)
|
assert.equal(fake.calls.filter((c) => c.path.includes('/activities/feeds')).length, 2)
|
||||||
})
|
})
|
||||||
|
test('Blättern hat eine Obergrenze', async () => {
|
||||||
|
// Feed liefert auf jeder Seite 50 volle, aktuelle Einträge - ohne Obergrenze würde
|
||||||
|
// listRecentPushes endlos weiterblättern.
|
||||||
|
const originalWarn = console.warn
|
||||||
|
console.warn = () => {}
|
||||||
|
let r
|
||||||
|
try {
|
||||||
|
r = await listRecentPushes('knso/endlos', { now })
|
||||||
|
} finally {
|
||||||
|
console.warn = originalWarn
|
||||||
|
}
|
||||||
|
assert.equal(r.length, 2000)
|
||||||
|
assert.equal(fake.calls.filter((c) => c.path.includes('/knso/endlos/activities/feeds')).length, 40)
|
||||||
|
})
|
||||||
Reference in new issue
Block a user