Skip to content

Commit b945f4d

Browse files
authored
Merge branch 'main' into fixresetNonUSDBankAccount
2 parents ce7c718 + e7245a3 commit b945f4d

1,261 files changed

Lines changed: 80250 additions & 23307 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ help/_scripts/**
1717
modules/ExpensifyNitroUtils/nitrogen/**
1818
Mobile-Expensify/**
1919
vendor
20+
modules/group-ib-fp/**

.eslintrc.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const restrictedImportPaths = [
1414
'Text',
1515
'ScrollView',
1616
'Animated',
17+
'findNodeHandle',
1718
],
1819
message: [
1920
'',
@@ -105,6 +106,10 @@ const restrictedImportPaths = [
105106
importNames: ['useOnyx'],
106107
message: "Please use '@hooks/useOnyx' instead.",
107108
},
109+
{
110+
name: '@src/utils/findNodeHandle',
111+
message: "Do not use 'findNodeHandle' as it is no longer supported on web.",
112+
},
108113
];
109114

110115
const restrictedImportPatterns = [
@@ -237,6 +242,7 @@ module.exports = {
237242
'react-native-a11y/has-accessibility-hint': ['off'],
238243
'react/require-default-props': 'off',
239244
'react/prop-types': 'off',
245+
'react/jsx-key': 'error',
240246
'react/jsx-no-constructed-context-values': 'error',
241247
'react-native-a11y/has-valid-accessibility-descriptors': [
242248
'error',

.github/actions/javascript/authorChecklist/index.js

Lines changed: 123 additions & 39 deletions
Large diffs are not rendered by default.

.github/actions/javascript/awaitStagingDeploys/index.js

Lines changed: 109 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12270,15 +12270,27 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
1227012270
}) : function(o, v) {
1227112271
o["default"] = v;
1227212272
});
12273-
var __importStar = (this && this.__importStar) || function (mod) {
12274-
if (mod && mod.__esModule) return mod;
12275-
var result = {};
12276-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
12277-
__setModuleDefault(result, mod);
12278-
return result;
12279-
};
12273+
var __importStar = (this && this.__importStar) || (function () {
12274+
var ownKeys = function(o) {
12275+
ownKeys = Object.getOwnPropertyNames || function (o) {
12276+
var ar = [];
12277+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
12278+
return ar;
12279+
};
12280+
return ownKeys(o);
12281+
};
12282+
return function (mod) {
12283+
if (mod && mod.__esModule) return mod;
12284+
var result = {};
12285+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
12286+
__setModuleDefault(result, mod);
12287+
return result;
12288+
};
12289+
})();
1228012290
Object.defineProperty(exports, "__esModule", ({ value: true }));
12281-
exports.convertToNumber = exports.getStringInput = exports.getJSONInput = void 0;
12291+
exports.getJSONInput = getJSONInput;
12292+
exports.getStringInput = getStringInput;
12293+
exports.convertToNumber = convertToNumber;
1228212294
const core = __importStar(__nccwpck_require__(2186));
1228312295
/**
1228412296
* Safely parse a JSON input to a GitHub Action.
@@ -12295,7 +12307,6 @@ function getJSONInput(name, options, defaultValue) {
1229512307
}
1229612308
return defaultValue;
1229712309
}
12298-
exports.getJSONInput = getJSONInput;
1229912310
/**
1230012311
* Safely access a string input to a GitHub Action, or fall back on a default if the string is empty.
1230112312
*/
@@ -12306,7 +12317,6 @@ function getStringInput(name, options, defaultValue) {
1230612317
}
1230712318
return input;
1230812319
}
12309-
exports.getStringInput = getStringInput;
1231012320
/**
1231112321
* Converts a value to a number, returning 0 for non-numeric values.
1231212322
*/
@@ -12323,7 +12333,6 @@ function convertToNumber(value) {
1232312333
return 0;
1232412334
}
1232512335
}
12326-
exports.convertToNumber = convertToNumber;
1232712336

