From 032cf7ccc5bbeb30ed5768b49c2c4d923dabcce4 Mon Sep 17 00:00:00 2001 From: quality Date: Sun, 11 Oct 2026 07:10:25 -0400 Subject: [PATCH] test(bundle): drive labelCatalog.ts:80 (the /label allowlist's empty prefix) through dist/index.js label-sync over a prow config with a labels.labels section must create its values verbatim, never as labels/. The arm was green only in the unit suite; no bundle case composed that section. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: quality --- .../labelSyncUnprefixedAllowlist.test.ts | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 __tests__/bundle/labelSyncUnprefixedAllowlist.test.ts diff --git a/__tests__/bundle/labelSyncUnprefixedAllowlist.test.ts b/__tests__/bundle/labelSyncUnprefixedAllowlist.test.ts new file mode 100644 index 0000000..9d17cf0 --- /dev/null +++ b/__tests__/bundle/labelSyncUnprefixedAllowlist.test.ts @@ -0,0 +1,71 @@ +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 { configReads, helpersFor, repo, token } from './helpers' +import { runBundle } from './runBundle' + +vi.setConfig({ testTimeout: 30_000 }) + +const labelsRead = `GET ${repo}/labels?per_page=100` + +function yamlFile(text: string) { + const file = structuredClone(labelFileContents) + file.content = Buffer.from(text).toString('base64') + return file +} + +// the `/label` allowlist is the one registry section with an empty prefix (prefix: '' in +// src/labels/prefixed.ts): the catalog must emit its values verbatim, never as `labels/` +describe('dist/index.js label-sync with the /label allowlist', () => { + let gh: FakeGithub + const { expectRequests } = helpersFor(() => gh) + + beforeAll(async () => { + gh = await start() + }) + afterEach(() => gh.reset()) + afterAll(() => gh.close()) + + it('creates the labels section values unprefixed while a prefixed section keeps its prefix', async () => { + const config = yamlFile([ + 'labels:', + ' kind: [bug]', + ' labels:', + ' - documentation', + ' - name: question', + ' color: D876E3', + ' description: Further information is requested', + '', + ].join('\n')) + gh.route('GET', '/repos/Codertocat/.project/contents/prow.yaml', { status: 200, body: config }) + gh.route('GET', `${repo}/labels`, { status: 200, body: [] }) + gh.route('POST', `${repo}/labels`, { status: 201, body: {} }) + + const result = await runBundle({ + eventName: 'workflow_dispatch', + payload: {}, + inputs: { ...token, jobs: 'label-sync' }, + apiUrl: gh.url, + }) + + expect(result.status, result.stdout).toBe(0) + expect(result.errors).toEqual([]) + const posts = gh.requestsMatching('POST', /\/labels$/) + const names = posts.map(p => (p.body as { name: string }).name) + expect(names).toContain('documentation') + expect(names).toContain('question') + expect(names).toContain('kind/bug') + expect(names.some(name => name.startsWith('labels/'))).toBe(false) + expect(posts.find(p => (p.body as { name: string }).name === 'documentation')!.body).toEqual({ name: 'documentation' }) + expect(posts.find(p => (p.body as { name: string }).name === 'question')!.body).toEqual({ + name: 'question', + color: 'd876e3', + description: 'Further information is requested', + }) + expect(result.stdout).toContain(`label-sync: created ${names.length} [${names.join(', ')}], updated 0 [], unchanged 0, failed 0`) + expectRequests([...configReads({ org: '.project' }), labelsRead], names.map(() => `POST ${repo}/labels`)) + }) +})