From 9c3f1e38d66b58aaa2d491550909e388bd61354f Mon Sep 17 00:00:00 2001 From: LionelB Date: Fri, 20 Dec 2024 10:18:01 +0100 Subject: [PATCH] fix: call mergequeue after a check_suite event --- build/controllers/github.js | 24 +++++++-- common/services/github.js | 6 +++ test/unit/build/controllers/github_test.js | 42 ++++++++++++++- test/unit/build/services/github_test.js | 60 ++++++++++++++++++++++ 4 files changed, 126 insertions(+), 6 deletions(-) diff --git a/build/controllers/github.js b/build/controllers/github.js index 78b178d3..0c247a5f 100644 --- a/build/controllers/github.js +++ b/build/controllers/github.js @@ -297,12 +297,26 @@ async function processWebhook( } return `Ignoring ${request.payload.action} action`; } else if (eventName === 'check_suite') { - if (request.payload.action === 'completed' && request.payload.check_suite.conclusion !== 'success') { + if (request.payload.action === 'completed') { const repositoryName = request.payload.repository.full_name; - await pullRequestRepository.remove({ - number: request.payload.pull_requests[0].number, - repositoryName, - }); + if (request.payload.check_suite.conclusion !== 'success') { + await pullRequestRepository.remove({ + number: request.payload.pull_requests[0].number, + repositoryName, + }); + } else { + const hasReadyToMergeLabel = await githubService.isPrLabelledWith({ + repositoryName, + number: request.payload.pull_requests[0].number, + label: ':rocket: Ready to Merge', + }); + if (hasReadyToMergeLabel) { + await pullRequestRepository.save({ + number: request.payload.pull_requests[0].number, + repositoryName, + }); + } + } await mergeQueue({ repositoryName }); } } else { diff --git a/common/services/github.js b/common/services/github.js index 07be3fd2..61c52c94 100644 --- a/common/services/github.js +++ b/common/services/github.js @@ -497,6 +497,12 @@ const github = { inputs, }); }, + + async isPrLabelledWith({ number, repositoryName, label }) { + const octokit = _createOctokit(); + const { data } = await octokit.request(`GET /repos/${repositoryName}/pulls/${number}`); + return data.labels.some((ghLabel) => ghLabel.name === label); + }, }; export default github; diff --git a/test/unit/build/controllers/github_test.js b/test/unit/build/controllers/github_test.js index 11446b7f..70cb896d 100644 --- a/test/unit/build/controllers/github_test.js +++ b/test/unit/build/controllers/github_test.js @@ -314,7 +314,7 @@ Les variables d'environnement seront accessibles sur scalingo https://dashboard. describe('when event is check_suite', function () { describe("when action is 'completed' and conclusion is not 'success'", function () { - it('should call pullRequestRepository.remove() method', async function () { + it('should call pullRequestRepository.update() method', async function () { const repositoryName = '1024pix/pix-sample-repo'; const request = { headers: { @@ -342,6 +342,46 @@ Les variables d'environnement seront accessibles sur scalingo https://dashboard. expect(mergeQueue).to.be.calledOnceWithExactly({ repositoryName }); }); }); + + describe("when action is 'completed' and conclusion is'success'", function () { + it('should check PR as Ready to Merge label before saved it', async function () { + const repositoryName = '1024pix/pix-sample-repo'; + const prNumber = 123; + const request = { + headers: { + 'x-github-event': 'check_suite', + }, + payload: { + action: 'completed', + pull_requests: [{ number: prNumber }], + repository: { full_name: repositoryName }, + check_suite: { conclusion: 'success' }, + }, + }; + + const mergeQueue = sinon.stub(); + const pullRequestRepository = { save: sinon.stub() }; + const githubService = { isPrLabelledWith: sinon.stub() }; + + githubService.isPrLabelledWith + .resolves(false) + .withArgs({ + repositoryName, + number: prNumber, + label: ':rocket: Ready to Merge', + }) + .resolves(true); + // when + await githubController.processWebhook(request, { githubService, pullRequestRepository, mergeQueue }); + + // then + expect(pullRequestRepository.save).to.be.calledOnceWithExactly({ + number: prNumber, + repositoryName, + }); + expect(mergeQueue).to.be.calledOnceWithExactly({ repositoryName }); + }); + }); }); }); }); diff --git a/test/unit/build/services/github_test.js b/test/unit/build/services/github_test.js index 60e4fb45..6995a14a 100644 --- a/test/unit/build/services/github_test.js +++ b/test/unit/build/services/github_test.js @@ -691,4 +691,64 @@ describe('Unit | Build | github-test', function () { expect(githubNock.isDone()).to.be.true; }); }); + + describe('#isPrLabelledWith', function () { + let githubNock; + const repositoryName = '1024pix/pix'; + const prNumber = 123; + + beforeEach(function () { + const response = { + labels: [ + { + id: 123, + node_id: 'MDU6TGFiZWwyMDgwNDU5NDY=', + url: 'https://api.github.com/repos/octocat/Hello-World/labels/%3Apanda%3A label', + name: ':panda: label', + description: 'Something is like a panda', + color: 'FFFFFF', + default: true, + }, + { + id: 123, + node_id: 'MDU6TGFiZWwyMDgwNDU5NDY=', + url: 'https://api.github.com/repos/octocat/Hello-World/labels/working', + name: 'working', + description: 'Something is working', + color: 'f29efef', + default: true, + }, + ], + }; + githubNock = nock('https://api.github.com') + .get(`/repos/${repositoryName}/pulls/${prNumber}`) + .reply(200, response); + }); + + describe('when PR is labelled with `:panda: label`', function () { + it('should return true for :panda: label', async function () { + const label = ':panda: label'; + + const hasPandaLabel = await githubService.isPrLabelledWith({ + number: prNumber, + repositoryName, + label, + }); + expect(hasPandaLabel).to.be.true; + expect(githubNock.isDone()).to.be.true; + }); + + it('should return false for bug', async function () { + const label = 'bug'; + + const hasBugLabel = await githubService.isPrLabelledWith({ + number: prNumber, + repositoryName, + label, + }); + expect(hasBugLabel).to.be.false; + expect(githubNock.isDone()).to.be.true; + }); + }); + }); });