From 4920091f45509fc3f050478afd5216077efe5aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Tue, 18 Apr 2023 14:16:21 +0200 Subject: [PATCH] Use /search API to check if first PR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Benjamin Cabé --- lib/main.js | 54 +++++++++++++++------------------------ package.json | 2 +- src/main.ts | 71 ++++++++++++++++------------------------------------ 3 files changed, 42 insertions(+), 85 deletions(-) diff --git a/lib/main.js b/lib/main.js index ec34670..148ce89 100644 --- a/lib/main.js +++ b/lib/main.js @@ -73,7 +73,7 @@ function run() { firstContribution = yield isFirstIssue(client, sender, issue.number); } else { - firstContribution = yield isFirstPull(client, sender, issue.number, context.payload.action === 'closed'); + firstContribution = yield isFirstOpenedOrMergedPR(client, sender, issue.number, context.payload.action === 'closed'); } if (!firstContribution) { console.log('Not the user\'s first contribution'); @@ -86,13 +86,7 @@ function run() { yield client.rest.issues.createComment(Object.assign(Object.assign({}, context.repo), { issue_number: issue.number, body: issueMessage })); } else { - // Get the pull request details - const { data: pr } = yield client.rest.pulls.get(Object.assign(Object.assign({}, context.repo), { pull_number: issue.number })); - if (context.payload.action === 'closed' && !pr.merged) { - console.log('PR was closed without merging, skipping'); - return; - } - const message = pr.merged ? prMergedMessage : prOpenedMessage; + const message = (context.payload.action === 'closed') ? prMergedMessage : prOpenedMessage; console.log(`Adding message: ${message} to ${issueType} ${issue.number}`); yield client.rest.pulls.createReview(Object.assign(Object.assign({}, context.repo), { pull_number: issue.number, body: message, event: 'COMMENT' })); } @@ -120,37 +114,29 @@ function isFirstIssue(client, sender, curIssueNumber) { return true; }); } -// It's someone's "first" PR if it's the first PR they've opened, -// or if it's their first closed PR that's been merged. -function isFirstPull(client, sender, curPullNumber, closed, page = 1) { - var _a; +function isFirstOpenedOrMergedPR(client, sender, curPullNumber, closed) { return __awaiter(this, void 0, void 0, function* () { - // Provide console output if we loop for a while. - console.log('Checking...'); - const { status, data: pulls } = yield client.rest.pulls.list(Object.assign(Object.assign({}, github.context.repo), { per_page: 100, page: page, state: 'all' })); - if (status !== 200) { + // get the PR's details + const { status: getPRStatus, data: pr } = yield client.rest.pulls.get(Object.assign(Object.assign({}, github.context.repo), { pull_number: curPullNumber })); + if (getPRStatus !== 200) { throw new Error(`Received unexpected API status code ${status}`); } - if (pulls.length === 0) { - return true; + let query = `repo:${github.context.repo.owner}/${github.context.repo.repo} type:pr author:${sender}`; + if (closed) { + let query = `repo:${github.context.repo.owner}/${github.context.repo.repo} type:pr author:${sender}`; + if (!pr.merged) + return false; + query += ` closed:<=${pr.closed_at} is:merged`; } - for (const pull of pulls) { - const login = (_a = pull.user) === null || _a === void 0 ? void 0 : _a.login; - if (!closed) { - // If the PR is open, we only care if it's the first PR they've opened. - if (login === sender && pull.number < curPullNumber) { - return false; - } - } - else { - // If the PR is closed, we need to check if it's the first PR of theirs that's been merged. - // In other words, are there PRs from them other than "currPullNumber" that are merged. - if (login === sender && pull.merged_at !== null && pull.number != curPullNumber) { - return false; - } - } + else { + query += ` created:<=${pr.created_at}`; + } + const { status: searchStatus, data: searchResults } = yield client.rest.search.issuesAndPullRequests({ q: query }); + if (searchStatus !== 200) { + throw new Error(`Received unexpected API status code ${status}`); } - return yield isFirstPull(client, sender, curPullNumber, closed, page + 1); + // If current PR is the user's first to be created or merged, there should be exactly one result + return searchResults.total_count === 1; }); } run(); diff --git a/package.json b/package.json index da33fdd..2cda615 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "first-interaction-action", - "version": "1.1.3-zephyr", + "version": "1.1.1-zephyr-1", "description": "An action for greeting first time contributors.", "main": "lib/main.js", "scripts": { diff --git a/src/main.ts b/src/main.ts index 99b9ed9..362dbae 100644 --- a/src/main.ts +++ b/src/main.ts @@ -52,7 +52,7 @@ async function run() { issue.number ); } else { - firstContribution = await isFirstPull( + firstContribution = await isFirstOpenedOrMergedPR( client, sender, issue.number, @@ -75,18 +75,7 @@ async function run() { body: issueMessage }); } else { - // Get the pull request details - const { data: pr } = await client.rest.pulls.get({ - ...context.repo, - pull_number: issue.number - }); - - if(context.payload.action === 'closed' && !pr.merged) { - console.log('PR was closed without merging, skipping'); - return; - } - - const message = pr.merged ? prMergedMessage : prOpenedMessage; + const message = (context.payload.action === 'closed') ? prMergedMessage : prOpenedMessage; console.log(`Adding message: ${message} to ${issueType} ${issue.number}`); await client.rest.pulls.createReview({ @@ -130,56 +119,38 @@ async function isFirstIssue( return true; } -// It's someone's "first" PR if it's the first PR they've opened, -// or if it's their first closed PR that's been merged. -async function isFirstPull( +async function isFirstOpenedOrMergedPR( client: ReturnType, sender: string, curPullNumber: number, - closed: boolean, - page: number = 1 + closed: boolean ): Promise { - // Provide console output if we loop for a while. - console.log('Checking...'); - const {status, data: pulls} = await client.rest.pulls.list({ + // get the PR's details + const {status: getPRStatus, data: pr} = await client.rest.pulls.get({ ...github.context.repo, - per_page: 100, - page: page, - state: 'all' + pull_number: curPullNumber }); - if (status !== 200) { + if (getPRStatus !== 200) { throw new Error(`Received unexpected API status code ${status}`); } - if (pulls.length === 0) { - return true; + let query = `repo:${github.context.repo.owner}/${github.context.repo.repo} type:pr author:${sender}`; + if (closed) { + let query = `repo:${github.context.repo.owner}/${github.context.repo.repo} type:pr author:${sender}`; + if(!pr.merged) return false; + query += ` closed:<=${pr.closed_at} is:merged`; + } else { + query += ` created:<=${pr.created_at}`; } - - for (const pull of pulls) { - const login = pull.user?.login; - - if(!closed) { - // If the PR is open, we only care if it's the first PR they've opened. - if (login === sender && pull.number < curPullNumber) { - return false; - } - } else { - // If the PR is closed, we need to check if it's the first PR of theirs that's been merged. - // In other words, are there PRs from them other than "currPullNumber" that are merged. - if (login === sender && pull.merged_at!==null && pull.number != curPullNumber) { - return false; - } - } + const {status: searchStatus, data: searchResults} = await client.rest.search.issuesAndPullRequests({ q: query }); + + if (searchStatus !== 200) { + throw new Error(`Received unexpected API status code ${status}`); } - return await isFirstPull( - client, - sender, - curPullNumber, - closed, - page + 1 - ); + // If current PR is the user's first to be created or merged, there should be exactly one result + return searchResults.total_count === 1; } run();