1232812337

1232912338
/***/ }),
@@ -12347,6 +12356,7 @@ const CONST = {
1234712356
LABELS: {
1234812357
STAGING_DEPLOY: 'StagingDeployCash',
1234912358
DEPLOY_BLOCKER: 'DeployBlockerCash',
12359+
LOCK_DEPLOY: '🔐 LockCashDeploys 🔐',
1235012360
INTERNAL_QA: 'InternalQA',
1235112361
HELP_WANTED: 'Help Wanted',
1235212362
CP_STAGING: 'CP Staging',
@@ -12365,6 +12375,21 @@ const CONST = {
1236512375
EVENTS: {
1236612376
ISSUE_COMMENT: 'issue_comment',
1236712377
},
12378+
RUN_EVENT: {
12379+
PULL_REQUEST: 'pull_request',
12380+
PULL_REQUEST_TARGET: 'pull_request_target',
12381+
PUSH: 'push',
12382+
},
12383+
RUN_STATUS: {
12384+
COMPLETED: 'completed',
12385+
IN_PROGRESS: 'in_progress',
12386+
QUEUED: 'queued',
12387+
},
12388+
RUN_STATUS_CONCLUSION: {
12389+
SUCCESS: 'success',
12390+
},
12391+
TEST_WORKFLOW_NAME: 'Jest Unit Tests',
12392+
TEST_WORKFLOW_PATH: '.github/workflows/test.yml',
1236812393
PROPOSAL_KEYWORD: 'Proposal',
1236912394
DATE_FORMAT_STRING: 'yyyy-MM-dd',
1237012395
PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`),
@@ -12373,6 +12398,7 @@ const CONST = {
1237312398
POLL_RATE: 10000,
1237412399
APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`,
1237512400
APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`,
12401+
MOBILE_EXPENSIFY_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.MOBILE_EXPENSIFY_REPO}`,
1237612402
NO_ACTION: 'NO_ACTION',
1237712403
ACTION_EDIT: 'ACTION_EDIT',
1237812404
ACTION_REQUIRED: 'ACTION_REQUIRED',
@@ -12404,13 +12430,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
1240412430
}) : function(o, v) {
1240512431
o["default"] = v;
1240612432
});
12407-
var __importStar = (this && this.__importStar) || function (mod) {
12408-
if (mod && mod.__esModule) return mod;
12409-
var result = {};
12410-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
12411-
__setModuleDefault(result, mod);
12412-
return result;
12413-
};
12433+
var __importStar = (this && this.__importStar) || (function () {
12434+
var ownKeys = function(o) {
12435+
ownKeys = Object.getOwnPropertyNames || function (o) {
12436+
var ar = [];
12437+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
12438+
return ar;
12439+
};
12440+
return ownKeys(o);
12441+
};
12442+
return function (mod) {
12443+
if (mod && mod.__esModule) return mod;
12444+
var result = {};
12445+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
12446+
__setModuleDefault(result, mod);
12447+
return result;
12448+
};
12449+
})();
1241412450
var __importDefault = (this && this.__importDefault) || function (mod) {
1241512451
return (mod && mod.__esModule) ? mod : { "default": mod };
1241612452
};
@@ -12540,6 +12576,7 @@ class GithubUtils {
1254012576
number: this.getIssueOrPullRequestNumberFromURL(issue.url),
1254112577
labels: issue.labels,
1254212578
PRList: this.getStagingDeployCashPRList(issue),
12579+
PRListMobileExpensify: this.getStagingDeployCashPRListMobileExpensify(issue),
1254312580
deployBlockers: this.getStagingDeployCashDeployBlockers(issue),
1254412581
internalQAPRList: this.getStagingDeployCashInternalQA(issue),
1254512582
isFirebaseChecked: issue.body ? /-\s\[x]\sI checked \[Firebase Crashlytics]/.test(issue.body) : false,
@@ -12572,6 +12609,19 @@ class GithubUtils {
1257212609
}));
1257312610
return PRList.sort((a, b) => a.number - b.number);
1257412611
}
12612+
static getStagingDeployCashPRListMobileExpensify(issue) {
12613+
let mobileExpensifySection = issue.body?.match(/Mobile-Expensify PRs:\*\*\r?\n((?:-.*\r?\n)+)/) ?? null;
12614+
if (mobileExpensifySection?.length !== 2) {
12615+
return [];
12616+
}
12617+
mobileExpensifySection = mobileExpensifySection[1];
12618+
const mobileExpensifyPRs = [...mobileExpensifySection.matchAll(new RegExp(`- \\[([ x])]\\s(${CONST_1.default.ISSUE_OR_PULL_REQUEST_REGEX.source})`, 'g'))].map((match) => ({
12619+
url: match[2],
12620+
number: Number.parseInt(match[3], 10),
12621+
isVerified: match[1] === 'x',
12622+
}));
12623+
return mobileExpensifyPRs.sort((a, b) => a.number - b.number);
12624+
}
1257512625
/**
1257612626
* Parse DeployBlocker section of the StagingDeployCash issue body.
1257712627
*
@@ -12611,7 +12661,7 @@ class GithubUtils {
1261112661
/**
1261212662
* Generate the issue body and assignees for a StagingDeployCash.
1261312663
*/
12614-
static generateStagingDeployCashBodyAndAssignees(tag, PRList, verifiedPRList = [], deployBlockers = [], resolvedDeployBlockers = [], resolvedInternalQAPRs = [], isFirebaseChecked = false, isGHStatusChecked = false) {
12664+
static generateStagingDeployCashBodyAndAssignees(tag, PRList, PRListMobileExpensify, verifiedPRList = [], verifiedPRListMobileExpensify = [], deployBlockers = [], resolvedDeployBlockers = [], resolvedInternalQAPRs = [], isFirebaseChecked = false, isGHStatusChecked = false) {
1261512665
return this.fetchAllPullRequests(PRList.map((pr) => this.getPullRequestNumberFromURL(pr)))
1261612666
.then((data) => {
1261712667
const internalQAPRs = Array.isArray(data) ? data.filter((pr) => !(0, isEmptyObject_1.isEmptyObject)(pr.labels.find((item) => item.name === CONST_1.default.LABELS.INTERNAL_QA))) : [];
@@ -12628,24 +12678,36 @@ class GithubUtils {
1262812678
console.log('Found the following Internal QA PRs:', internalQAPRMap);
1262912679
const noQAPRs = Array.isArray(data) ? data.filter((PR) => /\[No\s?QA]/i.test(PR.title)).map((item) => item.html_url) : [];
1263012680
console.log('Found the following NO QA PRs:', noQAPRs);
12631-
const verifiedOrNoQAPRs = [...new Set([...verifiedPRList, ...noQAPRs])];
12681+
const verifiedOrNoQAPRs = [...new Set([...verifiedPRList, ...verifiedPRListMobileExpensify, ...noQAPRs])];
1263212682
const sortedPRList = [...new Set((0, arrayDifference_1.default)(PRList, Object.keys(internalQAPRMap)))].sort((a, b) => GithubUtils.getPullRequestNumberFromURL(a) - GithubUtils.getPullRequestNumberFromURL(b));
12683+
const sortedPRListMobileExpensify = [...new Set(PRListMobileExpensify)].sort((a, b) => GithubUtils.getPullRequestNumberFromURL(a) - GithubUtils.getPullRequestNumberFromURL(b));
1263312684
const sortedDeployBlockers = [...new Set(deployBlockers)].sort((a, b) => GithubUtils.getIssueOrPullRequestNumberFromURL(a) - GithubUtils.getIssueOrPullRequestNumberFromURL(b));
1263412685
// Tag version and comparison URL
1263512686
// eslint-disable-next-line max-len
12636-
let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/${process.env.GITHUB_REPOSITORY}/compare/production...staging\r\n\r\n`;
12637-
// Warn deployers about potential bugs with the new process
12638-
issueBody +=
12639-
'> 💡 **Deployer FYI:** This checklist was generated using a new process. PR list from original method and detail logging can be found in the most recent [deploy workflow](https://github.com/Expensify/App/actions/workflows/deploy.yml) labeled `staging`, in the `createChecklist` action. Please tag @Julesssss with any issues.\r\n\r\n';
12687+
let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/${process.env.GITHUB_REPOSITORY}/compare/production...staging\r\n`;
12688+
// Add Mobile-Expensify compare link if there are Mobile-Expensify PRs
12689+
if (sortedPRListMobileExpensify.length > 0) {
12690+
issueBody += `**Mobile-Expensify Changes:** https://github.com/${CONST_1.default.GITHUB_OWNER}/${CONST_1.default.MOBILE_EXPENSIFY_REPO}/compare/production...staging\r\n`;
12691+
}
12692+
issueBody += '\r\n';
1264012693
// PR list
1264112694
if (sortedPRList.length > 0) {
12642-
issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n';
12695+
issueBody += '**This release contains changes from the following pull requests:**\r\n';
1264312696
sortedPRList.forEach((URL) => {
1264412697
issueBody += verifiedOrNoQAPRs.includes(URL) ? '- [x]' : '- [ ]';
1264512698
issueBody += ` ${URL}\r\n`;
1264612699
});
1264712700
issueBody += '\r\n\r\n';
1264812701
}
12702+
// Mobile-Expensify PR list
12703+
if (sortedPRListMobileExpensify.length > 0) {
12704+
issueBody += '**Mobile-Expensify PRs:**\r\n';
12705+
sortedPRListMobileExpensify.forEach((URL) => {
12706+
issueBody += verifiedOrNoQAPRs.includes(URL) ? '- [x]' : '- [ ]';
12707+
issueBody += ` ${URL}\r\n`;
12708+
});
12709+
issueBody += '\r\n\r\n';
12710+
}
1264912711
// Internal QA PR list
1265012712
if (!(0, isEmptyObject_1.isEmptyObject)(internalQAPRMap)) {
1265112713
console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs);
@@ -12703,7 +12765,7 @@ class GithubUtils {
1270312765
}
1270412766
return data;
1270512767
})
12706-
.then((prList) => prList.filter((pr) => pullRequestNumbers.includes(pr.number)))
12768+
.then((prList) => prList?.filter((pr) => pullRequestNumbers.includes(pr.number)) ?? [])
1270712769
.catch((err) => console.error('Failed to get PR list', err));
1270812770
}
1270912771
static getPullRequestMergerLogin(pullRequestNumber) {
@@ -12774,11 +12836,22 @@ class GithubUtils {
1277412836
})
1277512837
.then((response) => response.data.workflow_runs.at(0)?.id ?? -1);
1277612838
}
12839+
/**
12840+
* List workflow runs for the repository.
12841+
*/
12842+
static async listWorkflowRunsForRepo(options = {}) {
12843+
return this.octokit.actions.listWorkflowRunsForRepo({
12844+
owner: CONST_1.default.GITHUB_OWNER,
12845+
repo: CONST_1.default.APP_REPO,
12846+
per_page: options.per_page ?? 50,
12847+
...(options.status && { status: options.status }),
12848+
});
12849+
}
1277712850
/**
1277812851
* Generate the URL of an New Expensify pull request given the PR number.
1277912852
*/
12780-
static getPullRequestURLFromNumber(value) {
12781-
return `${CONST_1.default.APP_REPO_URL}/pull/${value}`;
12853+
static getPullRequestURLFromNumber(value, repositoryURL) {
12854+
return `${repositoryURL}/pull/${value}`;
1278212855
}
1278312856
/**
1278412857
* Parse the pull request number from a URL.
@@ -12876,7 +12949,7 @@ class GithubUtils {
1287612949
/**
1287712950
* Get commits between two tags via the GitHub API
1287812951
*/
12879-
static async getCommitHistoryBetweenTags(fromTag, toTag) {
12952+
static async getCommitHistoryBetweenTags(fromTag, toTag, repositoryName) {
1288012953
console.log('Getting pull requests merged between the following tags:', fromTag, toTag);
1288112954
core.startGroup('Fetching paginated commits:');
1288212955
try {
@@ -12888,7 +12961,7 @@ class GithubUtils {
1288812961
core.info(`📄 Fetching page ${page} of commits...`);
1288912962
const response = await this.octokit.repos.compareCommits({
1289012963
owner: CONST_1.default.GITHUB_OWNER,
12891-
repo: CONST_1.default.APP_REPO,
12964+
repo: repositoryName,
1289212965
base: fromTag,
1289312966
head: toTag,
1289412967
per_page: perPage,
@@ -12917,6 +12990,7 @@ class GithubUtils {
1291712990
}
1291812991
core.info(`🎉 Successfully fetched ${allCommits.length} total commits`);
1291912992
core.endGroup();
12993+
console.log('');
1292012994
return allCommits.map((commit) => ({
1292112995
commit: commit.sha,
1292212996
subject: commit.commit.message,
@@ -12925,9 +12999,10 @@ class GithubUtils {
1292512999
}
1292613000
catch (error) {
1292713001
if (error instanceof request_error_1.RequestError && error.status === 404) {
12928-
console.error(`❓❓ Failed to get commits with the GitHub API. The base tag ('${fromTag}') or head tag ('${toTag}') likely doesn't exist on the remote repository. If this is the case, create or push them.`);
13002+
core.error(`❓❓ Failed to get commits with the GitHub API. The base tag ('${fromTag}') or head tag ('${toTag}') likely doesn't exist on the remote repository. If this is the case, create or push them.`);
1292913003
}
1293013004
core.endGroup();
13005+
console.log('');
1293113006
throw error;
1293213007
}
1293313008
}
@@ -12961,11 +13036,10 @@ exports["default"] = arrayDifference;
1296113036
"use strict";
1296213037

1296313038
Object.defineProperty(exports, "__esModule", ({ value: true }));
12964-
exports.isEmptyObject = void 0;
13039+
exports.isEmptyObject = isEmptyObject;
1296513040
function isEmptyObject(obj) {
1296613041
return Object.keys(obj ?? {}).length === 0;
1296713042
}
12968-
exports.isEmptyObject = isEmptyObject;
1296913043

1297013044

1297113045
/***/ }),
@@ -12976,7 +13050,8 @@ exports.isEmptyObject = isEmptyObject;
1297613050
"use strict";
1297713051

1297813052
Object.defineProperty(exports, "__esModule", ({ value: true }));
12979-
exports.promiseDoWhile = exports.promiseWhile = void 0;
13053+
exports.promiseWhile = promiseWhile;
13054+
exports.promiseDoWhile = promiseDoWhile;
1298013055
/**
1298113056
* Simulates a while loop where the condition is determined by the result of a Promise.
1298213057
*/
@@ -13003,7 +13078,6 @@ function promiseWhile(condition, action) {
1300313078
loop();
1300413079
});
1300513080
}
13006-
exports.promiseWhile = promiseWhile;
1300713081
/**
1300813082
* Simulates a do-while loop where the condition is determined by the result of a Promise.
1300913083
*/
@@ -13020,7 +13094,6 @@ function promiseDoWhile(condition, action) {
1302013094
.catch(reject);
1302113095
});
1302213096
}
13023-
exports.promiseDoWhile = promiseDoWhile;
1302413097

1302513098

1302613099
/***/ }),

0 commit comments

Comments
 (0)