From cd088529c18d3a5350624e4e4b79c59eadb5ff1b Mon Sep 17 00:00:00 2001 From: quality <280983584+hivecommons-hive[bot]@users.noreply.github.com> Date: Tue, 20 Oct 2026 14:18:48 -0400 Subject: [PATCH] test(hold): pin cancelHold's case fold on the issue's labels and on hold.label MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /hold cancel releases the hold labels by comparing both the configured and the legacy name and the issue's labels in lower case. Neither side of that fold was asserted: every cancel fixture carried do-not-merge/hold and hold in lower case, and both hold.label fixtures were lower case too, so dropping either .toLowerCase() in cancelHold passed the suite while leaving a label created as Hold or DO-NOT-MERGE/HOLD stuck on the pull request — exactly the spelling meetsMergeGate is already pinned to block on. Two cases in the cancel block: an issue carrying Hold and DO-NOT-MERGE/HOLD has both removed under their own names, and hold.label: Do-Not-Merge/Hold releases the repository's do-not-merge/hold without a DELETE for the configured spelling. Refs #523 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: quality <280983584+hivecommons-hive[bot]@users.noreply.github.com> --- __tests__/label/hold.test.ts | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/__tests__/label/hold.test.ts b/__tests__/label/hold.test.ts index ff3e0624..ac29bfc6 100644 --- a/__tests__/label/hold.test.ts +++ b/__tests__/label/hold.test.ts @@ -147,6 +147,41 @@ describe('hold', () => { await expect(observeLegacy.notCalled()).resolves.toBe('not called') }) + it('removes a mixed-case Hold and DO-NOT-MERGE/HOLD under their own names: label names fold case', async () => { + issueCommentEvent.comment.body = '/hold cancel' + const commentContext = new utils.MockContext(issueCommentEvent) + + server.use(http.get(issueUrl, utils.mockResponse(200, issueWithLabels('Hold', 'DO-NOT-MERGE/HOLD')))) + const observeNew = observeDelete('DO-NOT-MERGE/HOLD') + const observeLegacy = observeDelete('Hold') + + const setFailed = vi.spyOn(core, 'setFailed').mockImplementation(() => {}) + await handleIssueComment(commentContext) + await expect(observeNew.called()).resolves.toBe('called') + await expect(observeLegacy.called()).resolves.toBe('called') + expect(setFailed).not.toHaveBeenCalled() + }) + + it('removes the label under its own name when the configured hold.label differs from it only by case', async () => { + issueCommentEvent.comment.body = '/hold cancel' + const commentContext = new utils.MockContext(issueCommentEvent) + + const file = structuredClone(labelFileContents) + file.content = Buffer.from('hold:\n label: Do-Not-Merge/Hold\n').toString('base64') + server.use( + http.get(utils.contentsUrl('.github/prow.yaml'), utils.mockResponse(200, file)), + http.get(issueUrl, utils.mockResponse(200, issueWithLabels('do-not-merge/hold'))), + ) + const observeLower = observeDelete('do-not-merge/hold') + const observeConfigured = observeDelete('Do-Not-Merge/Hold') + + const setFailed = vi.spyOn(core, 'setFailed').mockImplementation(() => {}) + await handleIssueComment(commentContext) + await expect(observeLower.called()).resolves.toBe('called') + await expect(observeConfigured.notCalled()).resolves.toBe('not called') + expect(setFailed).not.toHaveBeenCalled() + }) + it('removes the configured hold.label and the legacy hold label once when they are the same', async () => { issueCommentEvent.comment.body = '/hold cancel' const commentContext = new utils.MockContext(issueCommentEvent)