From 7a943303b7e3b7af81b423dc5b0419e251b64627 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 27 Oct 2021 22:29:39 -0700 Subject: [PATCH 1/9] Start generating internal QA checklist without assignments --- .github/libs/GithubUtils.js | 16 ++++++++ tests/unit/GithubUtilsTest.js | 74 +++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/.github/libs/GithubUtils.js b/.github/libs/GithubUtils.js index 94f242a81b53..309530b0ba9e 100644 --- a/.github/libs/GithubUtils.js +++ b/.github/libs/GithubUtils.js @@ -16,6 +16,7 @@ const ISSUE_OR_PULL_REQUEST_REGEX = new RegExp(`${GITHUB_BASE_URL_REGEX.source}/ const APPLAUSE_BOT = 'applausebot'; const STAGING_DEPLOY_CASH_LABEL = 'StagingDeployCash'; const DEPLOY_BLOCKER_CASH_LABEL = 'DeployBlockerCash'; +const INTERNAL_QA_LABEL = 'InternalQA'; class GithubUtils { /** @@ -189,6 +190,12 @@ class GithubUtils { ); console.log('Filtering out the following automated pull requests:', automatedPRs); + const internalQAPRs = _.pluck( + _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), + 'html_url', + ); + console.log('Found the following Internal QA PRs:', internalQAPRs); + const noQAPRs = _.pluck( _.filter(data, PR => (PR.title || '').toUpperCase().startsWith('[NO QA]')), 'html_url', @@ -199,6 +206,7 @@ class GithubUtils { const sortedPRList = _.chain(PRList) .difference(automatedPRs) + .difference(internalQAPRs) .unique() .sortBy(GithubUtils.getPullRequestNumberFromURL) .value(); @@ -221,6 +229,14 @@ class GithubUtils { }); } + if (!_.isEmpty(internalQAPRs)) { + issueBody += '\r\n\r\n\r\n**Internal QA:**'; + _.each(internalQAPRs, (URL) => { + issueBody += `\r\n\r\n- ${URL}`; + issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + }); + } + // Deploy blockers if (!_.isEmpty(deployBlockers)) { issueBody += '\r\n\r\n\r\n**Deploy Blockers:**'; diff --git a/tests/unit/GithubUtilsTest.js b/tests/unit/GithubUtilsTest.js index dff5e60a7b49..d60f0a956afb 100644 --- a/tests/unit/GithubUtilsTest.js +++ b/tests/unit/GithubUtilsTest.js @@ -276,6 +276,38 @@ describe('GithubUtils', () => { user: {login: 'testUser'}, labels: [], }, + { + number: 7, + title: '[Internal QA] Test Internal QA PR', + html_url: 'https://github.com/Expensify/App/pull/7', + user: {login: 'testUser'}, + labels: [ + { + id: 1234, + node_id: 'MDU6TGFiZWwyMDgwNDU5NDY=', + url: 'https://api.github.com/Expensify/App/labels/InternalQA', + name: 'InternalQA', + description: 'An Expensifier needs to test this.', + color: 'f29513', + }, + ], + }, + { + number: 8, + title: '[Internal QA] Another Test Internal QA PR', + html_url: 'https://github.com/Expensify/App/pull/8', + user: {login: 'testUser'}, + labels: [ + { + id: 1234, + node_id: 'MDU6TGFiZWwyMDgwNDU5NDY=', + url: 'https://api.github.com/Expensify/App/labels/InternalQA', + name: 'InternalQA', + description: 'An Expensifier needs to test this.', + color: 'f29513', + }, + ], + }, ]; const mockGithub = jest.fn(() => ({ getOctokit: () => ({ @@ -303,6 +335,11 @@ describe('GithubUtils', () => { 'https://github.com/Expensify/App/pull/6', // No QA ]; + const internalQAPRList = [ + 'https://github.com/Expensify/App/pull/7', // Internal QA + 'https://github.com/Expensify/App/pull/8', // Internal QA + ]; + const baseDeployBlockerList = [ 'https://github.com/Expensify/App/pull/3', 'https://github.com/Expensify/App/issues/4', @@ -317,6 +354,7 @@ describe('GithubUtils', () => { const accessibility = 'Accessibility'; const ccApplauseLeads = 'cc @Expensify/applauseleads\r\n'; const deployBlockerHeader = '\r\n**Deploy Blockers:**'; + const internalQAHeader = '\r\n**Internal QA:**'; const lineBreak = '\r\n'; const lineBreakDouble = '\r\n\r\n'; const indent = ' '; @@ -427,6 +465,42 @@ describe('GithubUtils', () => { ); }) )); + + test('Test internalQA PRs', () => ( + githubUtils.generateStagingDeployCashBody(tag, [...basePRList, ...internalQAPRList]) + .then((issueBody) => { + expect(issueBody).toBe( + `${baseExpectedOutput}` + + `${lineBreakDouble}${listStart}${basePRList[2]}${lineBreak}${indent}${openCheckbox}${QA}${lineBreak}${indent}${openCheckbox}${accessibility}` + + `${lineBreakDouble}${listStart}${basePRList[0]}${lineBreak}${indent}${openCheckbox}${QA}${lineBreak}${indent}${openCheckbox}${accessibility}` + + `${lineBreakDouble}${listStart}${basePRList[1]}${lineBreak}${indent}${openCheckbox}${QA}${lineBreak}${indent}${openCheckbox}${accessibility}` + + `${lineBreakDouble}${listStart}${basePRList[5]}${lineBreak}${indent}${closedCheckbox}${QA}${lineBreak}${indent}${closedCheckbox}${accessibility}` + + `${lineBreakDouble}${listStart}${basePRList[6]}${lineBreak}${indent}${closedCheckbox}${QA}${lineBreak}${indent}${closedCheckbox}${accessibility}` + + `${lineBreakDouble}${internalQAHeader}` + + `${lineBreakDouble}${listStart}${internalQAPRList[0]}${lineBreak}${indent}${openCheckbox}${QA}` + + `${lineBreakDouble}${listStart}${internalQAPRList[1]}${lineBreak}${indent}${openCheckbox}${QA}` + + `${lineBreakDouble}${ccApplauseLeads}`, + ); + }) + )); + + test('Test some verified internalQA PRs', () => ( + githubUtils.generateStagingDeployCashBody(tag, [...basePRList, ...internalQAPRList], [internalQAPRList[0]]) + .then((issueBody) => { + expect(issueBody).toBe( + `${baseExpectedOutput}` + + `${lineBreakDouble}${listStart}${basePRList[2]}${lineBreak}${indent}${openCheckbox}${QA}${lineBreak}${indent}${openCheckbox}${accessibility}` + + `${lineBreakDouble}${listStart}${basePRList[0]}${lineBreak}${indent}${openCheckbox}${QA}${lineBreak}${indent}${openCheckbox}${accessibility}` + + `${lineBreakDouble}${listStart}${basePRList[1]}${lineBreak}${indent}${openCheckbox}${QA}${lineBreak}${indent}${openCheckbox}${accessibility}` + + `${lineBreakDouble}${listStart}${basePRList[5]}${lineBreak}${indent}${closedCheckbox}${QA}${lineBreak}${indent}${closedCheckbox}${accessibility}` + + `${lineBreakDouble}${listStart}${basePRList[6]}${lineBreak}${indent}${closedCheckbox}${QA}${lineBreak}${indent}${closedCheckbox}${accessibility}` + + `${lineBreakDouble}${internalQAHeader}` + + `${lineBreakDouble}${listStart}${internalQAPRList[0]}${lineBreak}${indent}${closedCheckbox}${QA}` + + `${lineBreakDouble}${listStart}${internalQAPRList[1]}${lineBreak}${indent}${openCheckbox}${QA}` + + `${lineBreakDouble}${ccApplauseLeads}`, + ); + }) + )); }); describe('getPullRequestURLFromNumber', () => { From 77292453d27473dd45d9710ac25d96484a320384 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 8 Nov 2021 15:58:47 -0500 Subject: [PATCH 2/9] Append assignee tags to internalQA PRs --- .github/libs/GithubUtils.js | 20 +++++++++++++------- tests/unit/GithubUtilsTest.js | 25 +++++++++++++++++++++---- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/.github/libs/GithubUtils.js b/.github/libs/GithubUtils.js index 309530b0ba9e..5e941fece806 100644 --- a/.github/libs/GithubUtils.js +++ b/.github/libs/GithubUtils.js @@ -190,11 +190,16 @@ class GithubUtils { ); console.log('Filtering out the following automated pull requests:', automatedPRs); - const internalQAPRs = _.pluck( + const internalQAPRMap = _.reduce( _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), - 'html_url', + (map, pr) => { + // eslint-disable-next-line no-param-reassign + map[pr.html_url] = _.pluck(pr.assignees, 'login'); + return map; + }, + {}, ); - console.log('Found the following Internal QA PRs:', internalQAPRs); + console.log('Found the following Internal QA PRs:', internalQAPRMap); const noQAPRs = _.pluck( _.filter(data, PR => (PR.title || '').toUpperCase().startsWith('[NO QA]')), @@ -206,7 +211,7 @@ class GithubUtils { const sortedPRList = _.chain(PRList) .difference(automatedPRs) - .difference(internalQAPRs) + .difference(_.keys(internalQAPRMap)) .unique() .sortBy(GithubUtils.getPullRequestNumberFromURL) .value(); @@ -229,10 +234,11 @@ class GithubUtils { }); } - if (!_.isEmpty(internalQAPRs)) { + if (!_.isEmpty(internalQAPRMap)) { issueBody += '\r\n\r\n\r\n**Internal QA:**'; - _.each(internalQAPRs, (URL) => { - issueBody += `\r\n\r\n- ${URL}`; + _.each(internalQAPRMap, (assignees, URL) => { + const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); + issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; }); } diff --git a/tests/unit/GithubUtilsTest.js b/tests/unit/GithubUtilsTest.js index d60f0a956afb..37e454d3672c 100644 --- a/tests/unit/GithubUtilsTest.js +++ b/tests/unit/GithubUtilsTest.js @@ -291,6 +291,14 @@ describe('GithubUtils', () => { color: 'f29513', }, ], + assignees: [ + { + login: 'octocat', + }, + { + login: 'hubot', + }, + ], }, { number: 8, @@ -307,6 +315,14 @@ describe('GithubUtils', () => { color: 'f29513', }, ], + assignees: [ + { + login: 'octocat', + }, + { + login: 'hubot', + }, + ], }, ]; const mockGithub = jest.fn(() => ({ @@ -358,6 +374,7 @@ describe('GithubUtils', () => { const lineBreak = '\r\n'; const lineBreakDouble = '\r\n\r\n'; const indent = ' '; + const assignOctocatHubot = ' - @octocat @hubot'; // Valid output which will be reused in the deploy blocker tests const allVerifiedExpectedOutput = `${baseExpectedOutput}` @@ -477,8 +494,8 @@ describe('GithubUtils', () => { + `${lineBreakDouble}${listStart}${basePRList[5]}${lineBreak}${indent}${closedCheckbox}${QA}${lineBreak}${indent}${closedCheckbox}${accessibility}` + `${lineBreakDouble}${listStart}${basePRList[6]}${lineBreak}${indent}${closedCheckbox}${QA}${lineBreak}${indent}${closedCheckbox}${accessibility}` + `${lineBreakDouble}${internalQAHeader}` - + `${lineBreakDouble}${listStart}${internalQAPRList[0]}${lineBreak}${indent}${openCheckbox}${QA}` - + `${lineBreakDouble}${listStart}${internalQAPRList[1]}${lineBreak}${indent}${openCheckbox}${QA}` + + `${lineBreakDouble}${listStart}${internalQAPRList[0]}${assignOctocatHubot}${lineBreak}${indent}${openCheckbox}${QA}` + + `${lineBreakDouble}${listStart}${internalQAPRList[1]}${assignOctocatHubot}${lineBreak}${indent}${openCheckbox}${QA}` + `${lineBreakDouble}${ccApplauseLeads}`, ); }) @@ -495,8 +512,8 @@ describe('GithubUtils', () => { + `${lineBreakDouble}${listStart}${basePRList[5]}${lineBreak}${indent}${closedCheckbox}${QA}${lineBreak}${indent}${closedCheckbox}${accessibility}` + `${lineBreakDouble}${listStart}${basePRList[6]}${lineBreak}${indent}${closedCheckbox}${QA}${lineBreak}${indent}${closedCheckbox}${accessibility}` + `${lineBreakDouble}${internalQAHeader}` - + `${lineBreakDouble}${listStart}${internalQAPRList[0]}${lineBreak}${indent}${closedCheckbox}${QA}` - + `${lineBreakDouble}${listStart}${internalQAPRList[1]}${lineBreak}${indent}${openCheckbox}${QA}` + + `${lineBreakDouble}${listStart}${internalQAPRList[0]}${assignOctocatHubot}${lineBreak}${indent}${closedCheckbox}${QA}` + + `${lineBreakDouble}${listStart}${internalQAPRList[1]}${assignOctocatHubot}${lineBreak}${indent}${openCheckbox}${QA}` + `${lineBreakDouble}${ccApplauseLeads}`, ); }) From c211842840aec1b21cb4e23de3953585090ac208 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 8 Nov 2021 17:48:28 -0500 Subject: [PATCH 3/9] Build actions - Start generating internal QA checklist with assignments --- .github/actions/checkDeployBlockers/index.js | 22 +++++++++++++++++++ .../createOrUpdateStagingDeploy/index.js | 22 +++++++++++++++++++ .../actions/getPullRequestDetails/index.js | 22 +++++++++++++++++++ .github/actions/getReleaseBody/index.js | 22 +++++++++++++++++++ .../actions/isPullRequestMergeable/index.js | 22 +++++++++++++++++++ .../actions/isStagingDeployLocked/index.js | 22 +++++++++++++++++++ .../markPullRequestsAsDeployed/index.js | 22 +++++++++++++++++++ .../actions/reopenIssueWithComment/index.js | 22 +++++++++++++++++++ .../actions/triggerWorkflowAndWait/index.js | 22 +++++++++++++++++++ 9 files changed, 198 insertions(+) diff --git a/.github/actions/checkDeployBlockers/index.js b/.github/actions/checkDeployBlockers/index.js index e96a364e75d8..add40635f954 100644 --- a/.github/actions/checkDeployBlockers/index.js +++ b/.github/actions/checkDeployBlockers/index.js @@ -104,6 +104,7 @@ const ISSUE_OR_PULL_REQUEST_REGEX = new RegExp(`${GITHUB_BASE_URL_REGEX.source}/ const APPLAUSE_BOT = 'applausebot'; const STAGING_DEPLOY_CASH_LABEL = 'StagingDeployCash'; const DEPLOY_BLOCKER_CASH_LABEL = 'DeployBlockerCash'; +const INTERNAL_QA_LABEL = 'InternalQA'; class GithubUtils { /** @@ -277,6 +278,17 @@ class GithubUtils { ); console.log('Filtering out the following automated pull requests:', automatedPRs); + const internalQAPRMap = _.reduce( + _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), + (map, pr) => { + // eslint-disable-next-line no-param-reassign + map[pr.html_url] = _.pluck(pr.assignees, 'login'); + return map; + }, + {}, + ); + console.log('Found the following Internal QA PRs:', internalQAPRMap); + const noQAPRs = _.pluck( _.filter(data, PR => (PR.title || '').toUpperCase().startsWith('[NO QA]')), 'html_url', @@ -287,6 +299,7 @@ class GithubUtils { const sortedPRList = _.chain(PRList) .difference(automatedPRs) + .difference(_.keys(internalQAPRMap)) .unique() .sortBy(GithubUtils.getPullRequestNumberFromURL) .value(); @@ -309,6 +322,15 @@ class GithubUtils { }); } + if (!_.isEmpty(internalQAPRMap)) { + issueBody += '\r\n\r\n\r\n**Internal QA:**'; + _.each(internalQAPRMap, (assignees, URL) => { + const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); + issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; + issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + }); + } + // Deploy blockers if (!_.isEmpty(deployBlockers)) { issueBody += '\r\n\r\n\r\n**Deploy Blockers:**'; diff --git a/.github/actions/createOrUpdateStagingDeploy/index.js b/.github/actions/createOrUpdateStagingDeploy/index.js index 13c93feb2d24..72fa5549a8a6 100644 --- a/.github/actions/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/createOrUpdateStagingDeploy/index.js @@ -233,6 +233,7 @@ const ISSUE_OR_PULL_REQUEST_REGEX = new RegExp(`${GITHUB_BASE_URL_REGEX.source}/ const APPLAUSE_BOT = 'applausebot'; const STAGING_DEPLOY_CASH_LABEL = 'StagingDeployCash'; const DEPLOY_BLOCKER_CASH_LABEL = 'DeployBlockerCash'; +const INTERNAL_QA_LABEL = 'InternalQA'; class GithubUtils { /** @@ -406,6 +407,17 @@ class GithubUtils { ); console.log('Filtering out the following automated pull requests:', automatedPRs); + const internalQAPRMap = _.reduce( + _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), + (map, pr) => { + // eslint-disable-next-line no-param-reassign + map[pr.html_url] = _.pluck(pr.assignees, 'login'); + return map; + }, + {}, + ); + console.log('Found the following Internal QA PRs:', internalQAPRMap); + const noQAPRs = _.pluck( _.filter(data, PR => (PR.title || '').toUpperCase().startsWith('[NO QA]')), 'html_url', @@ -416,6 +428,7 @@ class GithubUtils { const sortedPRList = _.chain(PRList) .difference(automatedPRs) + .difference(_.keys(internalQAPRMap)) .unique() .sortBy(GithubUtils.getPullRequestNumberFromURL) .value(); @@ -438,6 +451,15 @@ class GithubUtils { }); } + if (!_.isEmpty(internalQAPRMap)) { + issueBody += '\r\n\r\n\r\n**Internal QA:**'; + _.each(internalQAPRMap, (assignees, URL) => { + const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); + issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; + issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + }); + } + // Deploy blockers if (!_.isEmpty(deployBlockers)) { issueBody += '\r\n\r\n\r\n**Deploy Blockers:**'; diff --git a/.github/actions/getPullRequestDetails/index.js b/.github/actions/getPullRequestDetails/index.js index 783bebbfb767..3ae53cb9db78 100644 --- a/.github/actions/getPullRequestDetails/index.js +++ b/.github/actions/getPullRequestDetails/index.js @@ -157,6 +157,7 @@ const ISSUE_OR_PULL_REQUEST_REGEX = new RegExp(`${GITHUB_BASE_URL_REGEX.source}/ const APPLAUSE_BOT = 'applausebot'; const STAGING_DEPLOY_CASH_LABEL = 'StagingDeployCash'; const DEPLOY_BLOCKER_CASH_LABEL = 'DeployBlockerCash'; +const INTERNAL_QA_LABEL = 'InternalQA'; class GithubUtils { /** @@ -330,6 +331,17 @@ class GithubUtils { ); console.log('Filtering out the following automated pull requests:', automatedPRs); + const internalQAPRMap = _.reduce( + _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), + (map, pr) => { + // eslint-disable-next-line no-param-reassign + map[pr.html_url] = _.pluck(pr.assignees, 'login'); + return map; + }, + {}, + ); + console.log('Found the following Internal QA PRs:', internalQAPRMap); + const noQAPRs = _.pluck( _.filter(data, PR => (PR.title || '').toUpperCase().startsWith('[NO QA]')), 'html_url', @@ -340,6 +352,7 @@ class GithubUtils { const sortedPRList = _.chain(PRList) .difference(automatedPRs) + .difference(_.keys(internalQAPRMap)) .unique() .sortBy(GithubUtils.getPullRequestNumberFromURL) .value(); @@ -362,6 +375,15 @@ class GithubUtils { }); } + if (!_.isEmpty(internalQAPRMap)) { + issueBody += '\r\n\r\n\r\n**Internal QA:**'; + _.each(internalQAPRMap, (assignees, URL) => { + const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); + issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; + issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + }); + } + // Deploy blockers if (!_.isEmpty(deployBlockers)) { issueBody += '\r\n\r\n\r\n**Deploy Blockers:**'; diff --git a/.github/actions/getReleaseBody/index.js b/.github/actions/getReleaseBody/index.js index 8e11a6eff2e7..d1401078f92d 100644 --- a/.github/actions/getReleaseBody/index.js +++ b/.github/actions/getReleaseBody/index.js @@ -75,6 +75,7 @@ const ISSUE_OR_PULL_REQUEST_REGEX = new RegExp(`${GITHUB_BASE_URL_REGEX.source}/ const APPLAUSE_BOT = 'applausebot'; const STAGING_DEPLOY_CASH_LABEL = 'StagingDeployCash'; const DEPLOY_BLOCKER_CASH_LABEL = 'DeployBlockerCash'; +const INTERNAL_QA_LABEL = 'InternalQA'; class GithubUtils { /** @@ -248,6 +249,17 @@ class GithubUtils { ); console.log('Filtering out the following automated pull requests:', automatedPRs); + const internalQAPRMap = _.reduce( + _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), + (map, pr) => { + // eslint-disable-next-line no-param-reassign + map[pr.html_url] = _.pluck(pr.assignees, 'login'); + return map; + }, + {}, + ); + console.log('Found the following Internal QA PRs:', internalQAPRMap); + const noQAPRs = _.pluck( _.filter(data, PR => (PR.title || '').toUpperCase().startsWith('[NO QA]')), 'html_url', @@ -258,6 +270,7 @@ class GithubUtils { const sortedPRList = _.chain(PRList) .difference(automatedPRs) + .difference(_.keys(internalQAPRMap)) .unique() .sortBy(GithubUtils.getPullRequestNumberFromURL) .value(); @@ -280,6 +293,15 @@ class GithubUtils { }); } + if (!_.isEmpty(internalQAPRMap)) { + issueBody += '\r\n\r\n\r\n**Internal QA:**'; + _.each(internalQAPRMap, (assignees, URL) => { + const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); + issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; + issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + }); + } + // Deploy blockers if (!_.isEmpty(deployBlockers)) { issueBody += '\r\n\r\n\r\n**Deploy Blockers:**'; diff --git a/.github/actions/isPullRequestMergeable/index.js b/.github/actions/isPullRequestMergeable/index.js index 8a40171bd26f..812f52eb9141 100644 --- a/.github/actions/isPullRequestMergeable/index.js +++ b/.github/actions/isPullRequestMergeable/index.js @@ -80,6 +80,7 @@ const ISSUE_OR_PULL_REQUEST_REGEX = new RegExp(`${GITHUB_BASE_URL_REGEX.source}/ const APPLAUSE_BOT = 'applausebot'; const STAGING_DEPLOY_CASH_LABEL = 'StagingDeployCash'; const DEPLOY_BLOCKER_CASH_LABEL = 'DeployBlockerCash'; +const INTERNAL_QA_LABEL = 'InternalQA'; class GithubUtils { /** @@ -253,6 +254,17 @@ class GithubUtils { ); console.log('Filtering out the following automated pull requests:', automatedPRs); + const internalQAPRMap = _.reduce( + _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), + (map, pr) => { + // eslint-disable-next-line no-param-reassign + map[pr.html_url] = _.pluck(pr.assignees, 'login'); + return map; + }, + {}, + ); + console.log('Found the following Internal QA PRs:', internalQAPRMap); + const noQAPRs = _.pluck( _.filter(data, PR => (PR.title || '').toUpperCase().startsWith('[NO QA]')), 'html_url', @@ -263,6 +275,7 @@ class GithubUtils { const sortedPRList = _.chain(PRList) .difference(automatedPRs) + .difference(_.keys(internalQAPRMap)) .unique() .sortBy(GithubUtils.getPullRequestNumberFromURL) .value(); @@ -285,6 +298,15 @@ class GithubUtils { }); } + if (!_.isEmpty(internalQAPRMap)) { + issueBody += '\r\n\r\n\r\n**Internal QA:**'; + _.each(internalQAPRMap, (assignees, URL) => { + const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); + issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; + issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + }); + } + // Deploy blockers if (!_.isEmpty(deployBlockers)) { issueBody += '\r\n\r\n\r\n**Deploy Blockers:**'; diff --git a/.github/actions/isStagingDeployLocked/index.js b/.github/actions/isStagingDeployLocked/index.js index c9f88fa7e1c5..e7578015eda6 100644 --- a/.github/actions/isStagingDeployLocked/index.js +++ b/.github/actions/isStagingDeployLocked/index.js @@ -56,6 +56,7 @@ const ISSUE_OR_PULL_REQUEST_REGEX = new RegExp(`${GITHUB_BASE_URL_REGEX.source}/ const APPLAUSE_BOT = 'applausebot'; const STAGING_DEPLOY_CASH_LABEL = 'StagingDeployCash'; const DEPLOY_BLOCKER_CASH_LABEL = 'DeployBlockerCash'; +const INTERNAL_QA_LABEL = 'InternalQA'; class GithubUtils { /** @@ -229,6 +230,17 @@ class GithubUtils { ); console.log('Filtering out the following automated pull requests:', automatedPRs); + const internalQAPRMap = _.reduce( + _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), + (map, pr) => { + // eslint-disable-next-line no-param-reassign + map[pr.html_url] = _.pluck(pr.assignees, 'login'); + return map; + }, + {}, + ); + console.log('Found the following Internal QA PRs:', internalQAPRMap); + const noQAPRs = _.pluck( _.filter(data, PR => (PR.title || '').toUpperCase().startsWith('[NO QA]')), 'html_url', @@ -239,6 +251,7 @@ class GithubUtils { const sortedPRList = _.chain(PRList) .difference(automatedPRs) + .difference(_.keys(internalQAPRMap)) .unique() .sortBy(GithubUtils.getPullRequestNumberFromURL) .value(); @@ -261,6 +274,15 @@ class GithubUtils { }); } + if (!_.isEmpty(internalQAPRMap)) { + issueBody += '\r\n\r\n\r\n**Internal QA:**'; + _.each(internalQAPRMap, (assignees, URL) => { + const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); + issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; + issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + }); + } + // Deploy blockers if (!_.isEmpty(deployBlockers)) { issueBody += '\r\n\r\n\r\n**Deploy Blockers:**'; diff --git a/.github/actions/markPullRequestsAsDeployed/index.js b/.github/actions/markPullRequestsAsDeployed/index.js index b7dcf4123709..a6cf64ebbc19 100644 --- a/.github/actions/markPullRequestsAsDeployed/index.js +++ b/.github/actions/markPullRequestsAsDeployed/index.js @@ -208,6 +208,7 @@ const ISSUE_OR_PULL_REQUEST_REGEX = new RegExp(`${GITHUB_BASE_URL_REGEX.source}/ const APPLAUSE_BOT = 'applausebot'; const STAGING_DEPLOY_CASH_LABEL = 'StagingDeployCash'; const DEPLOY_BLOCKER_CASH_LABEL = 'DeployBlockerCash'; +const INTERNAL_QA_LABEL = 'InternalQA'; class GithubUtils { /** @@ -381,6 +382,17 @@ class GithubUtils { ); console.log('Filtering out the following automated pull requests:', automatedPRs); + const internalQAPRMap = _.reduce( + _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), + (map, pr) => { + // eslint-disable-next-line no-param-reassign + map[pr.html_url] = _.pluck(pr.assignees, 'login'); + return map; + }, + {}, + ); + console.log('Found the following Internal QA PRs:', internalQAPRMap); + const noQAPRs = _.pluck( _.filter(data, PR => (PR.title || '').toUpperCase().startsWith('[NO QA]')), 'html_url', @@ -391,6 +403,7 @@ class GithubUtils { const sortedPRList = _.chain(PRList) .difference(automatedPRs) + .difference(_.keys(internalQAPRMap)) .unique() .sortBy(GithubUtils.getPullRequestNumberFromURL) .value(); @@ -413,6 +426,15 @@ class GithubUtils { }); } + if (!_.isEmpty(internalQAPRMap)) { + issueBody += '\r\n\r\n\r\n**Internal QA:**'; + _.each(internalQAPRMap, (assignees, URL) => { + const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); + issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; + issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + }); + } + // Deploy blockers if (!_.isEmpty(deployBlockers)) { issueBody += '\r\n\r\n\r\n**Deploy Blockers:**'; diff --git a/.github/actions/reopenIssueWithComment/index.js b/.github/actions/reopenIssueWithComment/index.js index 6e2278280df4..6a2a45bf4f80 100644 --- a/.github/actions/reopenIssueWithComment/index.js +++ b/.github/actions/reopenIssueWithComment/index.js @@ -67,6 +67,7 @@ const ISSUE_OR_PULL_REQUEST_REGEX = new RegExp(`${GITHUB_BASE_URL_REGEX.source}/ const APPLAUSE_BOT = 'applausebot'; const STAGING_DEPLOY_CASH_LABEL = 'StagingDeployCash'; const DEPLOY_BLOCKER_CASH_LABEL = 'DeployBlockerCash'; +const INTERNAL_QA_LABEL = 'InternalQA'; class GithubUtils { /** @@ -240,6 +241,17 @@ class GithubUtils { ); console.log('Filtering out the following automated pull requests:', automatedPRs); + const internalQAPRMap = _.reduce( + _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), + (map, pr) => { + // eslint-disable-next-line no-param-reassign + map[pr.html_url] = _.pluck(pr.assignees, 'login'); + return map; + }, + {}, + ); + console.log('Found the following Internal QA PRs:', internalQAPRMap); + const noQAPRs = _.pluck( _.filter(data, PR => (PR.title || '').toUpperCase().startsWith('[NO QA]')), 'html_url', @@ -250,6 +262,7 @@ class GithubUtils { const sortedPRList = _.chain(PRList) .difference(automatedPRs) + .difference(_.keys(internalQAPRMap)) .unique() .sortBy(GithubUtils.getPullRequestNumberFromURL) .value(); @@ -272,6 +285,15 @@ class GithubUtils { }); } + if (!_.isEmpty(internalQAPRMap)) { + issueBody += '\r\n\r\n\r\n**Internal QA:**'; + _.each(internalQAPRMap, (assignees, URL) => { + const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); + issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; + issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + }); + } + // Deploy blockers if (!_.isEmpty(deployBlockers)) { issueBody += '\r\n\r\n\r\n**Deploy Blockers:**'; diff --git a/.github/actions/triggerWorkflowAndWait/index.js b/.github/actions/triggerWorkflowAndWait/index.js index d6c4df3c8277..0c1b9db1f78e 100644 --- a/.github/actions/triggerWorkflowAndWait/index.js +++ b/.github/actions/triggerWorkflowAndWait/index.js @@ -218,6 +218,7 @@ const ISSUE_OR_PULL_REQUEST_REGEX = new RegExp(`${GITHUB_BASE_URL_REGEX.source}/ const APPLAUSE_BOT = 'applausebot'; const STAGING_DEPLOY_CASH_LABEL = 'StagingDeployCash'; const DEPLOY_BLOCKER_CASH_LABEL = 'DeployBlockerCash'; +const INTERNAL_QA_LABEL = 'InternalQA'; class GithubUtils { /** @@ -391,6 +392,17 @@ class GithubUtils { ); console.log('Filtering out the following automated pull requests:', automatedPRs); + const internalQAPRMap = _.reduce( + _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), + (map, pr) => { + // eslint-disable-next-line no-param-reassign + map[pr.html_url] = _.pluck(pr.assignees, 'login'); + return map; + }, + {}, + ); + console.log('Found the following Internal QA PRs:', internalQAPRMap); + const noQAPRs = _.pluck( _.filter(data, PR => (PR.title || '').toUpperCase().startsWith('[NO QA]')), 'html_url', @@ -401,6 +413,7 @@ class GithubUtils { const sortedPRList = _.chain(PRList) .difference(automatedPRs) + .difference(_.keys(internalQAPRMap)) .unique() .sortBy(GithubUtils.getPullRequestNumberFromURL) .value(); @@ -423,6 +436,15 @@ class GithubUtils { }); } + if (!_.isEmpty(internalQAPRMap)) { + issueBody += '\r\n\r\n\r\n**Internal QA:**'; + _.each(internalQAPRMap, (assignees, URL) => { + const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); + issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; + issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + }); + } + // Deploy blockers if (!_.isEmpty(deployBlockers)) { issueBody += '\r\n\r\n\r\n**Deploy Blockers:**'; From e548839a3ecef376ff2e6e160c94537620e32608 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 10 Nov 2021 08:38:50 -0500 Subject: [PATCH 4/9] Update .github/libs/GithubUtils.js Co-authored-by: Rory Abraham <47436092+roryabraham@users.noreply.github.com> --- .github/libs/GithubUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/libs/GithubUtils.js b/.github/libs/GithubUtils.js index 5e941fece806..5b2a02668014 100644 --- a/.github/libs/GithubUtils.js +++ b/.github/libs/GithubUtils.js @@ -194,7 +194,7 @@ class GithubUtils { _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), (map, pr) => { // eslint-disable-next-line no-param-reassign - map[pr.html_url] = _.pluck(pr.assignees, 'login'); + map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login')); return map; }, {}, From 2e8938fdfa74b9bb083f8bffe658350dfd2a1b78 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 10 Nov 2021 08:39:28 -0500 Subject: [PATCH 5/9] Update .github/libs/GithubUtils.js Co-authored-by: Rory Abraham <47436092+roryabraham@users.noreply.github.com> --- .github/libs/GithubUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/libs/GithubUtils.js b/.github/libs/GithubUtils.js index 5b2a02668014..ebcd924a4a26 100644 --- a/.github/libs/GithubUtils.js +++ b/.github/libs/GithubUtils.js @@ -238,7 +238,7 @@ class GithubUtils { issueBody += '\r\n\r\n\r\n**Internal QA:**'; _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); - issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; + issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} ${URL} ${assigneeMentions}`; issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; }); } From d6f850371e22e74cd2e329ce3c9e5252ce67f219 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 10 Nov 2021 08:39:40 -0500 Subject: [PATCH 6/9] Update .github/libs/GithubUtils.js Co-authored-by: Rory Abraham <47436092+roryabraham@users.noreply.github.com> --- .github/libs/GithubUtils.js | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/libs/GithubUtils.js b/.github/libs/GithubUtils.js index ebcd924a4a26..51b181c6b697 100644 --- a/.github/libs/GithubUtils.js +++ b/.github/libs/GithubUtils.js @@ -239,7 +239,6 @@ class GithubUtils { _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} ${URL} ${assigneeMentions}`; - issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; }); } From 4de43339d9e8e2a85e7c280d31a6015a17e0a233 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 10 Nov 2021 08:49:12 -0500 Subject: [PATCH 7/9] Fix URL positioning --- .github/libs/GithubUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/libs/GithubUtils.js b/.github/libs/GithubUtils.js index 51b181c6b697..177973e1601e 100644 --- a/.github/libs/GithubUtils.js +++ b/.github/libs/GithubUtils.js @@ -238,7 +238,7 @@ class GithubUtils { issueBody += '\r\n\r\n\r\n**Internal QA:**'; _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); - issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} ${URL} ${assigneeMentions}`; + issueBody += `\r\n${URL} ${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} ${assigneeMentions}`; }); } From 81a51f7fc216ca3e0fd14efb095a614cf70c8e38 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 10 Nov 2021 09:13:46 -0500 Subject: [PATCH 8/9] Update tests --- .github/libs/GithubUtils.js | 4 +++- tests/unit/GithubUtilsTest.js | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/libs/GithubUtils.js b/.github/libs/GithubUtils.js index 177973e1601e..d750c7340ccb 100644 --- a/.github/libs/GithubUtils.js +++ b/.github/libs/GithubUtils.js @@ -238,7 +238,9 @@ class GithubUtils { issueBody += '\r\n\r\n\r\n**Internal QA:**'; _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); - issueBody += `\r\n${URL} ${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} ${assigneeMentions}`; + issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} `; + issueBody += `${URL}`; + issueBody += ` -${assigneeMentions}`; }); } diff --git a/tests/unit/GithubUtilsTest.js b/tests/unit/GithubUtilsTest.js index 37e454d3672c..c4f0ccf59f1a 100644 --- a/tests/unit/GithubUtilsTest.js +++ b/tests/unit/GithubUtilsTest.js @@ -494,8 +494,8 @@ describe('GithubUtils', () => { + `${lineBreakDouble}${listStart}${basePRList[5]}${lineBreak}${indent}${closedCheckbox}${QA}${lineBreak}${indent}${closedCheckbox}${accessibility}` + `${lineBreakDouble}${listStart}${basePRList[6]}${lineBreak}${indent}${closedCheckbox}${QA}${lineBreak}${indent}${closedCheckbox}${accessibility}` + `${lineBreakDouble}${internalQAHeader}` - + `${lineBreakDouble}${listStart}${internalQAPRList[0]}${assignOctocatHubot}${lineBreak}${indent}${openCheckbox}${QA}` - + `${lineBreakDouble}${listStart}${internalQAPRList[1]}${assignOctocatHubot}${lineBreak}${indent}${openCheckbox}${QA}` + + `${lineBreak}${openCheckbox}${internalQAPRList[0]}${assignOctocatHubot}` + + `${lineBreak}${openCheckbox}${internalQAPRList[1]}${assignOctocatHubot}` + `${lineBreakDouble}${ccApplauseLeads}`, ); }) @@ -512,8 +512,8 @@ describe('GithubUtils', () => { + `${lineBreakDouble}${listStart}${basePRList[5]}${lineBreak}${indent}${closedCheckbox}${QA}${lineBreak}${indent}${closedCheckbox}${accessibility}` + `${lineBreakDouble}${listStart}${basePRList[6]}${lineBreak}${indent}${closedCheckbox}${QA}${lineBreak}${indent}${closedCheckbox}${accessibility}` + `${lineBreakDouble}${internalQAHeader}` - + `${lineBreakDouble}${listStart}${internalQAPRList[0]}${assignOctocatHubot}${lineBreak}${indent}${closedCheckbox}${QA}` - + `${lineBreakDouble}${listStart}${internalQAPRList[1]}${assignOctocatHubot}${lineBreak}${indent}${openCheckbox}${QA}` + + `${lineBreak}${closedCheckbox}${internalQAPRList[0]}${assignOctocatHubot}` + + `${lineBreak}${openCheckbox}${internalQAPRList[1]}${assignOctocatHubot}` + `${lineBreakDouble}${ccApplauseLeads}`, ); }) From 66fc68d1fd7513adfa0083be1418e8bf489b496a Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 10 Nov 2021 09:14:44 -0500 Subject: [PATCH 9/9] Build GH actions --- .github/actions/checkDeployBlockers/index.js | 7 ++++--- .github/actions/createOrUpdateStagingDeploy/index.js | 7 ++++--- .github/actions/getPullRequestDetails/index.js | 7 ++++--- .github/actions/getReleaseBody/index.js | 7 ++++--- .github/actions/isPullRequestMergeable/index.js | 7 ++++--- .github/actions/isStagingDeployLocked/index.js | 7 ++++--- .github/actions/markPullRequestsAsDeployed/index.js | 7 ++++--- .github/actions/reopenIssueWithComment/index.js | 7 ++++--- .github/actions/triggerWorkflowAndWait/index.js | 7 ++++--- 9 files changed, 36 insertions(+), 27 deletions(-) diff --git a/.github/actions/checkDeployBlockers/index.js b/.github/actions/checkDeployBlockers/index.js index add40635f954..1490fc8def3f 100644 --- a/.github/actions/checkDeployBlockers/index.js +++ b/.github/actions/checkDeployBlockers/index.js @@ -282,7 +282,7 @@ class GithubUtils { _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), (map, pr) => { // eslint-disable-next-line no-param-reassign - map[pr.html_url] = _.pluck(pr.assignees, 'login'); + map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login')); return map; }, {}, @@ -326,8 +326,9 @@ class GithubUtils { issueBody += '\r\n\r\n\r\n**Internal QA:**'; _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); - issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; - issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} `; + issueBody += `${URL}`; + issueBody += ` -${assigneeMentions}`; }); } diff --git a/.github/actions/createOrUpdateStagingDeploy/index.js b/.github/actions/createOrUpdateStagingDeploy/index.js index 72fa5549a8a6..0c9c04620081 100644 --- a/.github/actions/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/createOrUpdateStagingDeploy/index.js @@ -411,7 +411,7 @@ class GithubUtils { _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), (map, pr) => { // eslint-disable-next-line no-param-reassign - map[pr.html_url] = _.pluck(pr.assignees, 'login'); + map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login')); return map; }, {}, @@ -455,8 +455,9 @@ class GithubUtils { issueBody += '\r\n\r\n\r\n**Internal QA:**'; _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); - issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; - issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} `; + issueBody += `${URL}`; + issueBody += ` -${assigneeMentions}`; }); } diff --git a/.github/actions/getPullRequestDetails/index.js b/.github/actions/getPullRequestDetails/index.js index 3ae53cb9db78..d6f4972859fb 100644 --- a/.github/actions/getPullRequestDetails/index.js +++ b/.github/actions/getPullRequestDetails/index.js @@ -335,7 +335,7 @@ class GithubUtils { _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), (map, pr) => { // eslint-disable-next-line no-param-reassign - map[pr.html_url] = _.pluck(pr.assignees, 'login'); + map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login')); return map; }, {}, @@ -379,8 +379,9 @@ class GithubUtils { issueBody += '\r\n\r\n\r\n**Internal QA:**'; _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); - issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; - issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} `; + issueBody += `${URL}`; + issueBody += ` -${assigneeMentions}`; }); } diff --git a/.github/actions/getReleaseBody/index.js b/.github/actions/getReleaseBody/index.js index d1401078f92d..e07888a548a7 100644 --- a/.github/actions/getReleaseBody/index.js +++ b/.github/actions/getReleaseBody/index.js @@ -253,7 +253,7 @@ class GithubUtils { _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), (map, pr) => { // eslint-disable-next-line no-param-reassign - map[pr.html_url] = _.pluck(pr.assignees, 'login'); + map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login')); return map; }, {}, @@ -297,8 +297,9 @@ class GithubUtils { issueBody += '\r\n\r\n\r\n**Internal QA:**'; _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); - issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; - issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} `; + issueBody += `${URL}`; + issueBody += ` -${assigneeMentions}`; }); } diff --git a/.github/actions/isPullRequestMergeable/index.js b/.github/actions/isPullRequestMergeable/index.js index 812f52eb9141..acb6cad7cc85 100644 --- a/.github/actions/isPullRequestMergeable/index.js +++ b/.github/actions/isPullRequestMergeable/index.js @@ -258,7 +258,7 @@ class GithubUtils { _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), (map, pr) => { // eslint-disable-next-line no-param-reassign - map[pr.html_url] = _.pluck(pr.assignees, 'login'); + map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login')); return map; }, {}, @@ -302,8 +302,9 @@ class GithubUtils { issueBody += '\r\n\r\n\r\n**Internal QA:**'; _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); - issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; - issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} `; + issueBody += `${URL}`; + issueBody += ` -${assigneeMentions}`; }); } diff --git a/.github/actions/isStagingDeployLocked/index.js b/.github/actions/isStagingDeployLocked/index.js index e7578015eda6..72079750452e 100644 --- a/.github/actions/isStagingDeployLocked/index.js +++ b/.github/actions/isStagingDeployLocked/index.js @@ -234,7 +234,7 @@ class GithubUtils { _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), (map, pr) => { // eslint-disable-next-line no-param-reassign - map[pr.html_url] = _.pluck(pr.assignees, 'login'); + map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login')); return map; }, {}, @@ -278,8 +278,9 @@ class GithubUtils { issueBody += '\r\n\r\n\r\n**Internal QA:**'; _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); - issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; - issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} `; + issueBody += `${URL}`; + issueBody += ` -${assigneeMentions}`; }); } diff --git a/.github/actions/markPullRequestsAsDeployed/index.js b/.github/actions/markPullRequestsAsDeployed/index.js index a6cf64ebbc19..27c498ac781b 100644 --- a/.github/actions/markPullRequestsAsDeployed/index.js +++ b/.github/actions/markPullRequestsAsDeployed/index.js @@ -386,7 +386,7 @@ class GithubUtils { _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), (map, pr) => { // eslint-disable-next-line no-param-reassign - map[pr.html_url] = _.pluck(pr.assignees, 'login'); + map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login')); return map; }, {}, @@ -430,8 +430,9 @@ class GithubUtils { issueBody += '\r\n\r\n\r\n**Internal QA:**'; _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); - issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; - issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} `; + issueBody += `${URL}`; + issueBody += ` -${assigneeMentions}`; }); } diff --git a/.github/actions/reopenIssueWithComment/index.js b/.github/actions/reopenIssueWithComment/index.js index 6a2a45bf4f80..02d874fd23a0 100644 --- a/.github/actions/reopenIssueWithComment/index.js +++ b/.github/actions/reopenIssueWithComment/index.js @@ -245,7 +245,7 @@ class GithubUtils { _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), (map, pr) => { // eslint-disable-next-line no-param-reassign - map[pr.html_url] = _.pluck(pr.assignees, 'login'); + map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login')); return map; }, {}, @@ -289,8 +289,9 @@ class GithubUtils { issueBody += '\r\n\r\n\r\n**Internal QA:**'; _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); - issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; - issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} `; + issueBody += `${URL}`; + issueBody += ` -${assigneeMentions}`; }); } diff --git a/.github/actions/triggerWorkflowAndWait/index.js b/.github/actions/triggerWorkflowAndWait/index.js index 0c1b9db1f78e..9875b3ad7c4c 100644 --- a/.github/actions/triggerWorkflowAndWait/index.js +++ b/.github/actions/triggerWorkflowAndWait/index.js @@ -396,7 +396,7 @@ class GithubUtils { _.filter(data, pr => !_.isEmpty(_.findWhere(pr.labels, {name: INTERNAL_QA_LABEL}))), (map, pr) => { // eslint-disable-next-line no-param-reassign - map[pr.html_url] = _.pluck(pr.assignees, 'login'); + map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login')); return map; }, {}, @@ -440,8 +440,9 @@ class GithubUtils { issueBody += '\r\n\r\n\r\n**Internal QA:**'; _.each(internalQAPRMap, (assignees, URL) => { const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, ''); - issueBody += `\r\n\r\n- ${URL} -${assigneeMentions}`; - issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '\r\n - [x] QA' : '\r\n - [ ] QA'; + issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} `; + issueBody += `${URL}`; + issueBody += ` -${assigneeMentions}`; }); }