diff --git a/.github/actions/javascript/authorChecklist/index.js b/.github/actions/javascript/authorChecklist/index.js
index 528a0a11498a..b20cc83498ba 100644
--- a/.github/actions/javascript/authorChecklist/index.js
+++ b/.github/actions/javascript/authorChecklist/index.js
@@ -255,7 +255,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -268,7 +268,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -281,85 +281,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -393,6 +397,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/awaitStagingDeploys/index.js b/.github/actions/javascript/awaitStagingDeploys/index.js
index f042dbb38a91..6b8401a08d6d 100644
--- a/.github/actions/javascript/awaitStagingDeploys/index.js
+++ b/.github/actions/javascript/awaitStagingDeploys/index.js
@@ -367,7 +367,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -380,7 +380,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -393,85 +393,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -505,6 +509,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/checkDeployBlockers/index.js b/.github/actions/javascript/checkDeployBlockers/index.js
index 8e10f8b1d8b6..dffc089ea5c5 100644
--- a/.github/actions/javascript/checkDeployBlockers/index.js
+++ b/.github/actions/javascript/checkDeployBlockers/index.js
@@ -334,7 +334,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -347,7 +347,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -360,85 +360,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -472,6 +476,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/createOrUpdateStagingDeploy.js b/.github/actions/javascript/createOrUpdateStagingDeploy/createOrUpdateStagingDeploy.js
index 4441348a3c36..63398614fd11 100644
--- a/.github/actions/javascript/createOrUpdateStagingDeploy/createOrUpdateStagingDeploy.js
+++ b/.github/actions/javascript/createOrUpdateStagingDeploy/createOrUpdateStagingDeploy.js
@@ -40,8 +40,11 @@ async function run() {
// Next, we generate the checklist body
let checklistBody = '';
+ let checklistAssignees = [];
if (shouldCreateNewDeployChecklist) {
- checklistBody = await GithubUtils.generateStagingDeployCashBody(newVersionTag, _.map(mergedPRs, GithubUtils.getPullRequestURLFromNumber));
+ const {issueBody, issueAssignees} = await GithubUtils.generateStagingDeployCashBodyAndAssignees(newVersionTag, _.map(mergedPRs, GithubUtils.getPullRequestURLFromNumber));
+ checklistBody = issueBody;
+ checklistAssignees = issueAssignees;
} else {
// Generate the updated PR list, preserving the previous state of `isVerified` for existing PRs
const PRList = _.reduce(
@@ -94,7 +97,7 @@ async function run() {
}
const didVersionChange = newVersionTag !== currentChecklistData.tag;
- checklistBody = await GithubUtils.generateStagingDeployCashBody(
+ const {issueBody, issueAssignees} = await GithubUtils.generateStagingDeployCashBodyAndAssignees(
newVersionTag,
_.pluck(PRList, 'url'),
_.pluck(_.where(PRList, {isVerified: true}), 'url'),
@@ -105,6 +108,8 @@ async function run() {
didVersionChange ? false : currentChecklistData.isFirebaseChecked,
didVersionChange ? false : currentChecklistData.isGHStatusChecked,
);
+ checklistBody = issueBody;
+ checklistAssignees = issueAssignees;
}
// Finally, create or update the checklist
@@ -119,7 +124,7 @@ async function run() {
...defaultPayload,
title: `Deploy Checklist: New Expensify ${format(new Date(), CONST.DATE_FORMAT_STRING)}`,
labels: [CONST.LABELS.STAGING_DEPLOY],
- assignees: [CONST.APPLAUSE_BOT],
+ assignees: [CONST.APPLAUSE_BOT].concat(checklistAssignees),
});
console.log(`Successfully created new StagingDeployCash! 🎉 ${newChecklist.html_url}`);
return newChecklist;
diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js
index 154dacbdc3c3..60ec0b9f0ae3 100644
--- a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js
+++ b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js
@@ -49,8 +49,11 @@ async function run() {
// Next, we generate the checklist body
let checklistBody = '';
+ let checklistAssignees = [];
if (shouldCreateNewDeployChecklist) {
- checklistBody = await GithubUtils.generateStagingDeployCashBody(newVersionTag, _.map(mergedPRs, GithubUtils.getPullRequestURLFromNumber));
+ const {issueBody, issueAssignees} = await GithubUtils.generateStagingDeployCashBodyAndAssignees(newVersionTag, _.map(mergedPRs, GithubUtils.getPullRequestURLFromNumber));
+ checklistBody = issueBody;
+ checklistAssignees = issueAssignees;
} else {
// Generate the updated PR list, preserving the previous state of `isVerified` for existing PRs
const PRList = _.reduce(
@@ -103,7 +106,7 @@ async function run() {
}
const didVersionChange = newVersionTag !== currentChecklistData.tag;
- checklistBody = await GithubUtils.generateStagingDeployCashBody(
+ const {issueBody, issueAssignees} = await GithubUtils.generateStagingDeployCashBodyAndAssignees(
newVersionTag,
_.pluck(PRList, 'url'),
_.pluck(_.where(PRList, {isVerified: true}), 'url'),
@@ -114,6 +117,8 @@ async function run() {
didVersionChange ? false : currentChecklistData.isFirebaseChecked,
didVersionChange ? false : currentChecklistData.isGHStatusChecked,
);
+ checklistBody = issueBody;
+ checklistAssignees = issueAssignees;
}
// Finally, create or update the checklist
@@ -128,7 +133,7 @@ async function run() {
...defaultPayload,
title: `Deploy Checklist: New Expensify ${format(new Date(), CONST.DATE_FORMAT_STRING)}`,
labels: [CONST.LABELS.STAGING_DEPLOY],
- assignees: [CONST.APPLAUSE_BOT],
+ assignees: [CONST.APPLAUSE_BOT].concat(checklistAssignees),
});
console.log(`Successfully created new StagingDeployCash! 🎉 ${newChecklist.html_url}`);
return newChecklist;
@@ -406,7 +411,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -419,7 +424,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -432,85 +437,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -544,6 +553,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/getArtifactInfo/index.js b/.github/actions/javascript/getArtifactInfo/index.js
index ea56ff5f4ebd..b8cb062feba5 100644
--- a/.github/actions/javascript/getArtifactInfo/index.js
+++ b/.github/actions/javascript/getArtifactInfo/index.js
@@ -293,7 +293,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -306,7 +306,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -319,85 +319,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -431,6 +435,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js
index f272929d536a..c57ebf0fefe4 100644
--- a/.github/actions/javascript/getDeployPullRequestList/index.js
+++ b/.github/actions/javascript/getDeployPullRequestList/index.js
@@ -349,7 +349,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -362,7 +362,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -375,85 +375,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -487,6 +491,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/getPullRequestDetails/index.js b/.github/actions/javascript/getPullRequestDetails/index.js
index b8d7d821d64e..9eb608a8cc05 100644
--- a/.github/actions/javascript/getPullRequestDetails/index.js
+++ b/.github/actions/javascript/getPullRequestDetails/index.js
@@ -301,7 +301,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -314,7 +314,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -327,85 +327,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -439,6 +443,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/getReleaseBody/index.js b/.github/actions/javascript/getReleaseBody/index.js
index cc1321ce5cd5..ea12ef5f0df0 100644
--- a/.github/actions/javascript/getReleaseBody/index.js
+++ b/.github/actions/javascript/getReleaseBody/index.js
@@ -301,7 +301,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -314,7 +314,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -327,85 +327,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -439,6 +443,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/isStagingDeployLocked/index.js b/.github/actions/javascript/isStagingDeployLocked/index.js
index 8124c5795a5a..32b8b64d7b82 100644
--- a/.github/actions/javascript/isStagingDeployLocked/index.js
+++ b/.github/actions/javascript/isStagingDeployLocked/index.js
@@ -285,7 +285,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -298,7 +298,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -311,85 +311,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -423,6 +427,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/markPullRequestsAsDeployed/index.js b/.github/actions/javascript/markPullRequestsAsDeployed/index.js
index 36cd0aaefe4a..d275edf9d789 100644
--- a/.github/actions/javascript/markPullRequestsAsDeployed/index.js
+++ b/.github/actions/javascript/markPullRequestsAsDeployed/index.js
@@ -450,7 +450,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -463,7 +463,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -476,85 +476,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -588,6 +592,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/postTestBuildComment/index.js b/.github/actions/javascript/postTestBuildComment/index.js
index 329e0d3aad5d..3bd3e6121be8 100644
--- a/.github/actions/javascript/postTestBuildComment/index.js
+++ b/.github/actions/javascript/postTestBuildComment/index.js
@@ -360,7 +360,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -373,7 +373,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -386,85 +386,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -498,6 +502,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/reopenIssueWithComment/index.js b/.github/actions/javascript/reopenIssueWithComment/index.js
index 6a5f89badb5e..9c740914dc1b 100644
--- a/.github/actions/javascript/reopenIssueWithComment/index.js
+++ b/.github/actions/javascript/reopenIssueWithComment/index.js
@@ -255,7 +255,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -268,7 +268,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -281,85 +281,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -393,6 +397,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/reviewerChecklist/index.js b/.github/actions/javascript/reviewerChecklist/index.js
index 322b529b89bf..7b162f06840d 100644
--- a/.github/actions/javascript/reviewerChecklist/index.js
+++ b/.github/actions/javascript/reviewerChecklist/index.js
@@ -255,7 +255,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -268,7 +268,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -281,85 +281,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -393,6 +397,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/actions/javascript/verifySignedCommits/index.js b/.github/actions/javascript/verifySignedCommits/index.js
index ba188d3a2b86..07173cb19bc5 100644
--- a/.github/actions/javascript/verifySignedCommits/index.js
+++ b/.github/actions/javascript/verifySignedCommits/index.js
@@ -255,7 +255,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -268,7 +268,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -281,85 +281,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -393,6 +397,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/.github/libs/GithubUtils.js b/.github/libs/GithubUtils.js
index 0cd407c78153..47ad2440c165 100644
--- a/.github/libs/GithubUtils.js
+++ b/.github/libs/GithubUtils.js
@@ -222,7 +222,7 @@ class GithubUtils {
}
/**
- * Generate the issue body for a StagingDeployCash.
+ * Generate the issue body and assignees for a StagingDeployCash.
*
* @param {String} tag
* @param {Array} PRList - The list of PR URLs which are included in this StagingDeployCash
@@ -235,7 +235,7 @@ class GithubUtils {
* @param {Boolean} [isGHStatusChecked]
* @returns {Promise}
*/
- static generateStagingDeployCashBody(
+ static generateStagingDeployCashBodyAndAssignees(
tag,
PRList,
verifiedPRList = [],
@@ -248,85 +248,89 @@ class GithubUtils {
) {
return this.fetchAllPullRequests(_.map(PRList, this.getPullRequestNumberFromURL))
.then((data) => {
- // The format of this map is following:
- // {
- // 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
- // 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
- // }
- const internalQAPRMap = _.reduce(
- _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA}))),
- (map, pr) => {
- // eslint-disable-next-line no-param-reassign
- map[pr.html_url] = _.compact(_.pluck(pr.assignees, 'login'));
- return map;
- },
- {},
- );
- console.log('Found the following Internal QA PRs:', internalQAPRMap);
-
- const noQAPRs = _.pluck(
- _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
- 'html_url',
- );
- console.log('Found the following NO QA PRs:', noQAPRs);
- const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
-
- const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
- const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
-
- // Tag version and comparison URL
- // eslint-disable-next-line max-len
- let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
-
- // PR list
- if (!_.isEmpty(sortedPRList)) {
- issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
- _.each(sortedPRList, (URL) => {
- issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
- issueBody += ` ${URL}\r\n`;
- });
- issueBody += '\r\n\r\n';
- }
-
- // Internal QA PR list
- if (!_.isEmpty(internalQAPRMap)) {
- console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
- issueBody += '**Internal QA:**\r\n';
- _.each(internalQAPRMap, (assignees, URL) => {
- const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
- issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
- issueBody += `${URL}`;
- issueBody += ` -${assigneeMentions}`;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
-
- // Deploy blockers
- if (!_.isEmpty(deployBlockers)) {
- issueBody += '**Deploy Blockers:**\r\n';
- _.each(sortedDeployBlockers, (URL) => {
- issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
- issueBody += URL;
- issueBody += '\r\n';
- });
- issueBody += '\r\n\r\n';
- }
-
- issueBody += '**Deployer verifications:**';
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isTimingDashboardChecked ? 'x' : ' '
- }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${
- isFirebaseChecked ? 'x' : ' '
- }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
- // eslint-disable-next-line max-len
- issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
-
- issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
- return issueBody;
+ const internalQAPRs = _.filter(data, (pr) => !_.isEmpty(_.findWhere(pr.labels, {name: CONST.LABELS.INTERNAL_QA})));
+ return Promise.all(_.map(internalQAPRs, (pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({url: pr.html_url, mergerLogin})))).then((results) => {
+ // The format of this map is following:
+ // {
+ // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv',
+ // 'https://github.com/Expensify/App/pull/9642': 'mountiny'
+ // }
+ const internalQAPRMap = _.reduce(
+ results,
+ (acc, {url, mergerLogin}) => {
+ acc[url] = mergerLogin;
+ return acc;
+ },
+ {},
+ );
+ console.log('Found the following Internal QA PRs:', internalQAPRMap);
+
+ const noQAPRs = _.pluck(
+ _.filter(data, (PR) => /\[No\s?QA]/i.test(PR.title)),
+ 'html_url',
+ );
+ console.log('Found the following NO QA PRs:', noQAPRs);
+ const verifiedOrNoQAPRs = _.union(verifiedPRList, noQAPRs);
+
+ const sortedPRList = _.chain(PRList).difference(_.keys(internalQAPRMap)).unique().sortBy(GithubUtils.getPullRequestNumberFromURL).value();
+ const sortedDeployBlockers = _.sortBy(_.unique(deployBlockers), GithubUtils.getIssueOrPullRequestNumberFromURL);
+
+ // Tag version and comparison URL
+ // eslint-disable-next-line max-len
+ let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`;
+
+ // PR list
+ if (!_.isEmpty(sortedPRList)) {
+ issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
+ _.each(sortedPRList, (URL) => {
+ issueBody += _.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]';
+ issueBody += ` ${URL}\r\n`;
+ });
+ issueBody += '\r\n\r\n';
+ }
+
+ // Internal QA PR list
+ if (!_.isEmpty(internalQAPRMap)) {
+ console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
+ issueBody += '**Internal QA:**\r\n';
+ _.each(internalQAPRMap, (merger, URL) => {
+ const mergerMention = `@${merger}`;
+ issueBody += `${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
+ issueBody += `${URL}`;
+ issueBody += ` - ${mergerMention}`;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
+
+ // Deploy blockers
+ if (!_.isEmpty(deployBlockers)) {
+ issueBody += '**Deploy Blockers:**\r\n';
+ _.each(sortedDeployBlockers, (URL) => {
+ issueBody += _.contains(resolvedDeployBlockers, URL) ? '- [x] ' : '- [ ] ';
+ issueBody += URL;
+ issueBody += '\r\n';
+ });
+ issueBody += '\r\n\r\n';
+ }
+
+ issueBody += '**Deployer verifications:**';
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isTimingDashboardChecked ? 'x' : ' '
+ }] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${
+ isFirebaseChecked ? 'x' : ' '
+ }] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`;
+ // eslint-disable-next-line max-len
+ issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`;
+
+ issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n';
+ const issueAssignees = _.uniq(_.values(internalQAPRMap));
+ const issue = {issueBody, issueAssignees};
+ return issue;
+ });
})
.catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err));
}
@@ -360,6 +364,20 @@ class GithubUtils {
.catch((err) => console.error('Failed to get PR list', err));
}
+ /**
+ * @param {Number} pullRequestNumber
+ * @returns {Promise}
+ */
+ static getPullRequestMergerLogin(pullRequestNumber) {
+ return this.octokit.pulls
+ .get({
+ owner: CONST.GITHUB_OWNER,
+ repo: CONST.APP_REPO,
+ pull_number: pullRequestNumber,
+ })
+ .then(({data: pullRequest}) => pullRequest.merged_by.login);
+ }
+
/**
* @param {Number} pullRequestNumber
* @returns {Promise}
diff --git a/__mocks__/@react-native-clipboard/clipboard.js b/__mocks__/@react-native-clipboard/clipboard.js
deleted file mode 100644
index e56e290c3cc9..000000000000
--- a/__mocks__/@react-native-clipboard/clipboard.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import MockClipboard from '@react-native-clipboard/clipboard/jest/clipboard-mock';
-
-export default MockClipboard;
diff --git a/__mocks__/@react-native-clipboard/clipboard.ts b/__mocks__/@react-native-clipboard/clipboard.ts
new file mode 100644
index 000000000000..75b6f09f5345
--- /dev/null
+++ b/__mocks__/@react-native-clipboard/clipboard.ts
@@ -0,0 +1,3 @@
+import clipboardMock from '@react-native-clipboard/clipboard/jest/clipboard-mock';
+
+export default clipboardMock;
diff --git a/__mocks__/react-native-document-picker.js b/__mocks__/react-native-document-picker.ts
similarity index 64%
rename from __mocks__/react-native-document-picker.js
rename to __mocks__/react-native-document-picker.ts
index 8cba2bc1eba4..6d26a0227fc3 100644
--- a/__mocks__/react-native-document-picker.js
+++ b/__mocks__/react-native-document-picker.ts
@@ -1,9 +1,16 @@
-export default {
- getConstants: jest.fn(),
+import type {pick, pickDirectory, releaseSecureAccess, types} from 'react-native-document-picker';
+
+type ReactNativeDocumentPickerMock = {
+ pick: typeof pick;
+ releaseSecureAccess: typeof releaseSecureAccess;
+ pickDirectory: typeof pickDirectory;
+ types: typeof types;
+};
+
+const reactNativeDocumentPickerMock: ReactNativeDocumentPickerMock = {
pick: jest.fn(),
releaseSecureAccess: jest.fn(),
pickDirectory: jest.fn(),
-
types: Object.freeze({
allFiles: 'public.item',
audio: 'public.audio',
@@ -21,3 +28,5 @@ export default {
zip: 'public.zip-archive',
}),
};
+
+export default reactNativeDocumentPickerMock;
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 51f7ffc466b6..62e30858e73c 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -98,8 +98,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
- versionCode 1001045601
- versionName "1.4.56-1"
+ versionCode 1001045602
+ versionName "1.4.56-2"
}
flavorDimensions "default"
diff --git a/desktop/package-lock.json b/desktop/package-lock.json
index b8ae9d0a2be5..efa8a25a0614 100644
--- a/desktop/package-lock.json
+++ b/desktop/package-lock.json
@@ -10,7 +10,7 @@
"electron-context-menu": "^2.3.0",
"electron-log": "^4.4.8",
"electron-serve": "^1.3.0",
- "electron-updater": "^6.1.9",
+ "electron-updater": "^6.2.1",
"node-machine-id": "^1.1.12"
}
},
@@ -156,9 +156,9 @@
}
},
"node_modules/electron-updater": {
- "version": "6.1.9",
- "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.1.9.tgz",
- "integrity": "sha512-omoTwGSG+/H8G62cEZS/dc5Lmc4HohAd4198AP+JNv8H7bfxXUCKekaR6WpsN1n2DiWzvcqOusfGSogZv/uj9w==",
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.2.1.tgz",
+ "integrity": "sha512-83eKIPW14qwZqUUM6wdsIRwVKZyjmHxQ4/8G+1C6iS5PdDt7b1umYQyj1/qPpH510GmHEQe4q0kCPe3qmb3a0Q==",
"dependencies": {
"builder-util-runtime": "9.2.4",
"fs-extra": "^10.1.0",
@@ -541,9 +541,9 @@
"integrity": "sha512-OEC/48ZBJxR6XNSZtCl4cKPyQ1lvsu8yp8GdCplMWwGS1eEyMcEmzML5BRs/io/RLDnpgyf+7rSL+X6ICifRIg=="
},
"electron-updater": {
- "version": "6.1.9",
- "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.1.9.tgz",
- "integrity": "sha512-omoTwGSG+/H8G62cEZS/dc5Lmc4HohAd4198AP+JNv8H7bfxXUCKekaR6WpsN1n2DiWzvcqOusfGSogZv/uj9w==",
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.2.1.tgz",
+ "integrity": "sha512-83eKIPW14qwZqUUM6wdsIRwVKZyjmHxQ4/8G+1C6iS5PdDt7b1umYQyj1/qPpH510GmHEQe4q0kCPe3qmb3a0Q==",
"requires": {
"builder-util-runtime": "9.2.4",
"fs-extra": "^10.1.0",
diff --git a/desktop/package.json b/desktop/package.json
index 606fcac92500..4249f3fcfba9 100644
--- a/desktop/package.json
+++ b/desktop/package.json
@@ -7,7 +7,7 @@
"electron-context-menu": "^2.3.0",
"electron-log": "^4.4.8",
"electron-serve": "^1.3.0",
- "electron-updater": "^6.1.9",
+ "electron-updater": "^6.2.1",
"node-machine-id": "^1.1.12"
},
"author": "Expensify, Inc.",
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index e8f3bc7c38e2..a962c69f0bc6 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -40,7 +40,7 @@
CFBundleVersion
- 1.4.56.1
+ 1.4.56.2
ITSAppUsesNonExemptEncryption
LSApplicationQueriesSchemes
diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist
index fec078bdb26c..9f20eb574abc 100644
--- a/ios/NewExpensifyTests/Info.plist
+++ b/ios/NewExpensifyTests/Info.plist
@@ -19,6 +19,6 @@
CFBundleSignature
????
CFBundleVersion
- 1.4.56.1
+ 1.4.56.2
diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist
index 3fce69f13cdc..2319ff879a03 100644
--- a/ios/NotificationServiceExtension/Info.plist
+++ b/ios/NotificationServiceExtension/Info.plist
@@ -13,7 +13,7 @@
CFBundleShortVersionString
1.4.56
CFBundleVersion
- 1.4.56.1
+ 1.4.56.2
NSExtension
NSExtensionPointIdentifier
diff --git a/package-lock.json b/package-lock.json
index 9f0916546172..fcebc3cd46dd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "new.expensify",
- "version": "1.4.56-1",
+ "version": "1.4.56-2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "new.expensify",
- "version": "1.4.56-1",
+ "version": "1.4.56-2",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
diff --git a/package.json b/package.json
index e6531ae5e7e7..c41afac9d570 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.4.56-1",
+ "version": "1.4.56-2",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
@@ -50,8 +50,8 @@
"analyze-packages": "ANALYZE_BUNDLE=true webpack --config config/webpack/webpack.common.js --env envFile=.env.production",
"symbolicate:android": "npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map",
"symbolicate:ios": "npx metro-symbolicate main.jsbundle.map",
- "symbolicate-release:ios": "scripts/release-profile.js --platform=ios",
- "symbolicate-release:android": "scripts/release-profile.js --platform=android",
+ "symbolicate-release:ios": "scripts/release-profile.ts --platform=ios",
+ "symbolicate-release:android": "scripts/release-profile.ts --platform=android",
"test:e2e": "ts-node tests/e2e/testRunner.ts --config ./config.local.ts",
"test:e2e:dev": "ts-node tests/e2e/testRunner.ts --config ./config.dev.ts",
"gh-actions-unused-styles": "./.github/scripts/findUnusedKeys.sh",
diff --git a/scripts/release-profile.js b/scripts/release-profile.ts
similarity index 83%
rename from scripts/release-profile.js
rename to scripts/release-profile.ts
index 0f96232bcdca..8ec0979f9f9e 100755
--- a/scripts/release-profile.js
+++ b/scripts/release-profile.ts
@@ -1,13 +1,15 @@
-#!/usr/bin/env node
+#!/usr/bin/env ts-node
+
/* eslint-disable no-console */
+import {execSync} from 'child_process';
+import fs from 'fs';
-const fs = require('fs');
-const {execSync} = require('child_process');
+type ArgsMap = Record;
// Function to parse command-line arguments into a key-value object
-function parseCommandLineArguments() {
+function parseCommandLineArguments(): ArgsMap {
const args = process.argv.slice(2); // Skip node and script paths
- const argsMap = {};
+ const argsMap: ArgsMap = {};
args.forEach((arg) => {
const [key, value] = arg.split('=');
if (key.startsWith('--')) {
@@ -20,14 +22,13 @@ function parseCommandLineArguments() {
// Function to find .cpuprofile files in the current directory
function findCpuProfileFiles() {
const files = fs.readdirSync(process.cwd());
- // eslint-disable-next-line rulesdir/prefer-underscore-method
return files.filter((file) => file.endsWith('.cpuprofile'));
}
const argsMap = parseCommandLineArguments();
// Determine sourcemapPath based on the platform flag passed
-let sourcemapPath;
+let sourcemapPath: string | undefined;
if (argsMap.platform === 'ios') {
sourcemapPath = 'main.jsbundle.map';
} else if (argsMap.platform === 'android') {
@@ -57,7 +58,10 @@ if (cpuProfiles.length === 0) {
const output = execSync(command, {stdio: 'inherit'});
console.log(output.toString());
} catch (error) {
- console.error(`Error executing command: ${error}`);
+ if (error instanceof Error) {
+ console.error(`Error executing command: ${error.toString()}`);
+ }
+
process.exit(1);
}
}
diff --git a/src/CONST.ts b/src/CONST.ts
index 532939c10f1a..d13c3b374f5a 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -1679,7 +1679,7 @@ const CONST = {
POLICY_ID_FROM_PATH: /\/w\/([a-zA-Z0-9]+)(\/|$)/,
- SHORT_MENTION: new RegExp(`@[\\w\\-\\+\\'#]+(?:\\.[\\w\\-\\'\\+]+)*`, 'gim'),
+ SHORT_MENTION: new RegExp(`@[\\w\\-\\+\\'#@]+(?:\\.[\\w\\-\\'\\+]+)*`, 'gim'),
},
PRONOUNS: {
diff --git a/src/components/HeaderWithBackButton/index.tsx b/src/components/HeaderWithBackButton/index.tsx
index 21f3e9a3b605..f3293596aa46 100755
--- a/src/components/HeaderWithBackButton/index.tsx
+++ b/src/components/HeaderWithBackButton/index.tsx
@@ -15,7 +15,6 @@ import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import useThrottledButtonState from '@hooks/useThrottledButtonState';
-import useWaitForNavigation from '@hooks/useWaitForNavigation';
import getButtonState from '@libs/getButtonState';
import Navigation from '@libs/Navigation/Navigation';
import variables from '@styles/variables';
@@ -58,7 +57,6 @@ function HeaderWithBackButton({
children = null,
shouldOverlayDots = false,
shouldOverlay = false,
- singleExecution = (func) => func,
shouldNavigateToTopMostReport = false,
style,
}: HeaderWithBackButtonProps) {
@@ -68,7 +66,6 @@ function HeaderWithBackButton({
const [isDownloadButtonActive, temporarilyDisableDownloadButton] = useThrottledButtonState();
const {translate} = useLocalize();
const {isKeyboardShown} = useKeyboardState();
- const waitForNavigate = useWaitForNavigation();
// If the icon is present, the header bar should be taller and use different font.
const isCentralPaneSettings = !!icon;
@@ -175,7 +172,7 @@ function HeaderWithBackButton({
Navigation.navigate(ROUTES.GET_ASSISTANCE.getRoute(guidesCallTaskID, Navigation.getActiveRoute()))))}
+ onPress={() => Navigation.navigate(ROUTES.GET_ASSISTANCE.getRoute(guidesCallTaskID, Navigation.getActiveRoute()))}
style={[styles.touchableButtonImage]}
role="button"
accessibilityLabel={translate('getAssistancePage.questionMarkButtonTooltip')}
diff --git a/src/components/ScreenWrapper.tsx b/src/components/ScreenWrapper.tsx
index 827eec8088a6..b78e274371ca 100644
--- a/src/components/ScreenWrapper.tsx
+++ b/src/components/ScreenWrapper.tsx
@@ -23,6 +23,7 @@ import KeyboardAvoidingView from './KeyboardAvoidingView';
import OfflineIndicator from './OfflineIndicator';
import SafeAreaConsumer from './SafeAreaConsumer';
import TestToolsModal from './TestToolsModal';
+import withNavigationFallback from './withNavigationFallback';
type ChildrenProps = {
insets: EdgeInsets;
@@ -279,4 +280,4 @@ function ScreenWrapper(
ScreenWrapper.displayName = 'ScreenWrapper';
-export default forwardRef(ScreenWrapper);
+export default withNavigationFallback(forwardRef(ScreenWrapper));
diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx
index 0ea8ea308d6a..690a9485f099 100644
--- a/src/components/SettlementButton.tsx
+++ b/src/components/SettlementButton.tsx
@@ -143,9 +143,8 @@ function SettlementButton({
const session = useSession();
const chatReport = ReportUtils.getReport(chatReportID);
const isPaidGroupPolicy = ReportUtils.isPaidGroupPolicyExpenseChat(chatReport as OnyxEntry);
- const shouldShowPaywithExpensifyOption =
- !isPaidGroupPolicy ||
- (!shouldHidePaymentOptions && policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES && policy?.reimburserEmail === session?.email);
+ const shouldShowPaywithExpensifyOption = !isPaidGroupPolicy || (!shouldHidePaymentOptions && ReportUtils.isPayer(session, iouReport as OnyxEntry));
+ const shouldShowPayElsewhereOption = !isPaidGroupPolicy || policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL;
const paymentButtonOptions = useMemo(() => {
const buttonOptions = [];
const isExpenseReport = ReportUtils.isExpenseReport(iouReport);
@@ -189,7 +188,9 @@ function SettlementButton({
if (isExpenseReport && shouldShowPaywithExpensifyOption) {
buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.VBBA]);
}
- buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]);
+ if (shouldShowPayElsewhereOption) {
+ buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]);
+ }
if (shouldShowApproveButton) {
buttonOptions.push(approveButtonOption);
diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts
index f501244a725d..3b3e24867a4f 100644
--- a/src/libs/ModifiedExpenseMessage.ts
+++ b/src/libs/ModifiedExpenseMessage.ts
@@ -5,9 +5,9 @@ import ONYXKEYS from '@src/ONYXKEYS';
import type {PolicyTagList, ReportAction} from '@src/types/onyx';
import * as CurrencyUtils from './CurrencyUtils';
import DateUtils from './DateUtils';
+import getReportPolicyID from './getReportPolicyID';
import * as Localize from './Localize';
import * as PolicyUtils from './PolicyUtils';
-import * as ReportUtils from './ReportUtils';
import type {ExpenseOriginalMessage} from './ReportUtils';
import * as TransactionUtils from './TransactionUtils';
@@ -97,12 +97,12 @@ function getForDistanceRequest(newDistance: string, oldDistance: string, newAmou
* ModifiedExpense::getNewDotComment in Web-Expensify should match this.
* If we change this function be sure to update the backend as well.
*/
-function getForReportAction(reportID: string | undefined, reportAction: OnyxEntry): string {
+function getForReportAction(reportID: string | undefined, reportAction: OnyxEntry | ReportAction | Record): string {
if (reportAction?.actionName !== CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE) {
return '';
}
const reportActionOriginalMessage = reportAction?.originalMessage as ExpenseOriginalMessage | undefined;
- const policyID = ReportUtils.getReportPolicyID(reportID) ?? '';
+ const policyID = getReportPolicyID(reportID) ?? '';
const removalFragments: string[] = [];
const setFragments: string[] = [];
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index 1df59508257a..64bac4f46b5a 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -135,7 +135,7 @@ function isReportPreviewAction(reportAction: OnyxEntry): boolean {
return reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW;
}
-function isModifiedExpenseAction(reportAction: OnyxEntry): boolean {
+function isModifiedExpenseAction(reportAction: OnyxEntry | ReportAction | Record): boolean {
return reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE;
}
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 9ee97ff8a988..aca25f4926a8 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -55,11 +55,13 @@ import * as store from './actions/ReimbursementAccount/store';
import * as CollectionUtils from './CollectionUtils';
import * as CurrencyUtils from './CurrencyUtils';
import DateUtils from './DateUtils';
+import originalGetReportPolicyID from './getReportPolicyID';
import isReportMessageAttachment from './isReportMessageAttachment';
import localeCompare from './LocaleCompare';
import * as LocalePhoneNumber from './LocalePhoneNumber';
import * as Localize from './Localize';
import {isEmailPublicDomain} from './LoginUtils';
+import ModifiedExpenseMessage from './ModifiedExpenseMessage';
import linkingConfig from './Navigation/linkingConfig';
import Navigation from './Navigation/Navigation';
import * as NumberUtils from './NumberUtils';
@@ -1286,7 +1288,7 @@ function isPayer(session: OnyxEntry, iouReport: OnyxEntry) {
if (isPaidGroupPolicy(iouReport)) {
if (policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES) {
const isReimburser = session?.email === policy?.reimburserEmail;
- return isReimburser && (isApproved || isManager);
+ return (!policy?.reimburserEmail || isReimburser) && (isApproved || isManager);
}
if (policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL) {
return isAdmin && (isApproved || isManager);
@@ -2772,6 +2774,9 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu
if (parentReportActionMessage && isArchivedRoom(report)) {
return `${parentReportActionMessage} (${Localize.translateLocal('common.archived')})`;
}
+ if (ReportActionsUtils.isModifiedExpenseAction(parentReportAction)) {
+ return ModifiedExpenseMessage.getForReportAction(report?.reportID, parentReportAction);
+ }
return parentReportActionMessage;
}
@@ -4619,7 +4624,7 @@ function getReportIDFromLink(url: string | null): string {
* Get the report policyID given a reportID
*/
function getReportPolicyID(reportID?: string): string | undefined {
- return getReport(reportID)?.policyID;
+ return originalGetReportPolicyID(reportID);
}
/**
diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts
index 857f6f39173a..5632268ef6ca 100644
--- a/src/libs/actions/IOU.ts
+++ b/src/libs/actions/IOU.ts
@@ -4484,30 +4484,6 @@ function sendMoneyWithWallet(report: OnyxTypes.Report, amount: number, currency:
Report.notifyNewAction(params.chatReportID, managerID);
}
-function canIOUBePaid(iouReport: OnyxEntry | EmptyObject, chatReport: OnyxEntry | EmptyObject, policy: OnyxEntry | EmptyObject) {
- const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(chatReport);
- const iouCanceled = ReportUtils.isArchivedRoom(chatReport);
-
- if (isEmptyObject(iouReport)) {
- return false;
- }
-
- const isPayer = ReportUtils.isPayer(
- {
- email: currentUserEmail,
- accountID: userAccountID,
- },
- iouReport,
- );
-
- const isOpenExpenseReport = isPolicyExpenseChat && ReportUtils.isOpenExpenseReport(iouReport);
- const iouSettled = ReportUtils.isSettled(iouReport?.reportID);
-
- const {reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(iouReport);
- const isAutoReimbursable = ReportUtils.canBeAutoReimbursed(iouReport, policy);
- return isPayer && !isOpenExpenseReport && !iouSettled && !iouReport?.isWaitingOnBankAccount && reimbursableSpend !== 0 && !iouCanceled && !isAutoReimbursable;
-}
-
function canApproveIOU(iouReport: OnyxEntry | EmptyObject, chatReport: OnyxEntry | EmptyObject, policy: OnyxEntry | EmptyObject) {
if (isEmptyObject(chatReport)) {
return false;
@@ -4534,6 +4510,36 @@ function canApproveIOU(iouReport: OnyxEntry | EmptyObject, cha
return isCurrentUserManager && !isOpenExpenseReport && !isApproved && !iouSettled;
}
+function canIOUBePaid(iouReport: OnyxEntry | EmptyObject, chatReport: OnyxEntry | EmptyObject, policy: OnyxEntry | EmptyObject) {
+ const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(chatReport);
+ const iouCanceled = ReportUtils.isArchivedRoom(chatReport);
+
+ if (isEmptyObject(iouReport)) {
+ return false;
+ }
+
+ if (policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO) {
+ return false;
+ }
+
+ const isPayer = ReportUtils.isPayer(
+ {
+ email: currentUserEmail,
+ accountID: userAccountID,
+ },
+ iouReport,
+ );
+
+ const isOpenExpenseReport = isPolicyExpenseChat && ReportUtils.isOpenExpenseReport(iouReport);
+ const iouSettled = ReportUtils.isSettled(iouReport?.reportID);
+
+ const {reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(iouReport);
+ const isAutoReimbursable = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES ? false : ReportUtils.canBeAutoReimbursed(iouReport, policy);
+ const shouldBeApproved = canApproveIOU(iouReport, chatReport, policy);
+
+ return isPayer && !isOpenExpenseReport && !iouSettled && !iouReport?.isWaitingOnBankAccount && reimbursableSpend !== 0 && !iouCanceled && !isAutoReimbursable && !shouldBeApproved;
+}
+
function hasIOUToApproveOrPay(chatReport: OnyxEntry | EmptyObject, excludedIOUReportID: string): boolean {
const chatReportActions = ReportActionsUtils.getAllReportActions(chatReport?.reportID ?? '');
diff --git a/src/libs/actions/Link.ts b/src/libs/actions/Link.ts
index ae95424f5776..c83c946aed46 100644
--- a/src/libs/actions/Link.ts
+++ b/src/libs/actions/Link.ts
@@ -10,6 +10,7 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Route} from '@src/ROUTES';
import ROUTES from '@src/ROUTES';
+import * as Session from './Session';
let isNetworkOffline = false;
Onyx.connect({
@@ -102,6 +103,10 @@ function openLink(href: string, environmentURL: string, isAttachment = false) {
// If we are handling a New Expensify link then we will assume this should be opened by the app internally. This ensures that the links are opened internally via react-navigation
// instead of in a new tab or with a page refresh (which is the default behavior of an anchor tag)
if (internalNewExpensifyPath && hasSameOrigin) {
+ if (Session.isAnonymousUser() && !Session.canAnonymousUserAccessRoute(internalNewExpensifyPath)) {
+ Session.signOutAndRedirectToSignIn();
+ return;
+ }
Navigation.navigate(internalNewExpensifyPath as Route);
return;
}
diff --git a/src/libs/getReportPolicyID.ts b/src/libs/getReportPolicyID.ts
new file mode 100644
index 000000000000..12124f24fbe7
--- /dev/null
+++ b/src/libs/getReportPolicyID.ts
@@ -0,0 +1,33 @@
+import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
+import Onyx from 'react-native-onyx';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {Report} from '@src/types/onyx';
+import type {EmptyObject} from '@src/types/utils/EmptyObject';
+
+let allReports: OnyxCollection;
+Onyx.connect({
+ key: ONYXKEYS.COLLECTION.REPORT,
+ waitForCollectionCallback: true,
+ callback: (value) => (allReports = value),
+});
+
+/**
+ * Get the report given a reportID
+ */
+function getReport(reportID: string | undefined): OnyxEntry | EmptyObject {
+ if (!allReports) {
+ return {};
+ }
+
+ return allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? {};
+}
+
+/**
+ * Get the report policyID given a reportID.
+ * We need to define this method in a separate file to avoid cyclic dependency.
+ */
+function getReportPolicyID(reportID?: string): string | undefined {
+ return getReport(reportID)?.policyID;
+}
+
+export default getReportPolicyID;
diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx
index aa03714394b1..9bc0c4c3a4a8 100644
--- a/src/pages/home/ReportScreen.tsx
+++ b/src/pages/home/ReportScreen.tsx
@@ -269,7 +269,6 @@ function ReportScreen({
const hasHelpfulErrors = Object.keys(report?.errorFields ?? {}).some((key) => key !== 'notFound');
const shouldHideReport = !hasHelpfulErrors && !ReportUtils.canAccessReport(report, policies, betas);
- const isLoading = !reportIDFromRoute || !isSidebarLoaded || PersonalDetailsUtils.isPersonalDetailsEmpty();
const lastReportAction: OnyxEntry = useMemo(
() =>
reportActions.length
@@ -331,14 +330,28 @@ function ReportScreen({
return reportIDFromRoute !== '' && !!report.reportID && !isTransitioning;
}, [report, reportIDFromRoute]);
+ const isLoading = !ReportUtils.isValidReportIDFromPath(reportIDFromRoute) || !isSidebarLoaded || PersonalDetailsUtils.isPersonalDetailsEmpty();
const shouldShowSkeleton =
isLinkingToMessage ||
!isCurrentReportLoadedFromOnyx ||
(reportActions.length === 0 && !!reportMetadata?.isLoadingInitialReportActions) ||
isLoading ||
(!!reportActionIDFromRoute && reportMetadata?.isLoadingInitialReportActions);
-
const shouldShowReportActionList = isCurrentReportLoadedFromOnyx && !isLoading;
+ // eslint-disable-next-line rulesdir/no-negated-variables
+ const shouldShowNotFoundPage = useMemo(
+ (): boolean =>
+ !shouldShowSkeleton &&
+ ((!wasReportAccessibleRef.current &&
+ !firstRenderRef.current &&
+ !report.reportID &&
+ !isOptimisticDelete &&
+ !reportMetadata?.isLoadingInitialReportActions &&
+ !userLeavingStatus) ||
+ shouldHideReport ||
+ (!!reportIDFromRoute && !ReportUtils.isValidReportIDFromPath(reportIDFromRoute))),
+ [shouldShowSkeleton, report.reportID, isOptimisticDelete, reportMetadata?.isLoadingInitialReportActions, userLeavingStatus, shouldHideReport, reportIDFromRoute],
+ );
const fetchReport = useCallback(() => {
Report.openReport(reportIDFromRoute, reportActionIDFromRoute);
@@ -528,21 +541,6 @@ function ReportScreen({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- // eslint-disable-next-line rulesdir/no-negated-variables
- const shouldShowNotFoundPage = useMemo(
- (): boolean =>
- (!wasReportAccessibleRef.current &&
- !firstRenderRef.current &&
- !report.reportID &&
- !isOptimisticDelete &&
- !reportMetadata?.isLoadingInitialReportActions &&
- !isLoading &&
- !userLeavingStatus) ||
- shouldHideReport ||
- (!!reportIDFromRoute && !ReportUtils.isValidReportIDFromPath(reportIDFromRoute)),
- [report, reportMetadata, isLoading, shouldHideReport, isOptimisticDelete, userLeavingStatus, reportIDFromRoute],
- );
-
const actionListValue = useMemo((): ActionListContextType => ({flatListRef, scrollPosition, setScrollPosition}), [flatListRef, scrollPosition, setScrollPosition]);
// This helps in tracking from the moment 'route' triggers useMemo until isLoadingInitialReportActions becomes true. It prevents blinking when loading reportActions from cache.
diff --git a/src/stories/HeaderWithBackButton.stories.tsx b/src/stories/HeaderWithBackButton.stories.tsx
index 8306d8e19225..ca723715d5f0 100644
--- a/src/stories/HeaderWithBackButton.stories.tsx
+++ b/src/stories/HeaderWithBackButton.stories.tsx
@@ -2,25 +2,22 @@ import type {ComponentMeta, ComponentStory} from '@storybook/react';
import React from 'react';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import type HeaderWithBackButtonProps from '@components/HeaderWithBackButton/types';
-import withNavigationFallback from '@components/withNavigationFallback';
-const HeaderWithBackButtonWithNavigation = withNavigationFallback(HeaderWithBackButton);
-
-type HeaderWithBackButtonStory = ComponentStory;
+type HeaderWithBackButtonStory = ComponentStory;
/**
* We use the Component Story Format for writing stories. Follow the docs here:
*
* https://storybook.js.org/docs/react/writing-stories/introduction#component-story-format
*/
-const story: ComponentMeta = {
+const story: ComponentMeta = {
title: 'Components/HeaderWithBackButton',
- component: HeaderWithBackButtonWithNavigation,
+ component: HeaderWithBackButton,
};
function Template(props: HeaderWithBackButtonProps) {
// eslint-disable-next-line react/jsx-props-no-spreading
- return ;
+ return ;
}
// Arguments can be passed to the component by binding
diff --git a/src/styles/index.ts b/src/styles/index.ts
index 120b848bd5a4..a56a858d1707 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -1552,7 +1552,6 @@ const styles = (theme: ThemeColors) =>
breadcrumbLogo: {
top: 1.66, // Pixel-perfect alignment due to a small difference between logo height and breadcrumb text height
- height: variables.lineHeightSizeh1,
},
LHPNavigatorContainer: (isSmallScreenWidth: boolean) =>
diff --git a/src/types/modules/act.d.ts b/src/types/modules/act.d.ts
deleted file mode 100644
index 5fe00ec479cf..000000000000
--- a/src/types/modules/act.d.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import type {StepIdentifier as ActStepIdentifier} from '@kie/act-js';
-
-declare module '@kie/act-js' {
- // eslint-disable-next-line rulesdir/no-inline-named-export
- export declare type StepIdentifier = {
- id?: string;
- name: string;
- run?: string;
- mockWith?: string;
- with?: string;
- envs?: string[];
- inputs?: string[];
- } & Omit;
-}
diff --git a/src/types/modules/react-native-clipboard.d.ts b/src/types/modules/react-native-clipboard.d.ts
index 14f418a3f8b9..c38b3b2ff7cc 100644
--- a/src/types/modules/react-native-clipboard.d.ts
+++ b/src/types/modules/react-native-clipboard.d.ts
@@ -1,16 +1,7 @@
declare module '@react-native-clipboard/clipboard/jest/clipboard-mock' {
- const mockClipboard: {
- getString: jest.MockedFunction<() => Promise>;
- getImagePNG: jest.MockedFunction<() => void>;
- getImageJPG: jest.MockedFunction<() => void>;
- setImage: jest.MockedFunction<() => void>;
- setString: jest.MockedFunction<() => void>;
- hasString: jest.MockedFunction<() => Promise>;
- hasImage: jest.MockedFunction<() => Promise>;
- hasURL: jest.MockedFunction<() => Promise>;
- addListener: jest.MockedFunction<() => void>;
- removeAllListeners: jest.MockedFunction<() => void>;
- useClipboard: jest.MockedFunction<() => [string, jest.MockedFunction<() => void>]>;
- };
- export default mockClipboard;
+ import type Clipboard from '@react-native-clipboard/clipboard';
+
+ const clipboardMock: typeof Clipboard;
+
+ export default clipboardMock;
}
diff --git a/tests/unit/GithubUtilsTest.ts b/tests/unit/GithubUtilsTest.ts
index 794139286527..8267b26d3d0f 100644
--- a/tests/unit/GithubUtilsTest.ts
+++ b/tests/unit/GithubUtilsTest.ts
@@ -355,7 +355,7 @@ describe('GithubUtils', () => {
},
{
number: 6,
- title: '[Internal QA] Test Internal QA PR',
+ title: '[Internal QA] Another Test Internal QA PR',
html_url: 'https://github.com/Expensify/App/pull/6',
user: {login: 'testUser'},
labels: [
@@ -368,14 +368,7 @@ describe('GithubUtils', () => {
color: 'f29513',
},
],
- assignees: [
- {
- login: 'octocat',
- },
- {
- login: 'hubot',
- },
- ],
+ assignees: [],
},
{
number: 7,
@@ -392,16 +385,12 @@ describe('GithubUtils', () => {
color: 'f29513',
},
],
- assignees: [
- {
- login: 'octocat',
- },
- {
- login: 'hubot',
- },
- ],
+ assignees: [],
},
];
+ const mockInternalQaPR = {
+ merged_by: {login: 'octocat'},
+ };
const mockGithub = jest.fn(() => ({
getOctokit: () => ({
rest: {
@@ -410,6 +399,7 @@ describe('GithubUtils', () => {
},
pulls: {
list: jest.fn().mockResolvedValue({data: mockPRs}),
+ get: jest.fn().mockResolvedValue({data: mockInternalQaPR}),
},
},
paginate: jest.fn().mockImplementation((objectMethod: () => Promise>) => objectMethod().then(({data}) => data)),
@@ -446,7 +436,7 @@ describe('GithubUtils', () => {
const internalQAHeader = '\r\n\r\n**Internal QA:**';
const lineBreak = '\r\n';
const lineBreakDouble = '\r\n\r\n';
- const assignOctocatHubot = ' - @octocat @hubot';
+ const assignOctocat = ' - @octocat';
const deployerVerificationsHeader = '\r\n**Deployer verifications:**';
// eslint-disable-next-line max-len
const timingDashboardVerification =
@@ -468,8 +458,8 @@ describe('GithubUtils', () => {
`${lineBreak}`;
test('Test no verified PRs', () => {
- githubUtils.generateStagingDeployCashBody(tag, basePRList).then((issueBody: string) => {
- expect(issueBody).toBe(
+ githubUtils.generateStagingDeployCashBodyAndAssignees(tag, basePRList).then((issue) => {
+ expect(issue.issueBody).toBe(
`${baseExpectedOutput}` +
`${openCheckbox}${basePRList[2]}` +
`${lineBreak}${openCheckbox}${basePRList[0]}` +
@@ -482,12 +472,13 @@ describe('GithubUtils', () => {
`${lineBreak}${openCheckbox}${ghVerification}` +
`${lineBreakDouble}${ccApplauseLeads}`,
);
+ expect(issue.issueAssignees).toEqual([]);
});
});
test('Test some verified PRs', () => {
- githubUtils.generateStagingDeployCashBody(tag, basePRList, [basePRList[0]]).then((issueBody: string) => {
- expect(issueBody).toBe(
+ githubUtils.generateStagingDeployCashBodyAndAssignees(tag, basePRList, [basePRList[0]]).then((issue) => {
+ expect(issue.issueBody).toBe(
`${baseExpectedOutput}` +
`${openCheckbox}${basePRList[2]}` +
`${lineBreak}${closedCheckbox}${basePRList[0]}` +
@@ -500,12 +491,13 @@ describe('GithubUtils', () => {
`${lineBreak}${openCheckbox}${ghVerification}` +
`${lineBreakDouble}${ccApplauseLeads}`,
);
+ expect(issue.issueAssignees).toEqual([]);
});
});
test('Test all verified PRs', () => {
- githubUtils.generateStagingDeployCashBody(tag, basePRList, basePRList).then((issueBody: string) => {
- expect(issueBody).toBe(
+ githubUtils.generateStagingDeployCashBodyAndAssignees(tag, basePRList, basePRList).then((issue) => {
+ expect(issue.issueBody).toBe(
`${allVerifiedExpectedOutput}` +
`${lineBreak}${deployerVerificationsHeader}` +
`${lineBreak}${openCheckbox}${timingDashboardVerification}` +
@@ -513,12 +505,13 @@ describe('GithubUtils', () => {
`${lineBreak}${openCheckbox}${ghVerification}` +
`${lineBreakDouble}${ccApplauseLeads}`,
);
+ expect(issue.issueAssignees).toEqual([]);
});
});
test('Test no resolved deploy blockers', () => {
- githubUtils.generateStagingDeployCashBody(tag, basePRList, basePRList, baseDeployBlockerList).then((issueBody: string) => {
- expect(issueBody).toBe(
+ githubUtils.generateStagingDeployCashBodyAndAssignees(tag, basePRList, basePRList, baseDeployBlockerList).then((issue) => {
+ expect(issue.issueBody).toBe(
`${allVerifiedExpectedOutput}` +
`${lineBreak}${deployBlockerHeader}` +
`${lineBreak}${openCheckbox}${baseDeployBlockerList[0]}` +
@@ -529,12 +522,13 @@ describe('GithubUtils', () => {
`${lineBreak}${openCheckbox}${ghVerification}${lineBreak}` +
`${lineBreak}${ccApplauseLeads}`,
);
+ expect(issue.issueAssignees).toEqual([]);
});
});
test('Test some resolved deploy blockers', () => {
- githubUtils.generateStagingDeployCashBody(tag, basePRList, basePRList, baseDeployBlockerList, [baseDeployBlockerList[0]]).then((issueBody: string) => {
- expect(issueBody).toBe(
+ githubUtils.generateStagingDeployCashBodyAndAssignees(tag, basePRList, basePRList, baseDeployBlockerList, [baseDeployBlockerList[0]]).then((issue) => {
+ expect(issue.issueBody).toBe(
`${allVerifiedExpectedOutput}` +
`${lineBreak}${deployBlockerHeader}` +
`${lineBreak}${closedCheckbox}${baseDeployBlockerList[0]}` +
@@ -545,12 +539,13 @@ describe('GithubUtils', () => {
`${lineBreak}${openCheckbox}${ghVerification}` +
`${lineBreakDouble}${ccApplauseLeads}`,
);
+ expect(issue.issueAssignees).toEqual([]);
});
});
test('Test all resolved deploy blockers', () => {
- githubUtils.generateStagingDeployCashBody(tag, basePRList, basePRList, baseDeployBlockerList, baseDeployBlockerList).then((issueBody: string) => {
- expect(issueBody).toBe(
+ githubUtils.generateStagingDeployCashBodyAndAssignees(tag, basePRList, basePRList, baseDeployBlockerList, baseDeployBlockerList).then((issue) => {
+ expect(issue.issueBody).toBe(
`${baseExpectedOutput}` +
`${closedCheckbox}${basePRList[2]}` +
`${lineBreak}${closedCheckbox}${basePRList[0]}` +
@@ -566,12 +561,13 @@ describe('GithubUtils', () => {
`${lineBreak}${openCheckbox}${ghVerification}` +
`${lineBreakDouble}${ccApplauseLeads}`,
);
+ expect(issue.issueAssignees).toEqual([]);
});
});
test('Test internalQA PRs', () => {
- githubUtils.generateStagingDeployCashBody(tag, [...basePRList, ...internalQAPRList]).then((issueBody: string) => {
- expect(issueBody).toBe(
+ githubUtils.generateStagingDeployCashBodyAndAssignees(tag, [...basePRList, ...internalQAPRList]).then((issue) => {
+ expect(issue.issueBody).toBe(
`${baseExpectedOutput}` +
`${openCheckbox}${basePRList[2]}` +
`${lineBreak}${openCheckbox}${basePRList[0]}` +
@@ -579,20 +575,21 @@ describe('GithubUtils', () => {
`${lineBreak}${closedCheckbox}${basePRList[4]}` +
`${lineBreak}${closedCheckbox}${basePRList[5]}` +
`${lineBreak}${internalQAHeader}` +
- `${lineBreak}${openCheckbox}${internalQAPRList[0]}${assignOctocatHubot}` +
- `${lineBreak}${openCheckbox}${internalQAPRList[1]}${assignOctocatHubot}` +
+ `${lineBreak}${openCheckbox}${internalQAPRList[0]}${assignOctocat}` +
+ `${lineBreak}${openCheckbox}${internalQAPRList[1]}${assignOctocat}` +
`${lineBreakDouble}${deployerVerificationsHeader}` +
`${lineBreak}${openCheckbox}${timingDashboardVerification}` +
`${lineBreak}${openCheckbox}${firebaseVerification}` +
`${lineBreak}${openCheckbox}${ghVerification}` +
`${lineBreakDouble}${ccApplauseLeads}`,
);
+ expect(issue.issueAssignees).toEqual(['octocat']);
});
});
test('Test some verified internalQA PRs', () => {
- githubUtils.generateStagingDeployCashBody(tag, [...basePRList, ...internalQAPRList], [], [], [], [internalQAPRList[0]]).then((issueBody: string) => {
- expect(issueBody).toBe(
+ githubUtils.generateStagingDeployCashBodyAndAssignees(tag, [...basePRList, ...internalQAPRList], [], [], [], [internalQAPRList[0]]).then((issue) => {
+ expect(issue.issueBody).toBe(
`${baseExpectedOutput}` +
`${openCheckbox}${basePRList[2]}` +
`${lineBreak}${openCheckbox}${basePRList[0]}` +
@@ -600,14 +597,15 @@ describe('GithubUtils', () => {
`${lineBreak}${closedCheckbox}${basePRList[4]}` +
`${lineBreak}${closedCheckbox}${basePRList[5]}` +
`${lineBreak}${internalQAHeader}` +
- `${lineBreak}${closedCheckbox}${internalQAPRList[0]}${assignOctocatHubot}` +
- `${lineBreak}${openCheckbox}${internalQAPRList[1]}${assignOctocatHubot}` +
+ `${lineBreak}${closedCheckbox}${internalQAPRList[0]}${assignOctocat}` +
+ `${lineBreak}${openCheckbox}${internalQAPRList[1]}${assignOctocat}` +
`${lineBreakDouble}${deployerVerificationsHeader}` +
`${lineBreak}${openCheckbox}${timingDashboardVerification}` +
`${lineBreak}${openCheckbox}${firebaseVerification}` +
`${lineBreak}${openCheckbox}${ghVerification}` +
`${lineBreakDouble}${ccApplauseLeads}`,
);
+ expect(issue.issueAssignees).toEqual(['octocat']);
});
});
});
diff --git a/tsconfig.json b/tsconfig.json
index 79413fdd2ca7..d50f97a48aa2 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -48,6 +48,6 @@
}
},
"exclude": ["**/node_modules/*", "**/dist/*", ".github/actions/**/index.js", "**/docs/*"],
- "include": ["src", "desktop", "web", "website", "docs", "assets", "config", "tests", "jest", "__mocks__", ".github/**/*", ".storybook/**/*", "workflow_tests"],
+ "include": ["src", "desktop", "web", "website", "docs", "assets", "config", "tests", "jest", "__mocks__", ".github/**/*", ".storybook/**/*", "workflow_tests", "scripts"],
"extends": "expo/tsconfig.base"
}
diff --git a/workflow_tests/createNewVersion.test.ts b/workflow_tests/createNewVersion.test.js
similarity index 93%
rename from workflow_tests/createNewVersion.test.ts
rename to workflow_tests/createNewVersion.test.js
index 05dcc2b10073..08ac63ba9948 100644
--- a/workflow_tests/createNewVersion.test.ts
+++ b/workflow_tests/createNewVersion.test.js
@@ -1,13 +1,12 @@
-import {MockGithub} from '@kie/mock-github';
-import path from 'path';
-import assertions from './assertions/createNewVersionAssertions';
-import mocks from './mocks/createNewVersionMocks';
-import ExtendedAct from './utils/ExtendedAct';
-import * as utils from './utils/utils';
+const path = require('path');
+const kieMockGithub = require('@kie/mock-github');
+const utils = require('./utils/utils');
+const assertions = require('./assertions/createNewVersionAssertions');
+const mocks = require('./mocks/createNewVersionMocks');
+const ExtendedAct = require('./utils/ExtendedAct').default;
jest.setTimeout(90 * 1000); // 90 sec
-let mockGithub: MockGithub;
-
+let mockGithub;
const FILES_TO_COPY_INTO_TEST_REPO = [
...utils.deepCopy(utils.FILES_TO_COPY_INTO_TEST_REPO),
{
@@ -17,7 +16,7 @@ const FILES_TO_COPY_INTO_TEST_REPO = [
];
describe('test workflow createNewVersion', () => {
- beforeAll(() => {
+ beforeAll(async () => {
// in case of the tests being interrupted without cleanup the mock repo directory may be left behind
// which breaks the next test run, this removes any possible leftovers
utils.removeMockRepoDir();
@@ -25,7 +24,7 @@ describe('test workflow createNewVersion', () => {
beforeEach(async () => {
// create a local repository and copy required files
- mockGithub = new MockGithub({
+ mockGithub = new kieMockGithub.MockGithub({
repo: {
testCreateNewVersionWorkflowRepo: {
files: FILES_TO_COPY_INTO_TEST_REPO,
@@ -57,7 +56,7 @@ describe('test workflow createNewVersion', () => {
describe('actor is admin', () => {
const validateActorMockSteps = mocks.CREATENEWVERSION__VALIDATEACTOR__ADMIN__STEP_MOCKS;
it('executes full workflow', async () => {
- const repoPath = mockGithub.repo.getPath('testCreateNewVersionWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testCreateNewVersionWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'createNewVersion.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, inputs);
@@ -80,7 +79,7 @@ describe('test workflow createNewVersion', () => {
describe('actor is writer', () => {
const validateActorMockSteps = mocks.CREATENEWVERSION__VALIDATEACTOR__WRITER__STEP_MOCKS;
it('executes full workflow', async () => {
- const repoPath = mockGithub.repo.getPath('testCreateNewVersionWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testCreateNewVersionWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'createNewVersion.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, inputs);
@@ -103,7 +102,7 @@ describe('test workflow createNewVersion', () => {
describe('actor is reader', () => {
const validateActorMockSteps = mocks.CREATENEWVERSION__VALIDATEACTOR__NO_PERMISSION__STEP_MOCKS;
it('stops after validation', async () => {
- const repoPath = mockGithub.repo.getPath('testCreateNewVersionWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testCreateNewVersionWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'createNewVersion.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, inputs);
@@ -125,7 +124,7 @@ describe('test workflow createNewVersion', () => {
describe('one step fails', () => {
it('announces failure on Slack', async () => {
- const repoPath = mockGithub.repo.getPath('testCreateNewVersionWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testCreateNewVersionWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'createNewVersion.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, inputs);
@@ -134,7 +133,7 @@ describe('test workflow createNewVersion', () => {
validateActor: mocks.CREATENEWVERSION__VALIDATEACTOR__ADMIN__STEP_MOCKS,
createNewVersion: utils.deepCopy(mocks.CREATENEWVERSION__CREATENEWVERSION__STEP_MOCKS),
};
- testMockSteps.createNewVersion[5] = utils.createMockStep('Commit new version', 'Commit new version', 'CREATENEWVERSION', [], [], {}, {}, false);
+ testMockSteps.createNewVersion[5] = utils.createMockStep('Commit new version', 'Commit new version', 'CREATENEWVERSION', [], [], [], [], false);
const result = await act.runEvent(event, {
workflowFile: path.join(repoPath, '.github', 'workflows', 'createNewVersion.yml'),
mockSteps: testMockSteps,
@@ -147,7 +146,7 @@ describe('test workflow createNewVersion', () => {
});
it('chooses source branch depending on the SEMVER_LEVEL', async () => {
- const repoPath = mockGithub.repo.getPath('testCreateNewVersionWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testCreateNewVersionWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'createNewVersion.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, {SEMVER_LEVEL: 'MAJOR'});
diff --git a/workflow_tests/deploy.test.ts b/workflow_tests/deploy.test.js
similarity index 93%
rename from workflow_tests/deploy.test.ts
rename to workflow_tests/deploy.test.js
index 4edb3b252d38..cf5b658d3ffb 100644
--- a/workflow_tests/deploy.test.ts
+++ b/workflow_tests/deploy.test.js
@@ -1,13 +1,12 @@
-import {MockGithub} from '@kie/mock-github';
-import path from 'path';
-import assertions from './assertions/deployAssertions';
-import mocks from './mocks/deployMocks';
-import ExtendedAct from './utils/ExtendedAct';
-import * as utils from './utils/utils';
+const path = require('path');
+const kieMockGithub = require('@kie/mock-github');
+const utils = require('./utils/utils');
+const assertions = require('./assertions/deployAssertions');
+const mocks = require('./mocks/deployMocks');
+const ExtendedAct = require('./utils/ExtendedAct').default;
jest.setTimeout(90 * 1000);
-let mockGithub: MockGithub;
-
+let mockGithub;
const FILES_TO_COPY_INTO_TEST_REPO = [
...utils.deepCopy(utils.FILES_TO_COPY_INTO_TEST_REPO),
{
@@ -17,7 +16,7 @@ const FILES_TO_COPY_INTO_TEST_REPO = [
];
describe('test workflow deploy', () => {
- beforeAll(() => {
+ beforeAll(async () => {
// in case of the tests being interrupted without cleanup the mock repo directory may be left behind
// which breaks the next test run, this removes any possible leftovers
utils.removeMockRepoDir();
@@ -25,7 +24,7 @@ describe('test workflow deploy', () => {
beforeEach(async () => {
// create a local repository and copy required files
- mockGithub = new MockGithub({
+ mockGithub = new kieMockGithub.MockGithub({
repo: {
testDeployWorkflowRepo: {
files: FILES_TO_COPY_INTO_TEST_REPO,
@@ -49,7 +48,7 @@ describe('test workflow deploy', () => {
};
describe('push', () => {
it('to main - nothing triggered', async () => {
- const repoPath = mockGithub.repo.getPath('testDeployWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testDeployWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'deploy.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(
@@ -76,7 +75,7 @@ describe('test workflow deploy', () => {
});
it('to staging - deployStaging triggered', async () => {
- const repoPath = mockGithub.repo.getPath('testDeployWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testDeployWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'deploy.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(
@@ -103,7 +102,7 @@ describe('test workflow deploy', () => {
});
it('to production - deployProduction triggered', async () => {
- const repoPath = mockGithub.repo.getPath('testDeployWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testDeployWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'deploy.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(
@@ -131,7 +130,7 @@ describe('test workflow deploy', () => {
});
it('different event than push - workflow does not execute', async () => {
- const repoPath = mockGithub.repo.getPath('testDeployWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testDeployWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'deploy.yml');
let act = new ExtendedAct(repoPath, workflowPath);
const testMockSteps = {
diff --git a/workflow_tests/deployBlocker.test.ts b/workflow_tests/deployBlocker.test.js
similarity index 92%
rename from workflow_tests/deployBlocker.test.ts
rename to workflow_tests/deployBlocker.test.js
index d6ee67f97f2c..42c4f9e741f7 100644
--- a/workflow_tests/deployBlocker.test.ts
+++ b/workflow_tests/deployBlocker.test.js
@@ -1,13 +1,12 @@
-import {MockGithub} from '@kie/mock-github';
-import path from 'path';
-import assertions from './assertions/deployBlockerAssertions';
-import mocks from './mocks/deployBlockerMocks';
-import ExtendedAct from './utils/ExtendedAct';
-import * as utils from './utils/utils';
+const path = require('path');
+const kieMockGithub = require('@kie/mock-github');
+const utils = require('./utils/utils');
+const assertions = require('./assertions/deployBlockerAssertions');
+const mocks = require('./mocks/deployBlockerMocks');
+const ExtendedAct = require('./utils/ExtendedAct').default;
jest.setTimeout(90 * 1000);
-let mockGithub: MockGithub;
-
+let mockGithub;
const FILES_TO_COPY_INTO_TEST_REPO = [
...utils.deepCopy(utils.FILES_TO_COPY_INTO_TEST_REPO),
{
@@ -24,7 +23,7 @@ describe('test workflow deployBlocker', () => {
SLACK_WEBHOOK: 'dummy_slack_webhook',
};
- beforeAll(() => {
+ beforeAll(async () => {
// in case of the tests being interrupted without cleanup the mock repo directory may be left behind
// which breaks the next test run, this removes any possible leftovers
utils.removeMockRepoDir();
@@ -32,7 +31,7 @@ describe('test workflow deployBlocker', () => {
beforeEach(async () => {
// create a local repository and copy required files
- mockGithub = new MockGithub({
+ mockGithub = new kieMockGithub.MockGithub({
repo: {
testDeployBlockerWorkflowRepo: {
files: FILES_TO_COPY_INTO_TEST_REPO,
@@ -58,7 +57,6 @@ describe('test workflow deployBlocker', () => {
issue: {
title: 'Labeled issue title',
number: '1234',
- // eslint-disable-next-line @typescript-eslint/naming-convention
html_url: 'http://issue.html.url',
},
};
@@ -66,7 +64,7 @@ describe('test workflow deployBlocker', () => {
const testEventOptions = utils.deepCopy(eventOptions);
testEventOptions.label = {name: 'DeployBlockerCash'};
it('runs the workflow and announces success on Slack', async () => {
- const repoPath = mockGithub.repo.getPath('testDeployBlockerWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testDeployBlockerWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'deployBlocker.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, testEventOptions, secrets, githubToken, {}, {});
@@ -92,7 +90,7 @@ describe('test workflow deployBlocker', () => {
});
describe('one step fails', () => {
it('announces failure on Slack', async () => {
- const repoPath = mockGithub.repo.getPath('testDeployBlockerWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testDeployBlockerWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'deployBlocker.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, testEventOptions, secrets, githubToken, {}, {});
@@ -132,7 +130,7 @@ describe('test workflow deployBlocker', () => {
const testEventOptions = utils.deepCopy(eventOptions);
testEventOptions.label = {name: 'Different Label'};
it('does not run workflow', async () => {
- const repoPath = mockGithub.repo.getPath('testDeployBlockerWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testDeployBlockerWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'deployBlocker.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, testEventOptions, secrets, githubToken, {}, {});
diff --git a/workflow_tests/failureNotifier.test.js b/workflow_tests/failureNotifier.test.ts
similarity index 68%
rename from workflow_tests/failureNotifier.test.js
rename to workflow_tests/failureNotifier.test.ts
index d521c6cde00e..8dfc092c7e61 100644
--- a/workflow_tests/failureNotifier.test.js
+++ b/workflow_tests/failureNotifier.test.ts
@@ -1,28 +1,31 @@
-const path = require('path');
-const kieMockGithub = require('@kie/mock-github');
-const assertions = require('./assertions/failureNotifierAssertions');
-const mocks = require('./mocks/failureNotifierMocks');
-const ExtendedAct = require('./utils/ExtendedAct').default;
+import type {MockStep} from '@kie/act-js/build/src/step-mocker/step-mocker.types';
+import type {CreateRepositoryFile} from '@kie/mock-github';
+import {MockGithub} from '@kie/mock-github';
+import path from 'path';
+import assertions from './assertions/failureNotifierAssertions';
+import mocks from './mocks/failureNotifierMocks';
+import ExtendedAct from './utils/ExtendedAct';
jest.setTimeout(90 * 1000);
-let mockGithub;
+let mockGithub: MockGithub;
+
const FILES_TO_COPY_INTO_TEST_REPO = [
{
src: path.resolve(__dirname, '..', '.github', 'workflows', 'failureNotifier.yml'),
dest: '.github/workflows/failureNotifier.yml',
},
-];
+] as const satisfies CreateRepositoryFile[];
describe('test workflow failureNotifier', () => {
const actor = 'Dummy Actor';
beforeEach(async () => {
// create a local repository and copy required files
- mockGithub = new kieMockGithub.MockGithub({
+ mockGithub = new MockGithub({
repo: {
testFailureNotifierWorkflowRepo: {
files: FILES_TO_COPY_INTO_TEST_REPO,
- // if any branches besides main are need add: pushedBranches: ['staging', 'production'],
+ // if any branches besides main are needed add: pushedBranches: ['staging', 'production'],
},
},
});
@@ -34,11 +37,12 @@ describe('test workflow failureNotifier', () => {
await mockGithub.teardown();
});
it('runs the notify failure when main fails', async () => {
- const repoPath = mockGithub.repo.getPath('testFailureNotifierWorkflowRepo') || '';
+ const repoPath = mockGithub.repo.getPath('testFailureNotifierWorkflowRepo') ?? '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'failureNotifier.yml');
let act = new ExtendedAct(repoPath, workflowPath);
const event = 'workflow_run';
act = act.setEvent({
+ // eslint-disable-next-line @typescript-eslint/naming-convention
workflow_run: {
name: 'Process new code merged to main',
conclusion: 'failure',
@@ -46,7 +50,8 @@ describe('test workflow failureNotifier', () => {
});
const testMockSteps = {
notifyFailure: mocks.FAILURENOTIFIER__NOTIFYFAILURE__STEP_MOCKS,
- };
+ } as const satisfies MockStep;
+
const result = await act.runEvent(event, {
workflowFile: path.join(repoPath, '.github', 'workflows', 'failureNotifier.yml'),
mockSteps: testMockSteps,
diff --git a/workflow_tests/finishReleaseCycle.test.ts b/workflow_tests/finishReleaseCycle.test.js
similarity index 94%
rename from workflow_tests/finishReleaseCycle.test.ts
rename to workflow_tests/finishReleaseCycle.test.js
index 44f9c57ab9da..20ab66471d91 100644
--- a/workflow_tests/finishReleaseCycle.test.ts
+++ b/workflow_tests/finishReleaseCycle.test.js
@@ -1,13 +1,12 @@
-import {MockGithub} from '@kie/mock-github';
-import path from 'path';
-import assertions from './assertions/finishReleaseCycleAssertions';
-import mocks from './mocks/finishReleaseCycleMocks';
-import ExtendedAct from './utils/ExtendedAct';
-import type {MockJobs} from './utils/JobMocker';
-import * as utils from './utils/utils';
+const path = require('path');
+const kieMockGithub = require('@kie/mock-github');
+const utils = require('./utils/utils');
+const assertions = require('./assertions/finishReleaseCycleAssertions');
+const mocks = require('./mocks/finishReleaseCycleMocks');
+const ExtendedAct = require('./utils/ExtendedAct').default;
jest.setTimeout(90 * 1000);
-let mockGithub: MockGithub;
+let mockGithub;
const FILES_TO_COPY_INTO_TEST_REPO = [
...utils.deepCopy(utils.FILES_TO_COPY_INTO_TEST_REPO),
{
@@ -17,7 +16,7 @@ const FILES_TO_COPY_INTO_TEST_REPO = [
];
describe('test workflow finishReleaseCycle', () => {
- beforeAll(() => {
+ beforeAll(async () => {
// in case of the tests being interrupted without cleanup the mock repo directory may be left behind
// which breaks the next test run, this removes any possible leftovers
utils.removeMockRepoDir();
@@ -25,7 +24,7 @@ describe('test workflow finishReleaseCycle', () => {
beforeEach(async () => {
// create a local repository and copy required files
- mockGithub = new MockGithub({
+ mockGithub = new kieMockGithub.MockGithub({
repo: {
testFinishReleaseCycleWorkflowRepo: {
files: FILES_TO_COPY_INTO_TEST_REPO,
@@ -51,7 +50,7 @@ describe('test workflow finishReleaseCycle', () => {
describe('actor is a team member', () => {
describe('no deploy blockers', () => {
it('production updated, new version created', async () => {
- const repoPath = mockGithub.repo.getPath('testFinishReleaseCycleWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testFinishReleaseCycleWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'finishReleaseCycle.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(
@@ -72,7 +71,7 @@ describe('test workflow finishReleaseCycle', () => {
updateProduction: mocks.FINISHRELEASECYCLE__UPDATEPRODUCTION__STEP_MOCKS,
updateStaging: mocks.FINISHRELEASECYCLE__UPDATESTAGING__STEP_MOCKS,
};
- const testMockJobs: MockJobs = {
+ const testMockJobs = {
createNewPatchVersion: {
steps: mocks.FINISHRELEASECYCLE__CREATENEWPATCHVERSION__STEP_MOCKS,
outputs: {
@@ -97,7 +96,7 @@ describe('test workflow finishReleaseCycle', () => {
});
describe('deploy blockers', () => {
it('production not updated, new version not created, issue reopened', async () => {
- const repoPath = mockGithub.repo.getPath('testFinishReleaseCycleWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testFinishReleaseCycleWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'finishReleaseCycle.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(
@@ -144,7 +143,7 @@ describe('test workflow finishReleaseCycle', () => {
});
describe('actor is not a team member', () => {
it('production not updated, new version not created, issue reopened', async () => {
- const repoPath = mockGithub.repo.getPath('testFinishReleaseCycleWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testFinishReleaseCycleWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'finishReleaseCycle.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(
@@ -191,7 +190,7 @@ describe('test workflow finishReleaseCycle', () => {
});
describe('issue does not have StagingDeployCash', () => {
it('validate job not run', async () => {
- const repoPath = mockGithub.repo.getPath('testFinishReleaseCycleWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testFinishReleaseCycleWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'finishReleaseCycle.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(
diff --git a/workflow_tests/lint.test.ts b/workflow_tests/lint.test.js
similarity index 91%
rename from workflow_tests/lint.test.ts
rename to workflow_tests/lint.test.js
index f6ede86c5fd3..b13b4c1c3564 100644
--- a/workflow_tests/lint.test.ts
+++ b/workflow_tests/lint.test.js
@@ -1,14 +1,12 @@
-import type {MockStep} from '@kie/act-js/build/src/step-mocker/step-mocker.types';
-import {MockGithub} from '@kie/mock-github';
-import path from 'path';
-import assertions from './assertions/lintAssertions';
-import mocks from './mocks/lintMocks';
-import ExtendedAct from './utils/ExtendedAct';
-import * as utils from './utils/utils';
+const path = require('path');
+const kieMockGithub = require('@kie/mock-github');
+const utils = require('./utils/utils');
+const assertions = require('./assertions/lintAssertions');
+const mocks = require('./mocks/lintMocks');
+const ExtendedAct = require('./utils/ExtendedAct').default;
jest.setTimeout(90 * 1000);
-let mockGithub: MockGithub;
-
+let mockGithub;
const FILES_TO_COPY_INTO_TEST_REPO = [
...utils.deepCopy(utils.FILES_TO_COPY_INTO_TEST_REPO),
{
@@ -21,7 +19,7 @@ describe('test workflow lint', () => {
const githubToken = 'dummy_github_token';
const actor = 'Dummy Actor';
- beforeAll(() => {
+ beforeAll(async () => {
// in case of the tests being interrupted without cleanup the mock repo directory may be left behind
// which breaks the next test run, this removes any possible leftovers
utils.removeMockRepoDir();
@@ -29,7 +27,7 @@ describe('test workflow lint', () => {
beforeEach(async () => {
// create a local repository and copy required files
- mockGithub = new MockGithub({
+ mockGithub = new kieMockGithub.MockGithub({
repo: {
testLintWorkflowRepo: {
files: FILES_TO_COPY_INTO_TEST_REPO,
@@ -49,14 +47,13 @@ describe('test workflow lint', () => {
const event = 'workflow_call';
const eventOptions = {};
it('runs the lint', async () => {
- const repoPath = mockGithub.repo.getPath('testLintWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testLintWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'lint.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, eventOptions, {}, githubToken);
- const testMockSteps: MockStep = {
+ const testMockSteps = {
lint: mocks.LINT__LINT__STEP_MOCKS,
};
-
const result = await act.runEvent(event, {
workflowFile: path.join(repoPath, '.github', 'workflows', 'lint.yml'),
mockSteps: testMockSteps,
@@ -69,14 +66,13 @@ describe('test workflow lint', () => {
describe('actor is OSBotify', () => {
const testActor = 'OSBotify';
it('runs the lint', async () => {
- const repoPath = mockGithub.repo.getPath('testLintWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testLintWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'lint.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, eventOptions, {}, githubToken);
const testMockSteps = {
lint: mocks.LINT__LINT__STEP_MOCKS,
};
-
const result = await act.runEvent(event, {
workflowFile: path.join(repoPath, '.github', 'workflows', 'lint.yml'),
mockSteps: testMockSteps,
@@ -95,14 +91,13 @@ describe('test workflow lint', () => {
action: 'opened',
};
it('runs the lint', async () => {
- const repoPath = mockGithub.repo.getPath('testLintWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testLintWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'lint.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, eventOptions, {}, githubToken);
const testMockSteps = {
lint: mocks.LINT__LINT__STEP_MOCKS,
};
-
const result = await act.runEvent(event, {
workflowFile: path.join(repoPath, '.github', 'workflows', 'lint.yml'),
mockSteps: testMockSteps,
@@ -115,14 +110,13 @@ describe('test workflow lint', () => {
describe('actor is OSBotify', () => {
const testActor = 'OSBotify';
it('does not run the lint', async () => {
- const repoPath = mockGithub.repo.getPath('testLintWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testLintWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'lint.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, eventOptions, {}, githubToken);
const testMockSteps = {
lint: mocks.LINT__LINT__STEP_MOCKS,
};
-
const result = await act.runEvent(event, {
workflowFile: path.join(repoPath, '.github', 'workflows', 'lint.yml'),
mockSteps: testMockSteps,
@@ -139,14 +133,13 @@ describe('test workflow lint', () => {
action: 'synchronize',
};
it('runs the lint', async () => {
- const repoPath = mockGithub.repo.getPath('testLintWorkflowRepo') ?? '';
+ const repoPath = mockGithub.repo.getPath('testLintWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'lint.yml');
let act = new ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(act, event, eventOptions, {}, githubToken);
const testMockSteps = {
lint: mocks.LINT__LINT__STEP_MOCKS,
};
-
const result = await act.runEvent(event, {
workflowFile: path.join(repoPath, '.github', 'workflows', 'lint.yml'),
mockSteps: testMockSteps,
diff --git a/workflow_tests/mocks/authorChecklistMocks.ts b/workflow_tests/mocks/authorChecklistMocks.ts
index b4d520eb7a1f..3a7f49783111 100644
--- a/workflow_tests/mocks/authorChecklistMocks.ts
+++ b/workflow_tests/mocks/authorChecklistMocks.ts
@@ -4,9 +4,8 @@ import {createMockStep} from '../utils/utils';
// checklist
const AUTHORCHECKLIST__CHECKLIST__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checkout', 'CHECKLIST');
const AUTHORCHECKLIST__CHECKLIST__AUTHORCHECKLIST_JS__STEP_MOCK = createMockStep('authorChecklist.js', 'Running authorChecklist.js', 'CHECKLIST', ['GITHUB_TOKEN'], []);
-const AUTHORCHECKLIST__CHECKLIST__STEP_MOCKS = [AUTHORCHECKLIST__CHECKLIST__CHECKOUT__STEP_MOCK, AUTHORCHECKLIST__CHECKLIST__AUTHORCHECKLIST_JS__STEP_MOCK] as const;
+const AUTHORCHECKLIST__CHECKLIST__STEP_MOCKS = [AUTHORCHECKLIST__CHECKLIST__CHECKOUT__STEP_MOCK, AUTHORCHECKLIST__CHECKLIST__AUTHORCHECKLIST_JS__STEP_MOCK];
-export {
- // eslint-disable-next-line import/prefer-default-export
+export default {
AUTHORCHECKLIST__CHECKLIST__STEP_MOCKS,
};
diff --git a/workflow_tests/mocks/cherryPickMocks.ts b/workflow_tests/mocks/cherryPickMocks.ts
index f1508a3dc39d..e7762731c066 100644
--- a/workflow_tests/mocks/cherryPickMocks.ts
+++ b/workflow_tests/mocks/cherryPickMocks.ts
@@ -1,4 +1,5 @@
/* eslint-disable @typescript-eslint/naming-convention */
+import type {StepIdentifier} from '@kie/act-js/build/src/step-mocker/step-mocker.types';
import {createMockStep} from '../utils/utils';
// validateactor
@@ -18,8 +19,8 @@ const CHERRYPICK__VALIDATEACTOR__CHECK_IF_USER_IS_DEPLOYER_FALSE__STEP_MOCK = cr
['GITHUB_TOKEN'],
{IS_DEPLOYER: false},
);
-const CHERRYPICK__VALIDATEACTOR__TRUE__STEP_MOCKS = [CHERRYPICK__VALIDATEACTOR__CHECK_IF_USER_IS_DEPLOYER_TRUE__STEP_MOCK] as const;
-const CHERRYPICK__VALIDATEACTOR__FALSE__STEP_MOCKS = [CHERRYPICK__VALIDATEACTOR__CHECK_IF_USER_IS_DEPLOYER_FALSE__STEP_MOCK] as const;
+const CHERRYPICK__VALIDATEACTOR__TRUE__STEP_MOCKS = [CHERRYPICK__VALIDATEACTOR__CHECK_IF_USER_IS_DEPLOYER_TRUE__STEP_MOCK];
+const CHERRYPICK__VALIDATEACTOR__FALSE__STEP_MOCKS = [CHERRYPICK__VALIDATEACTOR__CHECK_IF_USER_IS_DEPLOYER_FALSE__STEP_MOCK];
// createnewversion
const CHERRYPICK__CREATENEWVERSION__CREATE_NEW_VERSION__STEP_MOCK = createMockStep(
@@ -33,7 +34,7 @@ const CHERRYPICK__CREATENEWVERSION__CREATE_NEW_VERSION__STEP_MOCK = createMockSt
true,
'createNewVersion',
);
-const CHERRYPICK__CREATENEWVERSION__STEP_MOCKS = [CHERRYPICK__CREATENEWVERSION__CREATE_NEW_VERSION__STEP_MOCK] as const;
+const CHERRYPICK__CREATENEWVERSION__STEP_MOCKS = [CHERRYPICK__CREATENEWVERSION__CREATE_NEW_VERSION__STEP_MOCK];
// cherrypick
const CHERRYPICK__CHERRYPICK__CHECKOUT_STAGING_BRANCH__STEP_MOCK = createMockStep('Checkout staging branch', 'Checking out staging branch', 'CHERRYPICK', ['ref', 'token'], []);
@@ -93,21 +94,20 @@ const CHERRYPICK__CHERRYPICK__ANNOUNCES_A_CP_FAILURE_IN_THE_ANNOUNCE_SLACK_ROOM_
['GITHUB_TOKEN', 'SLACK_WEBHOOK_URL'],
);
-const getCherryPickMockSteps = (upToDate: boolean, hasConflicts: boolean) =>
- [
- CHERRYPICK__CHERRYPICK__CHECKOUT_STAGING_BRANCH__STEP_MOCK,
- CHERRYPICK__CHERRYPICK__SET_UP_GIT_FOR_OSBOTIFY__STEP_MOCK,
- CHERRYPICK__CHERRYPICK__GET_PREVIOUS_APP_VERSION__STEP_MOCK,
- CHERRYPICK__CHERRYPICK__FETCH_HISTORY_OF_RELEVANT_REFS__STEP_MOCK,
- CHERRYPICK__CHERRYPICK__GET_VERSION_BUMP_COMMIT__STEP_MOCK,
- CHERRYPICK__CHERRYPICK__GET_MERGE_COMMIT_FOR_PULL_REQUEST_TO_CP__STEP_MOCK,
- CHERRYPICK__CHERRYPICK__CHERRY_PICK_THE_VERSION_BUMP_TO_STAGING__STEP_MOCK,
- hasConflicts
- ? CHERRYPICK__CHERRYPICK__CHERRY_PICK_THE_MERGE_COMMIT_OF_TARGET_PR_TO_NEW_BRANCH__HAS_CONFLICTS__STEP_MOCK
- : CHERRYPICK__CHERRYPICK__CHERRY_PICK_THE_MERGE_COMMIT_OF_TARGET_PR_TO_NEW_BRANCH__HAS_NO_CONFLICTS__STEP_MOCK,
- CHERRYPICK__CHERRYPICK__PUSH_CHANGES__STEP_MOCK,
- CHERRYPICK__CHERRYPICK__CREATE_PULL_REQUEST_TO_MANUALLY_FINISH_CP__STEP_MOCK,
- CHERRYPICK__CHERRYPICK__ANNOUNCES_A_CP_FAILURE_IN_THE_ANNOUNCE_SLACK_ROOM__STEP_MOCK,
- ] as const;
+const getCherryPickMockSteps = (upToDate: boolean, hasConflicts: boolean): StepIdentifier[] => [
+ CHERRYPICK__CHERRYPICK__CHECKOUT_STAGING_BRANCH__STEP_MOCK,
+ CHERRYPICK__CHERRYPICK__SET_UP_GIT_FOR_OSBOTIFY__STEP_MOCK,
+ CHERRYPICK__CHERRYPICK__GET_PREVIOUS_APP_VERSION__STEP_MOCK,
+ CHERRYPICK__CHERRYPICK__FETCH_HISTORY_OF_RELEVANT_REFS__STEP_MOCK,
+ CHERRYPICK__CHERRYPICK__GET_VERSION_BUMP_COMMIT__STEP_MOCK,
+ CHERRYPICK__CHERRYPICK__GET_MERGE_COMMIT_FOR_PULL_REQUEST_TO_CP__STEP_MOCK,
+ CHERRYPICK__CHERRYPICK__CHERRY_PICK_THE_VERSION_BUMP_TO_STAGING__STEP_MOCK,
+ hasConflicts
+ ? CHERRYPICK__CHERRYPICK__CHERRY_PICK_THE_MERGE_COMMIT_OF_TARGET_PR_TO_NEW_BRANCH__HAS_CONFLICTS__STEP_MOCK
+ : CHERRYPICK__CHERRYPICK__CHERRY_PICK_THE_MERGE_COMMIT_OF_TARGET_PR_TO_NEW_BRANCH__HAS_NO_CONFLICTS__STEP_MOCK,
+ CHERRYPICK__CHERRYPICK__PUSH_CHANGES__STEP_MOCK,
+ CHERRYPICK__CHERRYPICK__CREATE_PULL_REQUEST_TO_MANUALLY_FINISH_CP__STEP_MOCK,
+ CHERRYPICK__CHERRYPICK__ANNOUNCES_A_CP_FAILURE_IN_THE_ANNOUNCE_SLACK_ROOM__STEP_MOCK,
+];
-export {CHERRYPICK__VALIDATEACTOR__TRUE__STEP_MOCKS, CHERRYPICK__VALIDATEACTOR__FALSE__STEP_MOCKS, CHERRYPICK__CREATENEWVERSION__STEP_MOCKS, getCherryPickMockSteps};
+export {CHERRYPICK__CREATENEWVERSION__STEP_MOCKS, CHERRYPICK__VALIDATEACTOR__FALSE__STEP_MOCKS, CHERRYPICK__VALIDATEACTOR__TRUE__STEP_MOCKS, getCherryPickMockSteps};
diff --git a/workflow_tests/mocks/claMocks.ts b/workflow_tests/mocks/claMocks.ts
index ab2d5f15a756..ca065510cd4a 100644
--- a/workflow_tests/mocks/claMocks.ts
+++ b/workflow_tests/mocks/claMocks.ts
@@ -15,8 +15,8 @@ const CLA__CLA__CLA_ASSISTANT__STEP_MOCK = createMockStep(
['path-to-signatures', 'path-to-document', 'branch', 'remote-organization-name', 'remote-repository-name', 'lock-pullrequest-aftermerge', 'allowlist'],
['GITHUB_TOKEN', 'PERSONAL_ACCESS_TOKEN'],
);
-const CLA__CLA__NO_MATCHES__STEP_MOCKS = [CLA__CLA__CLA_COMMENT_CHECK__NO_MATCH__STEP_MOCK, CLA__CLA__CLA_COMMENT_RE_CHECK__NO_MATCH__STEP_MOCK, CLA__CLA__CLA_ASSISTANT__STEP_MOCK] as const;
-const CLA__CLA__CHECK_MATCH__STEP_MOCKS = [CLA__CLA__CLA_COMMENT_CHECK__MATCH__STEP_MOCK, CLA__CLA__CLA_COMMENT_RE_CHECK__NO_MATCH__STEP_MOCK, CLA__CLA__CLA_ASSISTANT__STEP_MOCK] as const;
-const CLA__CLA__RECHECK_MATCH__STEP_MOCKS = [CLA__CLA__CLA_COMMENT_CHECK__NO_MATCH__STEP_MOCK, CLA__CLA__CLA_COMMENT_RE_CHECK__MATCH__STEP_MOCK, CLA__CLA__CLA_ASSISTANT__STEP_MOCK] as const;
+const CLA__CLA__NO_MATCHES__STEP_MOCKS = [CLA__CLA__CLA_COMMENT_CHECK__NO_MATCH__STEP_MOCK, CLA__CLA__CLA_COMMENT_RE_CHECK__NO_MATCH__STEP_MOCK, CLA__CLA__CLA_ASSISTANT__STEP_MOCK];
+const CLA__CLA__CHECK_MATCH__STEP_MOCKS = [CLA__CLA__CLA_COMMENT_CHECK__MATCH__STEP_MOCK, CLA__CLA__CLA_COMMENT_RE_CHECK__NO_MATCH__STEP_MOCK, CLA__CLA__CLA_ASSISTANT__STEP_MOCK];
+const CLA__CLA__RECHECK_MATCH__STEP_MOCKS = [CLA__CLA__CLA_COMMENT_CHECK__NO_MATCH__STEP_MOCK, CLA__CLA__CLA_COMMENT_RE_CHECK__MATCH__STEP_MOCK, CLA__CLA__CLA_ASSISTANT__STEP_MOCK];
export {CLA__CLA__NO_MATCHES__STEP_MOCKS, CLA__CLA__CHECK_MATCH__STEP_MOCKS, CLA__CLA__RECHECK_MATCH__STEP_MOCKS};
diff --git a/workflow_tests/mocks/createNewVersionMocks.ts b/workflow_tests/mocks/createNewVersionMocks.ts
index 59aa6bc910a2..d3ebdfa57734 100644
--- a/workflow_tests/mocks/createNewVersionMocks.ts
+++ b/workflow_tests/mocks/createNewVersionMocks.ts
@@ -11,9 +11,9 @@ const CREATENEWVERSION__VALIDATEACTOR__GET_USER_PERMISSIONS__WRITE__STEP_MOCK =
const CREATENEWVERSION__VALIDATEACTOR__GET_USER_PERMISSIONS__NONE__STEP_MOCK = createMockStep('Get user permissions', 'Get user permissions', 'VALIDATEACTOR', [], ['GITHUB_TOKEN'], {
PERMISSION: 'read',
});
-const CREATENEWVERSION__VALIDATEACTOR__ADMIN__STEP_MOCKS = [CREATENEWVERSION__VALIDATEACTOR__GET_USER_PERMISSIONS__ADMIN__STEP_MOCK] as const;
-const CREATENEWVERSION__VALIDATEACTOR__WRITER__STEP_MOCKS = [CREATENEWVERSION__VALIDATEACTOR__GET_USER_PERMISSIONS__WRITE__STEP_MOCK] as const;
-const CREATENEWVERSION__VALIDATEACTOR__NO_PERMISSION__STEP_MOCKS = [CREATENEWVERSION__VALIDATEACTOR__GET_USER_PERMISSIONS__NONE__STEP_MOCK] as const;
+const CREATENEWVERSION__VALIDATEACTOR__ADMIN__STEP_MOCKS = [CREATENEWVERSION__VALIDATEACTOR__GET_USER_PERMISSIONS__ADMIN__STEP_MOCK];
+const CREATENEWVERSION__VALIDATEACTOR__WRITER__STEP_MOCKS = [CREATENEWVERSION__VALIDATEACTOR__GET_USER_PERMISSIONS__WRITE__STEP_MOCK];
+const CREATENEWVERSION__VALIDATEACTOR__NO_PERMISSION__STEP_MOCKS = [CREATENEWVERSION__VALIDATEACTOR__GET_USER_PERMISSIONS__NONE__STEP_MOCK];
// createnewversion
const CREATENEWVERSION__CREATENEWVERSION__RUN_TURNSTYLE__STEP_MOCK = createMockStep('Run turnstyle', 'Run turnstyle', 'CREATENEWVERSION', ['poll-interval-seconds'], ['GITHUB_TOKEN']);
@@ -37,7 +37,7 @@ const CREATENEWVERSION__CREATENEWVERSION__STEP_MOCKS = [
CREATENEWVERSION__CREATENEWVERSION__COMMIT_NEW_VERSION__STEP_MOCK,
CREATENEWVERSION__CREATENEWVERSION__UPDATE_MAIN_BRANCH__STEP_MOCK,
CREATENEWVERSION__CREATENEWVERSION__ANNOUNCE_FAILED_WORKFLOW_IN_SLACK__STEP_MOCK,
-] as const;
+];
export {
CREATENEWVERSION__VALIDATEACTOR__ADMIN__STEP_MOCKS,
diff --git a/workflow_tests/mocks/deployBlockerMocks.ts b/workflow_tests/mocks/deployBlockerMocks.ts
index 932d4626b67b..2280950890a0 100644
--- a/workflow_tests/mocks/deployBlockerMocks.ts
+++ b/workflow_tests/mocks/deployBlockerMocks.ts
@@ -3,7 +3,7 @@ import {createMockStep} from '../utils/utils';
// updateChecklist
const DEPLOYBLOCKER__UPDATECHECKLIST__STEP_MOCK = createMockStep('updateChecklist', 'Run updateChecklist', 'UPDATECHECKLIST');
-const DEPLOYBLOCKER__UPDATECHECKLIST__STEP_MOCKS = [DEPLOYBLOCKER__UPDATECHECKLIST__STEP_MOCK] as const;
+const DEPLOYBLOCKER__UPDATECHECKLIST__STEP_MOCKS = [DEPLOYBLOCKER__UPDATECHECKLIST__STEP_MOCK];
// deployblocker
const DEPLOYBLOCKER__DEPLOYBLOCKER__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checkout', 'DEPLOYBLOCKER');
@@ -35,6 +35,6 @@ const DEPLOYBLOCKER__DEPLOYBLOCKER__STEP_MOCKS = [
DEPLOYBLOCKER__DEPLOYBLOCKER__POST_THE_ISSUE_IN_THE_EXPENSIFY_OPEN_SOURCE_SLACK_ROOM__STEP_MOCK,
DEPLOYBLOCKER__DEPLOYBLOCKER__COMMENT_ON_DEPLOY_BLOCKER__STEP_MOCK,
DEPLOYBLOCKER__DEPLOYBLOCKER__ANNOUNCE_FAILED_WORKFLOW_IN_SLACK__STEP_MOCK,
-] as const;
+];
export {DEPLOYBLOCKER__UPDATECHECKLIST__STEP_MOCKS, DEPLOYBLOCKER__DEPLOYBLOCKER__STEP_MOCKS};
diff --git a/workflow_tests/mocks/deployMocks.ts b/workflow_tests/mocks/deployMocks.ts
index d0795477cfca..5888320a87b2 100644
--- a/workflow_tests/mocks/deployMocks.ts
+++ b/workflow_tests/mocks/deployMocks.ts
@@ -9,12 +9,7 @@ const DEPLOY_STAGING__SETUP_GIT__STEP_MOCK = createMockStep('Setup git for OSBot
]);
const DEPLOY_STAGING__TAG_VERSION__STEP_MOCK = createMockStep('Tag version', 'Tagging new version', 'DEPLOY_STAGING');
const DEPLOY_STAGING__PUSH_TAG__STEP_MOCK = createMockStep('🚀 Push tags to trigger staging deploy 🚀', 'Pushing tag to trigger staging deploy', 'DEPLOY_STAGING');
-const DEPLOY_STAGING_STEP_MOCKS = [
- DEPLOY_STAGING__CHECKOUT__STEP_MOCK,
- DEPLOY_STAGING__SETUP_GIT__STEP_MOCK,
- DEPLOY_STAGING__TAG_VERSION__STEP_MOCK,
- DEPLOY_STAGING__PUSH_TAG__STEP_MOCK,
-] as const;
+const DEPLOY_STAGING_STEP_MOCKS = [DEPLOY_STAGING__CHECKOUT__STEP_MOCK, DEPLOY_STAGING__SETUP_GIT__STEP_MOCK, DEPLOY_STAGING__TAG_VERSION__STEP_MOCK, DEPLOY_STAGING__PUSH_TAG__STEP_MOCK];
const DEPLOY_PRODUCTION__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checking out', 'DEPLOY_PRODUCTION', ['ref', 'token']);
const DEPLOY_PRODUCTION__SETUP_GIT__STEP_MOCK = createMockStep(
@@ -53,6 +48,6 @@ const DEPLOY_PRODUCTION_STEP_MOCKS = [
DEPLOY_PRODUCTION__RELEASE_PR_LIST__STEP_MOCK,
DEPLOY_PRODUCTION__GENERATE_RELEASE_BODY__STEP_MOCK,
DEPLOY_PRODUCTION__CREATE_RELEASE__STEP_MOCK,
-] as const;
+];
export {DEPLOY_STAGING_STEP_MOCKS, DEPLOY_PRODUCTION_STEP_MOCKS};
diff --git a/workflow_tests/mocks/failureNotifierMocks.ts b/workflow_tests/mocks/failureNotifierMocks.ts
index 5c869adae21b..cbea6fce95ae 100644
--- a/workflow_tests/mocks/failureNotifierMocks.ts
+++ b/workflow_tests/mocks/failureNotifierMocks.ts
@@ -6,12 +6,8 @@ import {createMockStep} from '../utils/utils';
// notifyfailure
const FAILURENOTIFIER__NOTIFYFAILURE__FETCH_WORKFLOW_RUN_JOBS__STEP_MOCK = createMockStep('Fetch Workflow Run Jobs', 'Fetch Workflow Run Jobs', 'NOTIFYFAILURE', [], []);
const FAILURENOTIFIER__NOTIFYFAILURE__PROCESS_EACH_FAILED_JOB__STEP_MOCK = createMockStep('Process Each Failed Job', 'Process Each Failed Job', 'NOTIFYFAILURE', [], []);
-const FAILURENOTIFIER__NOTIFYFAILURE__STEP_MOCKS = [
- FAILURENOTIFIER__NOTIFYFAILURE__FETCH_WORKFLOW_RUN_JOBS__STEP_MOCK,
- FAILURENOTIFIER__NOTIFYFAILURE__PROCESS_EACH_FAILED_JOB__STEP_MOCK,
-] as const;
+const FAILURENOTIFIER__NOTIFYFAILURE__STEP_MOCKS = [FAILURENOTIFIER__NOTIFYFAILURE__FETCH_WORKFLOW_RUN_JOBS__STEP_MOCK, FAILURENOTIFIER__NOTIFYFAILURE__PROCESS_EACH_FAILED_JOB__STEP_MOCK];
-export {
- // eslint-disable-next-line import/prefer-default-export
+export default {
FAILURENOTIFIER__NOTIFYFAILURE__STEP_MOCKS,
};
diff --git a/workflow_tests/mocks/finishReleaseCycleMocks.ts b/workflow_tests/mocks/finishReleaseCycleMocks.ts
index 360bb017da88..86493fb077c9 100644
--- a/workflow_tests/mocks/finishReleaseCycleMocks.ts
+++ b/workflow_tests/mocks/finishReleaseCycleMocks.ts
@@ -73,7 +73,7 @@ const FINISHRELEASECYCLE__VALIDATE__TEAM_MEMBER_NO_BLOCKERS__STEP_MOCKS = [
FINISHRELEASECYCLE__VALIDATE__CHECK_FOR_ANY_DEPLOY_BLOCKERS_FALSE__STEP_MOCK,
FINISHRELEASECYCLE__VALIDATE__REOPEN_AND_COMMENT_ON_ISSUE_HAS_BLOCKERS__STEP_MOCK,
FINISHRELEASECYCLE__VALIDATE__ANNOUNCE_FAILED_WORKFLOW_IN_SLACK__STEP_MOCK,
-] as const;
+];
const FINISHRELEASECYCLE__VALIDATE__TEAM_MEMBER_BLOCKERS__STEP_MOCKS = [
FINISHRELEASECYCLE__VALIDATE__CHECKOUT__STEP_MOCK,
FINISHRELEASECYCLE__VALIDATE__SETUP_GIT_FOR_OSBOTIFY__STEP_MOCK,
@@ -82,7 +82,7 @@ const FINISHRELEASECYCLE__VALIDATE__TEAM_MEMBER_BLOCKERS__STEP_MOCKS = [
FINISHRELEASECYCLE__VALIDATE__CHECK_FOR_ANY_DEPLOY_BLOCKERS_TRUE__STEP_MOCK,
FINISHRELEASECYCLE__VALIDATE__REOPEN_AND_COMMENT_ON_ISSUE_HAS_BLOCKERS__STEP_MOCK,
FINISHRELEASECYCLE__VALIDATE__ANNOUNCE_FAILED_WORKFLOW_IN_SLACK__STEP_MOCK,
-] as const;
+];
// eslint-disable-next-line rulesdir/no-negated-variables
const FINISHRELEASECYCLE__VALIDATE__NOT_TEAM_MEMBER_NO_BLOCKERS__STEP_MOCKS = [
FINISHRELEASECYCLE__VALIDATE__CHECKOUT__STEP_MOCK,
@@ -92,7 +92,7 @@ const FINISHRELEASECYCLE__VALIDATE__NOT_TEAM_MEMBER_NO_BLOCKERS__STEP_MOCKS = [
FINISHRELEASECYCLE__VALIDATE__CHECK_FOR_ANY_DEPLOY_BLOCKERS_FALSE__STEP_MOCK,
FINISHRELEASECYCLE__VALIDATE__REOPEN_AND_COMMENT_ON_ISSUE_HAS_BLOCKERS__STEP_MOCK,
FINISHRELEASECYCLE__VALIDATE__ANNOUNCE_FAILED_WORKFLOW_IN_SLACK__STEP_MOCK,
-] as const;
+];
// eslint-disable-next-line rulesdir/no-negated-variables
const FINISHRELEASECYCLE__VALIDATE__NOT_TEAM_MEMBER_BLOCKERS__STEP_MOCKS = [
FINISHRELEASECYCLE__VALIDATE__CHECKOUT__STEP_MOCK,
@@ -102,7 +102,7 @@ const FINISHRELEASECYCLE__VALIDATE__NOT_TEAM_MEMBER_BLOCKERS__STEP_MOCKS = [
FINISHRELEASECYCLE__VALIDATE__CHECK_FOR_ANY_DEPLOY_BLOCKERS_TRUE__STEP_MOCK,
FINISHRELEASECYCLE__VALIDATE__REOPEN_AND_COMMENT_ON_ISSUE_HAS_BLOCKERS__STEP_MOCK,
FINISHRELEASECYCLE__VALIDATE__ANNOUNCE_FAILED_WORKFLOW_IN_SLACK__STEP_MOCK,
-] as const;
+];
// updateproduction
const FINISHRELEASECYCLE__UPDATEPRODUCTION__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checkout', 'UPDATEPRODUCTION', ['ref', 'token'], []);
@@ -126,7 +126,7 @@ const FINISHRELEASECYCLE__UPDATEPRODUCTION__STEP_MOCKS = [
FINISHRELEASECYCLE__UPDATEPRODUCTION__SETUP_GIT_FOR_OSBOTIFY__STEP_MOCK,
FINISHRELEASECYCLE__UPDATEPRODUCTION__UPDATE_PRODUCTION_BRANCH__STEP_MOCK,
FINISHRELEASECYCLE__UPDATEPRODUCTION__ANNOUNCE_FAILED_WORKFLOW_IN_SLACK__STEP_MOCK,
-] as const;
+];
// createnewpatchversion
const FINISHRELEASECYCLE__CREATENEWPATCHVERSION__CREATE_NEW_VERSION__STEP_MOCK = createMockStep(
@@ -140,7 +140,7 @@ const FINISHRELEASECYCLE__CREATENEWPATCHVERSION__CREATE_NEW_VERSION__STEP_MOCK =
true,
'createNewVersion',
);
-const FINISHRELEASECYCLE__CREATENEWPATCHVERSION__STEP_MOCKS = [FINISHRELEASECYCLE__CREATENEWPATCHVERSION__CREATE_NEW_VERSION__STEP_MOCK] as const;
+const FINISHRELEASECYCLE__CREATENEWPATCHVERSION__STEP_MOCKS = [FINISHRELEASECYCLE__CREATENEWPATCHVERSION__CREATE_NEW_VERSION__STEP_MOCK];
// updatestaging
const FINISHRELEASECYCLE__UPDATESTAGING__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checkout', 'UPDATESTAGING', ['ref', 'token'], []);
@@ -164,7 +164,7 @@ const FINISHRELEASECYCLE__UPDATESTAGING__STEP_MOCKS = [
FINISHRELEASECYCLE__UPDATESTAGING__SETUP_GIT_FOR_OSBOTIFY__STEP_MOCK,
FINISHRELEASECYCLE__UPDATESTAGING__UPDATE_STAGING_BRANCH_TO_TRIGGER_STAGING_DEPLOY__STEP_MOCK,
FINISHRELEASECYCLE__UPDATESTAGING__ANNOUNCE_FAILED_WORKFLOW_IN_SLACK__STEP_MOCK,
-] as const;
+];
export {
FINISHRELEASECYCLE__VALIDATE__TEAM_MEMBER_NO_BLOCKERS__STEP_MOCKS,
diff --git a/workflow_tests/mocks/lintMocks.ts b/workflow_tests/mocks/lintMocks.ts
index 93a3fd190a41..851555313cff 100644
--- a/workflow_tests/mocks/lintMocks.ts
+++ b/workflow_tests/mocks/lintMocks.ts
@@ -13,9 +13,8 @@ const LINT__LINT__STEP_MOCKS = [
LINT__LINT__LINT_JAVASCRIPT_WITH_ESLINT__STEP_MOCK,
LINT__LINT__VERIFY_NO_PRETTIER__STEP_MOCK,
LINT__LINT__RUN_UNUSED_SEARCHER__STEP_MOCK,
-] as const;
+];
-export {
- // eslint-disable-next-line import/prefer-default-export
+export default {
LINT__LINT__STEP_MOCKS,
};
diff --git a/workflow_tests/mocks/lockDeploysMocks.ts b/workflow_tests/mocks/lockDeploysMocks.ts
index 2c9aa1fd6d11..138b30fbb306 100644
--- a/workflow_tests/mocks/lockDeploysMocks.ts
+++ b/workflow_tests/mocks/lockDeploysMocks.ts
@@ -29,9 +29,8 @@ const LOCKDEPLOYS__LOCKSTAGINGDEPLOYS__STEP_MOCKS = [
LOCKDEPLOYS__LOCKSTAGINGDEPLOYS__WAIT_FOR_STAGING_DEPLOYS_TO_FINISH__STEP_MOCK,
LOCKDEPLOYS__LOCKSTAGINGDEPLOYS__COMMENT_IN_STAGINGDEPLOYCASH_TO_GIVE_APPLAUSE_THE_GREEN_LIGHT_TO_BEGIN_QA__STEP_MOCK,
LOCKDEPLOYS__LOCKSTAGINGDEPLOYS__ANNOUNCE_FAILED_WORKFLOW__STEP_MOCK,
-] as const;
+];
-export {
- // eslint-disable-next-line import/prefer-default-export
+export default {
LOCKDEPLOYS__LOCKSTAGINGDEPLOYS__STEP_MOCKS,
};
diff --git a/workflow_tests/mocks/platformDeployMocks.ts b/workflow_tests/mocks/platformDeployMocks.ts
index 72176e34d1fa..1a14f488a81d 100644
--- a/workflow_tests/mocks/platformDeployMocks.ts
+++ b/workflow_tests/mocks/platformDeployMocks.ts
@@ -18,12 +18,12 @@ const PLATFORM_DEPLOY__VALIDATE_ACTOR__CHECK_USER_DEPLOYER__OUTSIDER__STEP_MOCK
['GITHUB_TOKEN'],
{IS_DEPLOYER: false},
);
-const PLATFORM_DEPLOY__VALIDATE_ACTOR__TEAM_MEMBER__STEP_MOCKS = [PLATFORM_DEPLOY__VALIDATE_ACTOR__CHECK_USER_DEPLOYER__TEAM_MEMBER__STEP_MOCK] as const;
-const PLATFORM_DEPLOY__VALIDATE_ACTOR__OUTSIDER__STEP_MOCKS = [PLATFORM_DEPLOY__VALIDATE_ACTOR__CHECK_USER_DEPLOYER__OUTSIDER__STEP_MOCK] as const;
+const PLATFORM_DEPLOY__VALIDATE_ACTOR__TEAM_MEMBER__STEP_MOCKS = [PLATFORM_DEPLOY__VALIDATE_ACTOR__CHECK_USER_DEPLOYER__TEAM_MEMBER__STEP_MOCK];
+const PLATFORM_DEPLOY__VALIDATE_ACTOR__OUTSIDER__STEP_MOCKS = [PLATFORM_DEPLOY__VALIDATE_ACTOR__CHECK_USER_DEPLOYER__OUTSIDER__STEP_MOCK];
// deployChecklist
const PLATFORM_DEPLOY__DEPLOY_CHECKLIST__STEP_MOCK = createMockStep('deployChecklist', 'Run deployChecklist', 'DEPLOY_CHECKLIST');
-const PLATFORM_DEPLOY__DEPLOY_CHECKLIST__STEP_MOCKS = [PLATFORM_DEPLOY__DEPLOY_CHECKLIST__STEP_MOCK] as const;
+const PLATFORM_DEPLOY__DEPLOY_CHECKLIST__STEP_MOCKS = [PLATFORM_DEPLOY__DEPLOY_CHECKLIST__STEP_MOCK];
// android
const PLATFORM_DEPLOY__ANDROID__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checking out', 'ANDROID');
@@ -75,7 +75,7 @@ const PLATFORM_DEPLOY__ANDROID__STEP_MOCKS = [
PLATFORM_DEPLOY__ANDROID__UPLOAD_ANDROID_VERSION_TO_GITHUB_ARTIFACTS__STEP_MOCK,
PLATFORM_DEPLOY__ANDROID__UPLOAD_TO_BROWSER_STACK__STEP_MOCK,
PLATFORM_DEPLOY__ANDROID__WARN_DEPLOYERS__STEP_MOCK,
-] as const;
+];
// desktop
const PLATFORM_DEPLOY__DESKTOP__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checking out', 'DESKTOP');
@@ -105,7 +105,7 @@ const PLATFORM_DEPLOY__DESKTOP__STEP_MOCKS = [
PLATFORM_DEPLOY__DESKTOP__DECRYPT_ID__STEP_MOCK,
PLATFORM_DEPLOY__DESKTOP__BUILD_PRODUCTION__STEP_MOCK,
PLATFORM_DEPLOY__DESKTOP__BUILD_STAGING__STEP_MOCK,
-] as const;
+];
// ios
const PLATFORM_DEPLOY__IOS__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checking out', 'IOS');
@@ -167,7 +167,7 @@ const PLATFORM_DEPLOY__IOS__STEP_MOCKS = [
PLATFORM_DEPLOY__IOS__SET_VERSION__STEP_MOCK,
PLATFORM_DEPLOY__IOS__RELEASE_FASTLANE__STEP_MOCK,
PLATFORM_DEPLOY__IOS__WARN_FAIL__STEP_MOCK,
-] as const;
+];
// web
const PLATFORM_DEPLOY__WEB__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checking out', 'WEB');
@@ -199,13 +199,13 @@ const PLATFORM_DEPLOY__WEB__STEP_MOCKS = [
PLATFORM_DEPLOY__WEB__DEPLOY_STAGING_S3__STEP_MOCK,
PLATFORM_DEPLOY__WEB__PURGE_PRODUCTION_CACHE__STEP_MOCK,
PLATFORM_DEPLOY__WEB__PURGE_STAGING_CACHE__STEP_MOCK,
-] as const;
+];
// post slack message on failure
const PLATFORM_DEPLOY__POST_SLACK_FAIL__POST_SLACK__STEP_MOCK = createMockStep('Post Slack message on failure', 'Posting Slack message on platform deploy failure', 'POST_SLACK_FAIL', [
'SLACK_WEBHOOK',
]);
-const PLATFORM_DEPLOY__POST_SLACK_FAIL__STEP_MOCKS = [PLATFORM_DEPLOY__POST_SLACK_FAIL__POST_SLACK__STEP_MOCK] as const;
+const PLATFORM_DEPLOY__POST_SLACK_FAIL__STEP_MOCKS = [PLATFORM_DEPLOY__POST_SLACK_FAIL__POST_SLACK__STEP_MOCK];
// post slack message on success
const PLATFORM_DEPLOY__POST_SLACK_SUCCESS__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checking out', 'POST_SLACK_SUCCESS');
@@ -237,7 +237,7 @@ const PLATFORM_DEPLOY__POST_SLACK_SUCCESS__STEP_MOCKS = [
PLATFORM_DEPLOY__POST_SLACK_SUCCESS__ANNOUNCE_CHANNEL__STEP_MOCK,
PLATFORM_DEPLOY__POST_SLACK_SUCCESS__DEPLOYER_CHANNEL__STEP_MOCK,
PLATFORM_DEPLOY__POST_SLACK_SUCCESS__EXPENSIFY_CHANNEL__STEP_MOCK,
-] as const;
+];
// post github comment
const PLATFORM_DEPLOY__POST_GIHUB_COMMENT__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checking out', 'POST_GITHUB_COMMENT');
@@ -267,7 +267,7 @@ const PLATFORM_DEPLOY__POST_GITHUB_COMMENT__STEP_MOCKS = [
PLATFORM_DEPLOY__POST_GIHUB_COMMENT__SET_VERSION__STEP_MOCK,
PLATFORM_DEPLOY__POST_GIHUB_COMMENT__GET_PR_LIST__STEP_MOCK,
PLATFORM_DEPLOY__POST_GIHUB_COMMENT__COMMENT__STEP_MOCK,
-] as const;
+];
export {
PLATFORM_DEPLOY__VALIDATE_ACTOR__TEAM_MEMBER__STEP_MOCKS,
diff --git a/workflow_tests/mocks/preDeployMocks.ts b/workflow_tests/mocks/preDeployMocks.ts
index df6bc63e7dd9..d9da9d51bd85 100644
--- a/workflow_tests/mocks/preDeployMocks.ts
+++ b/workflow_tests/mocks/preDeployMocks.ts
@@ -3,15 +3,15 @@ import {createMockStep} from '../utils/utils';
// typecheck
const TYPECHECK_WORKFLOW_MOCK_STEP = createMockStep('Run typecheck workflow', 'Running typecheck workflow', 'TYPECHECK');
-const TYPECHECK_JOB_MOCK_STEPS = [TYPECHECK_WORKFLOW_MOCK_STEP] as const;
+const TYPECHECK_JOB_MOCK_STEPS = [TYPECHECK_WORKFLOW_MOCK_STEP];
// lint
const LINT_WORKFLOW_MOCK_STEP = createMockStep('Run lint workflow', 'Running lint workflow', 'LINT');
-const LINT_JOB_MOCK_STEPS = [LINT_WORKFLOW_MOCK_STEP] as const;
+const LINT_JOB_MOCK_STEPS = [LINT_WORKFLOW_MOCK_STEP];
// test
const TEST_WORKFLOW_MOCK_STEP = createMockStep('Run test workflow', 'Running test workflow', 'TEST');
-const TEST_JOB_MOCK_STEPS = [TEST_WORKFLOW_MOCK_STEP] as const;
+const TEST_JOB_MOCK_STEPS = [TEST_WORKFLOW_MOCK_STEP];
// confirm_passing_build
const ANNOUNCE_IN_SLACK_MOCK_STEP = createMockStep('Announce failed workflow in Slack', 'Announcing failed workflow in slack', 'CONFIRM_PASSING_BUILD', ['SLACK_WEBHOOK']);
@@ -19,7 +19,7 @@ const CONFIRM_PASSING_BUILD_JOB_MOCK_STEPS = [
ANNOUNCE_IN_SLACK_MOCK_STEP,
// 2nd step runs normally
-] as const;
+];
// choose_deploy_actions
const GET_MERGED_PULL_REQUEST_MOCK_STEP__CHOOSE_DEPLOY = createMockStep('Get merged pull request', 'Getting merged pull request', 'CHOOSE_DEPLOY_ACTIONS', ['github_token'], null, {
@@ -47,21 +47,21 @@ const CHOOSE_DEPLOY_ACTIONS_JOB_MOCK_STEPS__STAGING_LOCKED = [
CHECK_IF_STAGINGDEPLOYCASH_IS_LOCKED_MOCK_STEP__LOCKED,
// step 3 runs normally
-] as const;
+];
const CHOOSE_DEPLOY_ACTIONS_JOB_MOCK_STEPS__STAGING_UNLOCKED = [
GET_MERGED_PULL_REQUEST_MOCK_STEP__CHOOSE_DEPLOY,
CHECK_IF_STAGINGDEPLOYCASH_IS_LOCKED_MOCK_STEP__UNLOCKED,
// step 3 runs normally
-] as const;
+];
// skip_deploy
const COMMENT_ON_DEFERRED_PR_MOCK_STEP = createMockStep('Comment on deferred PR', 'Skipping deploy', 'SKIP_DEPLOY', ['github_token', 'number', 'body']);
-const SKIP_DEPLOY_JOB_MOCK_STEPS = [COMMENT_ON_DEFERRED_PR_MOCK_STEP] as const;
+const SKIP_DEPLOY_JOB_MOCK_STEPS = [COMMENT_ON_DEFERRED_PR_MOCK_STEP];
// create_new_version
const CREATE_NEW_VERSION_MOCK_STEP = createMockStep('Create new version', 'Creating new version', 'CREATE_NEW_VERSION', null, null, {NEW_VERSION: '1.2.3'}, null, true, 'createNewVersion');
-const CREATE_NEW_VERSION_JOB_MOCK_STEPS = [CREATE_NEW_VERSION_MOCK_STEP] as const;
+const CREATE_NEW_VERSION_JOB_MOCK_STEPS = [CREATE_NEW_VERSION_MOCK_STEP];
// update_staging
const RUN_TURNSTYLE_MOCK_STEP = createMockStep('Run turnstyle', 'Running turnstyle', 'UPDATE_STAGING', ['poll-interval-seconds'], ['GITHUB_TOKEN']);
@@ -75,10 +75,10 @@ const UPDATE_STAGING_JOB_MOCK_STEPS = [
SETUP_GIT_FOR_OSBOTIFY_MOCK_STEP,
UPDATE_STAGING_BRANCH_FROM_MAIN_MOCK_STEP,
ANNOUNCE_FAILED_WORKFLOW_IN_SLACK_MOCK_STEP,
-] as const;
+];
const PREDEPLOY__E2EPERFORMANCETESTS__PERFORM_E2E_TESTS__MOCK_STEP = createMockStep('Perform E2E tests', 'Perform E2E tests', 'E2EPERFORMANCETESTS');
-const PREDEPLOY__E2EPERFORMANCETESTS__MOCK_STEPS = [PREDEPLOY__E2EPERFORMANCETESTS__PERFORM_E2E_TESTS__MOCK_STEP] as const;
+const PREDEPLOY__E2EPERFORMANCETESTS__MOCK_STEPS = [PREDEPLOY__E2EPERFORMANCETESTS__PERFORM_E2E_TESTS__MOCK_STEP];
export {
TYPECHECK_JOB_MOCK_STEPS,
diff --git a/workflow_tests/mocks/reviewerChecklistMocks.ts b/workflow_tests/mocks/reviewerChecklistMocks.ts
index 20c87994f957..8a70c0c71597 100644
--- a/workflow_tests/mocks/reviewerChecklistMocks.ts
+++ b/workflow_tests/mocks/reviewerChecklistMocks.ts
@@ -3,9 +3,8 @@ import {createMockStep} from '../utils/utils';
// checklist
const REVIEWERCHECKLIST__CHECKLIST__REVIEWERCHECKLIST_JS__STEP_MOCK = createMockStep('reviewerChecklist.js', 'reviewerChecklist.js', 'CHECKLIST', ['GITHUB_TOKEN'], []);
-const REVIEWERCHECKLIST__CHECKLIST__STEP_MOCKS = [REVIEWERCHECKLIST__CHECKLIST__REVIEWERCHECKLIST_JS__STEP_MOCK] as const;
+const REVIEWERCHECKLIST__CHECKLIST__STEP_MOCKS = [REVIEWERCHECKLIST__CHECKLIST__REVIEWERCHECKLIST_JS__STEP_MOCK];
-export {
- // eslint-disable-next-line import/prefer-default-export
+export default {
REVIEWERCHECKLIST__CHECKLIST__STEP_MOCKS,
};
diff --git a/workflow_tests/mocks/testBuildMocks.ts b/workflow_tests/mocks/testBuildMocks.ts
index 12109d0a875b..f502bfb248ba 100644
--- a/workflow_tests/mocks/testBuildMocks.ts
+++ b/workflow_tests/mocks/testBuildMocks.ts
@@ -27,19 +27,19 @@ const TESTBUILD__VALIDATEACTOR__SET_HAS_READY_TO_BUILD_LABEL_FLAG__FALSE__STEP_M
const TESTBUILD__VALIDATEACTOR__TEAM_MEMBER_HAS_FLAG__STEP_MOCKS = [
TESTBUILD__VALIDATEACTOR__IS_TEAM_MEMBER__TRUE__STEP_MOCK,
TESTBUILD__VALIDATEACTOR__SET_HAS_READY_TO_BUILD_LABEL_FLAG__TRUE__STEP_MOCK,
-] as const;
+];
const TESTBUILD__VALIDATEACTOR__TEAM_MEMBER_NO_FLAG__STEP_MOCKS = [
TESTBUILD__VALIDATEACTOR__IS_TEAM_MEMBER__TRUE__STEP_MOCK,
TESTBUILD__VALIDATEACTOR__SET_HAS_READY_TO_BUILD_LABEL_FLAG__FALSE__STEP_MOCK,
-] as const;
+];
const TESTBUILD__VALIDATEACTOR__NO_TEAM_MEMBER_HAS_FLAG__STEP_MOCKS = [
TESTBUILD__VALIDATEACTOR__IS_TEAM_MEMBER__FALSE__STEP_MOCK,
TESTBUILD__VALIDATEACTOR__SET_HAS_READY_TO_BUILD_LABEL_FLAG__TRUE__STEP_MOCK,
-] as const;
+];
const TESTBUILD__VALIDATEACTOR__NO_TEAM_MEMBER_NO_FLAG__STEP_MOCKS = [
TESTBUILD__VALIDATEACTOR__IS_TEAM_MEMBER__FALSE__STEP_MOCK,
TESTBUILD__VALIDATEACTOR__SET_HAS_READY_TO_BUILD_LABEL_FLAG__FALSE__STEP_MOCK,
-] as const;
+];
// getbranchref
const TESTBUILD__GETBRANCHREF__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checkout', 'GETBRANCHREF', [], []);
@@ -51,7 +51,7 @@ const TESTBUILD__GETBRANCHREF__CHECK_IF_PULL_REQUEST_NUMBER_IS_CORRECT__STEP_MOC
['GITHUB_TOKEN'],
{REF: 'test-ref'},
);
-const TESTBUILD__GETBRANCHREF__STEP_MOCKS = [TESTBUILD__GETBRANCHREF__CHECKOUT__STEP_MOCK, TESTBUILD__GETBRANCHREF__CHECK_IF_PULL_REQUEST_NUMBER_IS_CORRECT__STEP_MOCK] as const;
+const TESTBUILD__GETBRANCHREF__STEP_MOCKS = [TESTBUILD__GETBRANCHREF__CHECKOUT__STEP_MOCK, TESTBUILD__GETBRANCHREF__CHECK_IF_PULL_REQUEST_NUMBER_IS_CORRECT__STEP_MOCK];
// android
const TESTBUILD__ANDROID__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checkout', 'ANDROID', ['ref'], []);
@@ -95,7 +95,7 @@ const TESTBUILD__ANDROID__STEP_MOCKS = [
TESTBUILD__ANDROID__CONFIGURE_MAPBOX_SDK__STEP_MOCK,
TESTBUILD__ANDROID__RUN_FASTLANE_BETA_TEST__STEP_MOCK,
TESTBUILD__ANDROID__UPLOAD_ARTIFACT__STEP_MOCK,
-] as const;
+];
// ios
const TESTBUILD__IOS__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checkout', 'IOS', ['ref'], []);
@@ -151,7 +151,7 @@ const TESTBUILD__IOS__STEP_MOCKS = [
TESTBUILD__IOS__CONFIGURE_AWS_CREDENTIALS__STEP_MOCK,
TESTBUILD__IOS__RUN_FASTLANE__STEP_MOCK,
TESTBUILD__IOS__UPLOAD_ARTIFACT__STEP_MOCK,
-] as const;
+];
// desktop
const TESTBUILD__DESKTOP__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checkout', 'DESKTOP', ['ref'], []);
@@ -191,7 +191,7 @@ const TESTBUILD__DESKTOP__STEP_MOCKS = [
TESTBUILD__DESKTOP__DECRYPT_DEVELOPER_ID_CERTIFICATE__STEP_MOCK,
TESTBUILD__DESKTOP__CONFIGURE_AWS_CREDENTIALS__STEP_MOCK,
TESTBUILD__DESKTOP__BUILD_DESKTOP_APP_FOR_TESTING__STEP_MOCK,
-] as const;
+];
// web
const TESTBUILD__WEB__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checkout', 'WEB', ['ref'], []);
@@ -221,7 +221,7 @@ const TESTBUILD__WEB__STEP_MOCKS = [
TESTBUILD__WEB__BUILD_WEB_FOR_TESTING__STEP_MOCK,
TESTBUILD__WEB__BUILD_DOCS__STEP_MOCK,
TESTBUILD__WEB__DEPLOY_TO_S3_FOR_INTERNAL_TESTING__STEP_MOCK,
-] as const;
+];
// postgithubcomment
const TESTBUILD__POSTGITHUBCOMMENT__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checkout', 'POSTGITHUBCOMMENT', ['ref'], []);
@@ -245,7 +245,7 @@ const TESTBUILD__POSTGITHUBCOMMENT__STEP_MOCKS = [
TESTBUILD__POSTGITHUBCOMMENT__READ_JSONS_WITH_ANDROID_PATHS__STEP_MOCK,
TESTBUILD__POSTGITHUBCOMMENT__READ_JSONS_WITH_IOS_PATHS__STEP_MOCK,
TESTBUILD__POSTGITHUBCOMMENT__PUBLISH_LINKS_TO_APPS_FOR_DOWNLOAD__STEP_MOCK,
-] as const;
+];
export {
TESTBUILD__VALIDATEACTOR__TEAM_MEMBER_HAS_FLAG__STEP_MOCKS,
diff --git a/workflow_tests/mocks/testMocks.ts b/workflow_tests/mocks/testMocks.ts
index 96f47d4204fb..cb8240169a8e 100644
--- a/workflow_tests/mocks/testMocks.ts
+++ b/workflow_tests/mocks/testMocks.ts
@@ -13,12 +13,12 @@ const TEST__JEST__STEP_MOCKS = [
TEST__JEST__GET_NUMBER_OF_CPU_CORES__STEP_MOCK,
TEST__JEST__CACHE_JEST_CACHE__STEP_MOCK,
TEST__JEST__JEST_TESTS__STEP_MOCK,
-] as const;
+];
// shelltests
const TEST__SHELLTESTS__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checkout', 'SHELLTESTS', [], []);
const TEST__SHELLTESTS__SETUP_NODE__STEP_MOCK = createMockStep('Setup Node', 'Setup Node', 'SHELLTESTS', [], []);
const TEST__SHELLTESTS__TEST_CI_GIT_LOGIC__STEP_MOCK = createMockStep('Test CI git logic', 'Test CI git logic', 'SHELLTESTS', [], []);
-const TEST__SHELLTESTS__STEP_MOCKS = [TEST__SHELLTESTS__CHECKOUT__STEP_MOCK, TEST__SHELLTESTS__SETUP_NODE__STEP_MOCK, TEST__SHELLTESTS__TEST_CI_GIT_LOGIC__STEP_MOCK] as const;
+const TEST__SHELLTESTS__STEP_MOCKS = [TEST__SHELLTESTS__CHECKOUT__STEP_MOCK, TEST__SHELLTESTS__SETUP_NODE__STEP_MOCK, TEST__SHELLTESTS__TEST_CI_GIT_LOGIC__STEP_MOCK];
export {TEST__JEST__STEP_MOCKS, TEST__SHELLTESTS__STEP_MOCKS};
diff --git a/workflow_tests/mocks/validateGithubActionsMocks.ts b/workflow_tests/mocks/validateGithubActionsMocks.ts
index 8249945dbfc7..2c1afba74387 100644
--- a/workflow_tests/mocks/validateGithubActionsMocks.ts
+++ b/workflow_tests/mocks/validateGithubActionsMocks.ts
@@ -11,9 +11,8 @@ const VALIDATEGITHUBACTIONS__VERIFY__STEP_MOCKS = [
VALIDATEGITHUBACTIONS__VERIFY__SETUP_NODE__STEP_MOCK,
VALIDATEGITHUBACTIONS__VERIFY__VERIFY_JAVASCRIPT_ACTION_BUILDS__STEP_MOCK,
VALIDATEGITHUBACTIONS__VERIFY__VALIDATE_ACTIONS_AND_WORKFLOWS__STEP_MOCK,
-] as const;
+];
-export {
- // eslint-disable-next-line import/prefer-default-export
+export default {
VALIDATEGITHUBACTIONS__VERIFY__STEP_MOCKS,
};
diff --git a/workflow_tests/mocks/verifyPodfileMocks.ts b/workflow_tests/mocks/verifyPodfileMocks.ts
index b1f0669b8b00..0cd7ea396dad 100644
--- a/workflow_tests/mocks/verifyPodfileMocks.ts
+++ b/workflow_tests/mocks/verifyPodfileMocks.ts
@@ -5,13 +5,8 @@ import {createMockStep} from '../utils/utils';
const VERIFYPODFILE__VERIFY__CHECKOUT__STEP_MOCK = createMockStep('Checkout', 'Checkout', 'VERIFY');
const VERIFYPODFILE__VERIFY__SETUP_NODE__STEP_MOCK = createMockStep('Setup Node', 'Setup Node', 'VERIFY', [], []);
const VERIFYPODFILE__VERIFY__VERIFY_PODFILE__STEP_MOCK = createMockStep('Verify podfile', 'Verify podfile', 'VERIFY', [], []);
-const VERIFYPODFILE__VERIFY__STEP_MOCKS = [
- VERIFYPODFILE__VERIFY__CHECKOUT__STEP_MOCK,
- VERIFYPODFILE__VERIFY__SETUP_NODE__STEP_MOCK,
- VERIFYPODFILE__VERIFY__VERIFY_PODFILE__STEP_MOCK,
-] as const;
+const VERIFYPODFILE__VERIFY__STEP_MOCKS = [VERIFYPODFILE__VERIFY__CHECKOUT__STEP_MOCK, VERIFYPODFILE__VERIFY__SETUP_NODE__STEP_MOCK, VERIFYPODFILE__VERIFY__VERIFY_PODFILE__STEP_MOCK];
-export {
- // eslint-disable-next-line import/prefer-default-export
+export default {
VERIFYPODFILE__VERIFY__STEP_MOCKS,
};
diff --git a/workflow_tests/mocks/verifySignedCommitsMocks.ts b/workflow_tests/mocks/verifySignedCommitsMocks.ts
index 953d09d1255f..6109af183fd7 100644
--- a/workflow_tests/mocks/verifySignedCommitsMocks.ts
+++ b/workflow_tests/mocks/verifySignedCommitsMocks.ts
@@ -9,9 +9,8 @@ const VERIFYSIGNEDCOMMITS__VERIFYSIGNEDCOMMITS__VERIFY_SIGNED_COMMITS__STEP_MOCK
['GITHUB_TOKEN'],
[],
);
-const VERIFYSIGNEDCOMMITS__VERIFYSIGNEDCOMMITS__STEP_MOCKS = [VERIFYSIGNEDCOMMITS__VERIFYSIGNEDCOMMITS__VERIFY_SIGNED_COMMITS__STEP_MOCK] as const;
+const VERIFYSIGNEDCOMMITS__VERIFYSIGNEDCOMMITS__STEP_MOCKS = [VERIFYSIGNEDCOMMITS__VERIFYSIGNEDCOMMITS__VERIFY_SIGNED_COMMITS__STEP_MOCK];
-export {
- // eslint-disable-next-line import/prefer-default-export
+export default {
VERIFYSIGNEDCOMMITS__VERIFYSIGNEDCOMMITS__STEP_MOCKS,
};
diff --git a/workflow_tests/utils/JobMocker.ts b/workflow_tests/utils/JobMocker.ts
index 171d625b2fe1..b6dc99771dd2 100644
--- a/workflow_tests/utils/JobMocker.ts
+++ b/workflow_tests/utils/JobMocker.ts
@@ -1,4 +1,3 @@
-import type {StepIdentifier} from '@kie/act-js';
import type {PathOrFileDescriptor} from 'fs';
import fs from 'fs';
import path from 'path';
@@ -12,12 +11,12 @@ type YamlWorkflow = {
};
type MockJob = {
- steps: StepIdentifier[];
+ steps: MockJobStep[];
uses?: string;
secrets?: string[];
with?: string;
- outputs?: Record;
- runsOn: string;
+ outputs?: string[];
+ runsOn?: string;
};
type MockJobs = Record;
@@ -60,8 +59,8 @@ class JobMocker {
jobWith = job.with;
delete job.with;
}
- job.steps = mockJob.steps.map((step): StepIdentifier => {
- const mockStep: StepIdentifier = {
+ job.steps = mockJob.steps.map((step) => {
+ const mockStep: MockJobStep = {
name: step.name,
run: step.mockWith,
};
diff --git a/workflow_tests/utils/preGenerateTest.ts b/workflow_tests/utils/preGenerateTest.ts
index c5e54d9a11c0..7698e618432d 100644
--- a/workflow_tests/utils/preGenerateTest.ts
+++ b/workflow_tests/utils/preGenerateTest.ts
@@ -1,11 +1,10 @@
/* eslint no-console: ["error", { allow: ["warn", "log"] }] */
-import type {StepIdentifier} from '@kie/act-js';
import type {PathLike} from 'fs';
import fs from 'fs';
import path from 'path';
import {exit} from 'process';
import yaml from 'yaml';
-import type {YamlMockJob, YamlWorkflow} from './JobMocker';
+import type {MockJobStep, YamlMockJob, YamlWorkflow} from './JobMocker';
const workflowsDirectory = path.resolve(__dirname, '..', '..', '.github', 'workflows');
const workflowTestsDirectory = path.resolve(__dirname, '..');
@@ -98,7 +97,7 @@ describe('test workflow ${workflowName}', () => {
});
`;
-const mockStepTemplate = (stepMockName: string, step: StepIdentifier, jobId: string | undefined) => `
+const mockStepTemplate = (stepMockName: string, step: MockJobStep, jobId: string | undefined) => `
const ${stepMockName} = utils.createMockStep(
'${step.name ?? ''}',
'${step.name ?? ''}',
diff --git a/workflow_tests/utils/utils.ts b/workflow_tests/utils/utils.ts
index 2b4036c8b826..df4cc0468963 100644
--- a/workflow_tests/utils/utils.ts
+++ b/workflow_tests/utils/utils.ts
@@ -1,10 +1,13 @@
-import type {StepIdentifier} from '@kie/act-js';
-import type {EventJSON} from '@kie/act-js/build/src/action-event/action-event.types';
+import type {StepIdentifier} from '@kie/act-js/build/src/step-mocker/step-mocker.types';
import fs from 'fs';
import path from 'path';
import yaml from 'yaml';
import type ExtendedAct from './ExtendedAct';
+type EventOptions = {
+ action?: string;
+};
+
type StepAssertionInputEntry = {key: string; value: string};
type StepAssertion = {
@@ -16,7 +19,7 @@ type StepAssertion = {
function setUpActParams(
act: ExtendedAct,
event: string | null = null,
- eventOptions: EventJSON | null = null,
+ eventOptions: EventOptions | null = null,
secrets: Record | null = null,
githubToken: string | null = null,
envVars: Record | null = null,