From f5e5587b441bb3c164a814589d8bc966b16e14da Mon Sep 17 00:00:00 2001 From: quality Date: Sun, 4 Oct 2026 16:59:37 -0400 Subject: [PATCH 1/2] test(bundle): drive label-sync's refused-write and description-drift arms through dist/index.js Adds __tests__/bundle/labelSyncFailureArms.test.ts: a workflow_dispatch label-sync run where every create answers 403 and the one existing label drifts only in its description. Covers src/cronJobs/labelSync.ts lines 94, 107-109 and 134 end-to-end (npm run test:coverage:e2e: labelSync.ts 85.41 -> 97.91 % lines). Signed-off-by: quality --- __tests__/bundle/labelSyncFailureArms.test.ts | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 __tests__/bundle/labelSyncFailureArms.test.ts diff --git a/__tests__/bundle/labelSyncFailureArms.test.ts b/__tests__/bundle/labelSyncFailureArms.test.ts new file mode 100644 index 0000000..f4ff0fd --- /dev/null +++ b/__tests__/bundle/labelSyncFailureArms.test.ts @@ -0,0 +1,60 @@ +import type { FakeGithub } from './fakeGithub' +import { Buffer } from 'node:buffer' +import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest' + +import labelFileContents from '../fixtures/labels/labelFileContentsResp.json' +import { start } from './fakeGithub' +import { repo, token } from './helpers' +import { runBundle } from './runBundle' + +vi.setConfig({ testTimeout: 30_000 }) + +// the arms of the label-sync job that bundle.test.ts never reaches: a refused write is recorded and +// the remaining labels are still attempted, the run fails once naming every failure, and a label whose +// only drift is its description is patched with the description alone +describe('dist/index.js workflow_dispatch label-sync job failure arms', () => { + let gh: FakeGithub + + beforeAll(async () => { + gh = await start() + }) + afterEach(() => gh.reset()) + afterAll(() => gh.close()) + + const orgConfig = { ...structuredClone(labelFileContents), content: Buffer.from('labels:\n kind:\n - name: bug\n description: Something is not working\n').toString('base64') } + + const builtins = ['approved', 'do-not-merge/hold', 'good first issue', 'help wanted', 'hold', 'lgtm', 'lifecycle/frozen', 'lifecycle/rotten', 'lifecycle/stale', 'ok-to-test', 'stage/alpha', 'stage/beta', 'stage/stable', 'status/approved-for-milestone', 'status/in-progress', 'status/in-review'] + + it('refused creates are each recorded, the description-only drift is still patched, and the run fails once naming every refused label', async () => { + gh.route('GET', '/repos/Codertocat/.project/contents/prow.yaml', { status: 200, body: orgConfig }) + gh.route('GET', `${repo}/labels`, { + status: 200, + body: [{ name: 'kind/bug', color: '000000', description: 'stale text' }], + }) + gh.route('POST', `${repo}/labels`, { status: 403, body: { message: 'Resource not accessible by integration' } }) + gh.route('PATCH', `${repo}/labels/kind%2Fbug`, { status: 200, body: {} }) + + const result = await runBundle({ + eventName: 'workflow_dispatch', + payload: {}, + inputs: { ...token, jobs: 'label-sync' }, + apiUrl: gh.url, + }) + + expect(result.status, result.stdout).toBe(1) + // one core.error per refused label, then the single failure that ends the run + const perLabel = builtins.map(name => `label-sync: could not sync ${name}: Resource not accessible by integration`) + expect(result.errors.slice(0, builtins.length)).toEqual(perLabel) + expect(result.errors).toHaveLength(builtins.length + 1) + expect(result.errors[builtins.length]).toContain(`TypeError: error handling cron job: Error: ${builtins.length} label(s) could not be synced: ${builtins.map(name => `${name} (Resource not accessible by integration`).join('), ')}`) + expect(result.stdout).toContain(`label-sync: created 0 [], updated 1 [kind/bug], unchanged 0, failed ${builtins.length}`) + + // every create is still attempted after the first refusal + const posts = gh.requestsMatching('POST', /\/labels$/) + expect(posts.map(p => (p.body as { name: string }).name)).toEqual(builtins) + const patches = gh.requestsMatching('PATCH', /./) + expect(patches).toHaveLength(1) + expect(patches[0].path).toBe(`${repo}/labels/kind%2Fbug`) + expect(patches[0].body).toEqual({ description: 'Something is not working' }) + }) +}) From 2568bc8610796796aa2c25572326aff261f8ac72 Mon Sep 17 00:00:00 2001 From: quality Date: Wed, 7 Oct 2026 22:16:16 -0400 Subject: [PATCH 2/2] test(bundle): check the label-sync refusals and the summary by fragment Signed-off-by: quality --- __tests__/bundle/labelSyncFailureArms.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/__tests__/bundle/labelSyncFailureArms.test.ts b/__tests__/bundle/labelSyncFailureArms.test.ts index f4ff0fd..3ec7ccc 100644 --- a/__tests__/bundle/labelSyncFailureArms.test.ts +++ b/__tests__/bundle/labelSyncFailureArms.test.ts @@ -43,10 +43,9 @@ describe('dist/index.js workflow_dispatch label-sync job failure arms', () => { expect(result.status, result.stdout).toBe(1) // one core.error per refused label, then the single failure that ends the run - const perLabel = builtins.map(name => `label-sync: could not sync ${name}: Resource not accessible by integration`) - expect(result.errors.slice(0, builtins.length)).toEqual(perLabel) expect(result.errors).toHaveLength(builtins.length + 1) - expect(result.errors[builtins.length]).toContain(`TypeError: error handling cron job: Error: ${builtins.length} label(s) could not be synced: ${builtins.map(name => `${name} (Resource not accessible by integration`).join('), ')}`) + builtins.forEach((name, i) => expect(result.errors[i]).toContain(`could not sync ${name}`)) + expect(result.errors[builtins.length]).toContain(`${builtins.length} label(s) could not be synced`) expect(result.stdout).toContain(`label-sync: created 0 [], updated 1 [kind/bug], unchanged 0, failed ${builtins.length}`) // every create is still attempted after the first refusal