From b64aef602d5fb94d2a016a90db21d310416f2f6c Mon Sep 17 00:00:00 2001 From: quality <280983584+hivecommons-hive[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2026 10:53:38 -0500 Subject: [PATCH] test(worker): pin the day-long KV delivery TTL and the grace-period queue delay kvDeliveryStore writes each delivery id with expirationTtl 86_400 and deferViaQueue sends the deferred message with delaySeconds rounded up from the grace period; neither value was asserted, so dropping either left the miniflare suite green (the redelivery test only reads the key back, and the grace-period test only waits for the label). The Redis store's TTL is pinned in redis.test.ts; the KV store now is too, through the expiration KV reports on list(). The delay is pinned on the fake GitHub's own clock, comparing the deferring run's config read with the resumed run's label POST under a 3 s grace period: without the delay the resume lands in under 100 ms. Signed-off-by: quality <280983584+hivecommons-hive[bot]@users.noreply.github.com> --- __tests__/worker/worker.test.ts | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/__tests__/worker/worker.test.ts b/__tests__/worker/worker.test.ts index c98049af..f9d71452 100644 --- a/__tests__/worker/worker.test.ts +++ b/__tests__/worker/worker.test.ts @@ -16,6 +16,8 @@ const secret = 'worker-secret' const { privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048, privateKeyEncoding: { type: 'pkcs8', format: 'pem' }, publicKeyEncoding: { type: 'spki', format: 'pem' } }) interface Seen { method: string, path: string, auth: string | null, body: string } +// `at` is the fake's own clock (the ms prefix of its LOG key), so two entries compare on one clock +interface SeenAt extends Seen { at: number } // the fake GitHub: every request is logged under its own LOG key (seen:-, so two in flight at once — // the org- and repo-tier config probes — cannot lose each other's write); LOG.prow.yaml, when set, is served as @@ -150,10 +152,10 @@ function closeComment(id = 7, issue = 1): Payload { return payload } -async function githubSawIn(mf: Miniflare): Promise { +async function githubSawIn(mf: Miniflare): Promise { const log = await mf.getKVNamespace('LOG', 'github') const keys = (await log.list({ prefix: 'seen:' })).keys.map(key => key.name) - return Promise.all(keys.map(async key => JSON.parse((await log.get(key))!) as Seen)) + return Promise.all(keys.map(async key => ({ ...JSON.parse((await log.get(key))!) as Seen, at: Number(key.slice('seen:'.length, 'seen:'.length + 15)) }))) } async function eventually(check: () => Promise, ms = 10_000): Promise { @@ -283,6 +285,18 @@ describe('the Worker', () => { expect(await deliveries.get('delivery:d-twice')).toBe('1') }) + it('remembers a delivery id for a day, so a redelivery after that runs again', async () => { + const before = Math.floor(Date.now() / 1000) + expect((await deliver('issue_comment', closeComment(), 'd-for-a-day')).status).toBe(202) + await eventually(async () => (await githubSaw()).some(s => s.method === 'PATCH')) + + const deliveries = await mf.getKVNamespace('DELIVERIES', 'prow') + const key = (await deliveries.list()).keys.find(key => key.name === 'delivery:d-for-a-day') + // KV reports expiration in seconds since the epoch; a key written without one has none and never ages out + expect(key?.expiration).toBeGreaterThanOrEqual(before + 86_400) + expect(key?.expiration).toBeLessThanOrEqual(Math.floor(Date.now() / 1000) + 86_400) + }) + it('forgets a pull request delivery whose run fails, so GitHub\'s redelivery runs it again', async () => { await failing('patch') const payload = closeComment() @@ -364,6 +378,21 @@ describe('the Worker', () => { expect(JSON.parse(labeled!.body)).toEqual({ labels: ['needs-kind'] }) }) + it('holds the deferred message for the grace period: the resumed run starts no sooner than the period after the deferring one', async () => { + const log = await mf.getKVNamespace('LOG', 'github') + await log.put('prow.yaml', requireKind.replace('grace_period_duration: 1s', 'grace_period_duration: 3s')) + + expect((await deliver('pull_request', withInstallation(pullReqOpenedEvent), 'd-grace-held')).status).toBe(202) + await eventually(async () => (await githubSaw()).some(s => s.method === 'POST' && s.path.endsWith('/issues/1/labels'))) + + // the deferring run's config read and the resumed run's label, both stamped by the fake's clock: a message sent + // without its delay would resume within the queue's batch timeout, well under the period + const seen = await githubSaw() + const deferred = seen.find(s => s.path.endsWith('/contents/.github/prow.yaml'))! + const labeled = seen.find(s => s.method === 'POST' && s.path.endsWith('/issues/1/labels'))! + expect(labeled.at - deferred.at).toBeGreaterThanOrEqual(2_500) + }) + it('a deferred check carries the delivery once, so a payload over half the queue\'s 128 KB limit still defers', async () => { const log = await mf.getKVNamespace('LOG', 'github') await log.put('prow.yaml', requireKind)