Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
srikarparsi committed May 3, 2024
2 parents 2990a7d + a6299a1 commit 9899133
Show file tree
Hide file tree
Showing 665 changed files with 19,681 additions and 11,403 deletions.
31 changes: 23 additions & 8 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const restrictedImportPatterns = [

module.exports = {
extends: ['expensify', 'plugin:storybook/recommended', 'plugin:react-native-a11y/basic', 'plugin:@dword-design/import-alias/recommended', 'prettier'],
plugins: ['react-native-a11y'],
plugins: ['react-native-a11y', 'testing-library'],
parser: 'babel-eslint',
ignorePatterns: ['!.*', 'src/vendor', '.github/actions/**/index.js', 'desktop/dist/*.js', 'dist/*.js', 'node_modules/.bin/**', 'node_modules/.cache/**', '.git/**'],
env: {
Expand Down Expand Up @@ -122,13 +122,28 @@ module.exports = {
},
},
],
'rulesdir/avoid-anonymous-functions': 'off',
},
},
// This helps disable the `prefer-alias` rule to be enabled for specific directories
{
files: ['tests/**/*.js', 'tests/**/*.ts', 'tests/**/*.jsx', 'assets/**/*.js', '.storybook/**/*.js'],
rules: {'@dword-design/import-alias/prefer-alias': ['off']},
},
{
files: ['tests/**/*.js', 'tests/**/*.ts', 'tests/**/*.jsx', 'tests/**/*.tsx'],
extends: ['plugin:testing-library/react'],
rules: {
'testing-library/await-async-queries': 'error',
'testing-library/await-async-utils': 'error',
'testing-library/no-debugging-utils': 'error',
'testing-library/no-manual-cleanup': 'error',
'testing-library/no-unnecessary-act': 'error',
'testing-library/prefer-find-by': 'error',
'testing-library/prefer-presence-queries': 'error',
'testing-library/prefer-screen-queries': 'error',
},
},
{
files: ['*.js', '*.jsx'],
settings: {
Expand Down Expand Up @@ -260,13 +275,7 @@ module.exports = {
'no-restricted-imports': [
'error',
{
paths: [
...restrictedImportPaths,
{
name: 'underscore',
message: 'Please use the corresponding method from lodash instead',
},
],
paths: restrictedImportPaths,
patterns: restrictedImportPatterns,
},
],
Expand All @@ -282,5 +291,11 @@ module.exports = {
'no-restricted-syntax': ['error', 'ForInStatement', 'LabeledStatement', 'WithStatement'],
},
},
{
files: ['en.ts', 'es.ts'],
rules: {
'rulesdir/use-periods-for-error-messages': 'error',
},
},
],
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {promiseDoWhile} from '@github/libs/promiseWhile';
type CurrentStagingDeploys = Awaited<ReturnType<typeof GitHubUtils.octokit.actions.listWorkflowRuns>>['data']['workflow_runs'];

function run() {
console.info('[awaitStagingDeploys] POLL RATE', CONST.POLL_RATE);
console.info('[awaitStagingDeploys] run()');
console.info('[awaitStagingDeploys] getStringInput', getStringInput);
console.info('[awaitStagingDeploys] GitHubUtils', GitHubUtils);
Expand Down
8 changes: 7 additions & 1 deletion .github/actions/javascript/awaitStagingDeploys/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12131,6 +12131,7 @@ const CONST_1 = __importDefault(__nccwpck_require__(9873));
const GithubUtils_1 = __importDefault(__nccwpck_require__(9296));
const promiseWhile_1 = __nccwpck_require__(9438);
function run() {
console.info('[awaitStagingDeploys] POLL RATE', CONST_1.default.POLL_RATE);
console.info('[awaitStagingDeploys] run()');
console.info('[awaitStagingDeploys] getStringInput', ActionUtils_1.getStringInput);
console.info('[awaitStagingDeploys] GitHubUtils', GithubUtils_1.default);
Expand Down Expand Up @@ -12742,7 +12743,12 @@ function promiseWhile(condition, action) {
resolve();
return;
}
Promise.resolve(actionResult).then(loop).catch(reject);
Promise.resolve(actionResult)
.then(() => {
// Set a timeout to delay the next loop iteration
setTimeout(loop, 1000); // 1000 ms delay
})
.catch(reject);
}
};
loop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const run = () => {

// Initialize string to store Graphite metrics
let graphiteString = '';
let timestamp: number;

// Iterate over each entry
regressionEntries.forEach((entry) => {
Expand All @@ -26,7 +27,9 @@ const run = () => {
const current = JSON.parse(entry);

// Extract timestamp, Graphite accepts timestamp in seconds
const timestamp = current.metadata?.creationDate ? Math.floor(new Date(current.metadata.creationDate).getTime() / 1000) : '';
if (current.metadata?.creationDate) {
timestamp = Math.floor(new Date(current.metadata.creationDate).getTime() / 1000);
}

if (current.name && current.meanDuration && current.meanCount && timestamp) {
const formattedName = current.name.split(' ').join('-');
Expand Down
5 changes: 4 additions & 1 deletion .github/actions/javascript/getGraphiteString/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2735,6 +2735,7 @@ const run = () => {
const regressionEntries = regressionFile.split('\n');
// Initialize string to store Graphite metrics
let graphiteString = '';
let timestamp;
// Iterate over each entry
regressionEntries.forEach((entry) => {
// Skip empty lines
Expand All @@ -2744,7 +2745,9 @@ const run = () => {
try {
const current = JSON.parse(entry);
// Extract timestamp, Graphite accepts timestamp in seconds
const timestamp = current.metadata?.creationDate ? Math.floor(new Date(current.metadata.creationDate).getTime() / 1000) : '';
if (current.metadata?.creationDate) {
timestamp = Math.floor(new Date(current.metadata.creationDate).getTime() / 1000);
}
if (current.name && current.meanDuration && current.meanCount && timestamp) {
const formattedName = current.name.split(' ').join('-');
const renderDurationString = `${GRAPHITE_PATH}.${formattedName}.renderDuration ${current.meanDuration} ${timestamp}`;
Expand Down
7 changes: 6 additions & 1 deletion .github/libs/promiseWhile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ function promiseWhile(condition: () => boolean, action: (() => Promise<void>) |
return;
}

Promise.resolve(actionResult).then(loop).catch(reject);
Promise.resolve(actionResult)
.then(() => {
// Set a timeout to delay the next loop iteration
setTimeout(loop, 1000); // 1000 ms delay
})
.catch(reject);
}
};
loop();
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/deployExpensifyHelp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ concurrency:

jobs:
build:
env:
IS_PR_FROM_FORK: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork }}
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand All @@ -49,24 +51,26 @@ jobs:
- name: Deploy to Cloudflare Pages
uses: cloudflare/pages-action@f0a1cd58cd66095dee69bfa18fa5efd1dde93bca
id: deploy
if: github.event_name != 'pull_request' || (github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork)
if: env.IS_PR_FROM_FORK != 'true'
with:
apiToken: ${{ secrets.CLOUDFLARE_PAGES_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: helpdot
directory: ./docs/_site

- name: Setup Cloudflare CLI
if: env.IS_PR_FROM_FORK != 'true'
run: pip3 install cloudflare==2.19.0

- name: Purge Cloudflare cache
if: env.IS_PR_FROM_FORK != 'true'
run: /home/runner/.local/bin/cli4 --verbose --delete hosts=["help.expensify.com"] /zones/:9ee042e6cfc7fd45e74aa7d2f78d617b/purge_cache
env:
CF_API_KEY: ${{ secrets.CLOUDFLARE_TOKEN }}

- name: Leave a comment on the PR
uses: actions-cool/maintain-one-comment@de04bd2a3750d86b324829a3ff34d47e48e16f4b
if: ${{ github.event_name == 'pull_request' }}
if: ${{ github.event_name == 'pull_request' && env.IS_PR_FROM_FORK != 'true' }}
with:
token: ${{ secrets.OS_BOTIFY_TOKEN }}
body: ${{ format('A preview of your ExpensifyHelp changes have been deployed to {0} ⚡️', steps.deploy.outputs.alias) }}
Expand Down
44 changes: 34 additions & 10 deletions .github/workflows/failureNotifier.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,49 @@ jobs:
});
return jobsData.data;
- name: Fetch Previous Workflow Run
id: previous-workflow-run
uses: actions/github-script@v7
with:
script: |
const runId = ${{ github.event.workflow_run.id }};
const allRuns = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'preDeploy.yml',
});
const filteredRuns = allRuns.data.workflow_runs.filter(run => run.actor.login !== 'OSBotify' && run.status !== 'cancelled');
const currentIndex = filteredRuns.findIndex(run => run.id === runId);
const previousRun = filteredRuns[currentIndex + 1];
return previousRun;
- name: Fetch Previous Workflow Run Jobs
id: previous-workflow-jobs
uses: actions/github-script@v7
with:
script: |
const previousRun = ${{ steps.previous-workflow-run.outputs.result }};
const runId = previousRun.id;
const jobsData = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: runId,
});
return jobsData.data;
- name: Process Each Failed Job
uses: actions/github-script@v7
with:
script: |
const jobs = ${{ steps.fetch-workflow-jobs.outputs.result }};
const previousRun = ${{ steps.previous-workflow-run.outputs.result }};
const previousRunJobs = ${{ steps.previous-workflow-jobs.outputs.result }};
const headCommit = "${{ github.event.workflow_run.head_commit.id }}";
const prData = await github.rest.repos.listPullRequestsAssociatedWithCommit({
owner: context.repo.owner,
repo: context.repo.repo,
commit_sha: headCommit,
});
const pr = prData.data[0];
const prLink = pr.html_url;
const prAuthor = pr.user.login;
Expand All @@ -50,14 +80,8 @@ jobs:
if (jobs.jobs[i].conclusion == 'failure') {
const jobName = jobs.jobs[i].name;
const jobLink = jobs.jobs[i].html_url;
const issues = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
labels: failureLabel,
state: 'open'
});
const existingIssue = issues.data.find(issue => issue.title.includes(jobName));
if (!existingIssue) {
const previousJob = previousRunJobs.jobs.find(job => job.name === jobName);
if (previousJob?.conclusion === 'success') {
const annotations = await github.rest.checks.listAnnotations({
owner: context.repo.owner,
repo: context.repo.repo,
Expand Down
11 changes: 5 additions & 6 deletions .github/workflows/platformDeploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,11 @@ jobs:
MYAPP_UPLOAD_STORE_PASSWORD: ${{ secrets.MYAPP_UPLOAD_STORE_PASSWORD }}
MYAPP_UPLOAD_KEY_PASSWORD: ${{ secrets.MYAPP_UPLOAD_KEY_PASSWORD }}

# Note: Android production deploys are temporarily disabled until https://github.com/Expensify/App/issues/40108 is resolved
# - name: Run Fastlane production
# if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }}
# run: bundle exec fastlane android production
# env:
# VERSION: ${{ env.VERSION_CODE }}
- name: Run Fastlane production
if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }}
run: bundle exec fastlane android production
env:
VERSION: ${{ env.VERSION_CODE }}

- name: Archive Android sourcemaps
uses: actions/upload-artifact@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/typecheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
# - git diff is used to see the files that were added on this branch
# - gh pr view is used to list files touched by this PR. Git diff may give false positives if the branch isn't up-to-date with main
# - wc counts the words in the result of the intersection
count_new_js=$(comm -1 -2 <(git diff --name-only --diff-filter=A origin/main HEAD -- 'src/*.js' '__mocks__/*.js' '.storybook/*.js' 'assets/*.js' 'config/*.js' 'desktop/*.js' 'jest/*.js' 'scripts/*.js' 'tests/*.js' 'web/*.js' 'workflow_tests/*.js' '.github/libs/*.js' '.github/scripts/*.js') <(gh pr view ${{ github.event.pull_request.number }} --json files | jq -r '.files | map(.path) | .[]') | wc -l)
count_new_js=$(comm -1 -2 <(git diff --name-only --diff-filter=A origin/main HEAD -- 'src/*.js' '__mocks__/*.js' '.storybook/*.js' 'assets/*.js' 'config/*.js' 'desktop/*.js' 'jest/*.js' 'scripts/*.js' 'tests/*.js' 'workflow_tests/*.js' '.github/libs/*.js' '.github/scripts/*.js') <(gh pr view ${{ github.event.pull_request.number }} --json files | jq -r '.files | map(.path) | .[]') | wc -l)
if [ "$count_new_js" -gt "0" ]; then
echo "ERROR: Found new JavaScript files in the project; use TypeScript instead."
exit 1
Expand Down
8 changes: 8 additions & 0 deletions .well-known/apple-app-site-association
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
"/": "/split/*",
"comment": "Split Expense"
},
{
"/": "/submit/*",
"comment": "Submit Expense"
},
{
"/": "/request/*",
"comment": "Submit Expense"
Expand All @@ -76,6 +80,10 @@
"/": "/search/*",
"comment": "Search"
},
{
"/": "/pay/*",
"comment": "Pay someone"
},
{
"/": "/send/*",
"comment": "Pay someone"
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#### Table of Contents
* [Local Development](#local-development)
* [Testing on browsers on simulators and emulators](#testing-on-browsers-on-simulators-and-emulators)
* [Testing on browsers in simulators and emulators](#testing-on-browsers-in-simulators-and-emulators)
* [Running The Tests](#running-the-tests)
* [Debugging](#debugging)
* [App Structure and Conventions](#app-structure-and-conventions)
Expand Down Expand Up @@ -60,6 +60,7 @@ If you're using another operating system, you will need to ensure `mkcert` is in
For an M1 Mac, read this [SO](https://stackoverflow.com/questions/64901180/how-to-run-cocoapods-on-apple-silicon-m1) for installing cocoapods.

* If you haven't already, install Xcode tools and make sure to install the optional "iOS Platform" package as well. This installation may take awhile.
* After installation, check in System Settings that there's no update for Xcode. Otherwise, you may encounter issues later that don't explain that you solve them by updating Xcode.
* Install project gems, including cocoapods, using bundler to ensure everyone uses the same versions. In the project root, run: `bundle install`
* If you get the error `Could not find 'bundler'`, install the bundler gem first: `gem install bundler` and try again.
* If you are using MacOS and get the error `Gem::FilePermissionError` when trying to install the bundler gem, you're likely using system Ruby, which requires administrator permission to modify. To get around this, install another version of Ruby with a version manager like [rbenv](https://github.com/rbenv/rbenv#installation).
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001046313
versionName "1.4.63-13"
versionCode 1001047001
versionName "1.4.70-1"
// Supported language variants must be declared here to avoid from being removed during the compilation.
// This also helps us to not include unnecessary language variants in the APK.
resConfigs "en", "es"
Expand Down
4 changes: 4 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/bank-account"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/iou"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/request"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/submit"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/enable-payments"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/statements"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/concierge"/>
Expand All @@ -70,6 +71,7 @@
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/new"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/search"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/send"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/pay"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/money2020"/>

<!-- Staging URLs -->
Expand All @@ -81,6 +83,7 @@
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/bank-account"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/iou"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/request"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/submit"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/enable-payments"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/statements"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/concierge"/>
Expand All @@ -89,6 +92,7 @@
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/new"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/search"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/send"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/pay"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/money2020"/>
</intent-filter>
</activity>
Expand Down
Loading

0 comments on commit 9899133

Please sign in to comment.