Skip to content

Commit

Permalink
Merge branch 'Expensify:main' into fix/33797
Browse files Browse the repository at this point in the history
  • Loading branch information
Tony-MK authored Feb 11, 2024
2 parents bcbd4e6 + 06c7dac commit 62e03ba
Show file tree
Hide file tree
Showing 687 changed files with 16,917 additions and 10,459 deletions.
16 changes: 5 additions & 11 deletions .github/actions/composite/buildAndroidE2EAPK/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,15 @@ runs:
- name: Append environment variables to env file
shell: bash
run: |
echo "EXPENSIFY_PARTNER_NAME=${EXPENSIFY_PARTNER_NAME}" >> ${{ inputs.PATH_ENV_FILE }}
echo "EXPENSIFY_PARTNER_PASSWORD=${EXPENSIFY_PARTNER_PASSWORD}" >> ${{ inputs.PATH_ENV_FILE }}
echo "EXPENSIFY_PARTNER_USER_ID=${EXPENSIFY_PARTNER_USER_ID}" >> ${{ inputs.PATH_ENV_FILE }}
echo "EXPENSIFY_PARTNER_USER_SECRET=${EXPENSIFY_PARTNER_USER_SECRET}" >> ${{ inputs.PATH_ENV_FILE }}
echo "EXPENSIFY_PARTNER_PASSWORD_EMAIL=${EXPENSIFY_PARTNER_PASSWORD_EMAIL}" >> ${{ inputs.PATH_ENV_FILE }}
echo "EXPENSIFY_PARTNER_NAME=${{ inputs.EXPENSIFY_PARTNER_NAME }}" >> ${{ inputs.PATH_ENV_FILE }}
echo "EXPENSIFY_PARTNER_PASSWORD=${{ inputs.EXPENSIFY_PARTNER_PASSWORD }}" >> ${{ inputs.PATH_ENV_FILE }}
echo "EXPENSIFY_PARTNER_USER_ID=${{ inputs.EXPENSIFY_PARTNER_USER_ID }}" >> ${{ inputs.PATH_ENV_FILE }}
echo "EXPENSIFY_PARTNER_USER_SECRET=${{ inputs.EXPENSIFY_PARTNER_USER_SECRET }}" >> ${{ inputs.PATH_ENV_FILE }}
echo "EXPENSIFY_PARTNER_PASSWORD_EMAIL=${{ inputs.EXPENSIFY_PARTNER_PASSWORD_EMAIL }}" >> ${{ inputs.PATH_ENV_FILE }}
- name: Build APK
run: npm run ${{ inputs.PACKAGE_SCRIPT_NAME }}
shell: bash
env:
EXPENSIFY_PARTNER_NAME: ${{ inputs.EXPENSIFY_PARTNER_NAME }}
EXPENSIFY_PARTNER_PASSWORD: ${{ inputs.EXPENSIFY_PARTNER_PASSWORD }}
EXPENSIFY_PARTNER_USER_ID: ${{ inputs.EXPENSIFY_PARTNER_USER_ID }}
EXPENSIFY_PARTNER_USER_SECRET: ${{ inputs.EXPENSIFY_PARTNER_USER_SECRET }}
EXPENSIFY_PARTNER_PASSWORD_EMAIL: ${{ inputs.EXPENSIFY_PARTNER_PASSWORD_EMAIL }}

- name: Upload APK
uses: actions/upload-artifact@65d862660abb392b8c4a3d1195a2108db131dd05
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/createHelpRedirects.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function checkCloudflareResult {

if ! [[ "$RESULT_MESSAGE" == "true" ]]; then
ERROR_MESSAGE=$(echo "$RESULTS" | jq .errors)
error "Error calling Cloudfalre API: $ERROR_MESSAGE"
error "Error calling Cloudflare API: $ERROR_MESSAGE"
exit 1
fi
}
Expand Down
52 changes: 46 additions & 6 deletions .github/workflows/e2ePerformanceTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
git fetch origin tag ${{ steps.getMostRecentRelease.outputs.VERSION }} --no-tags --depth=1
git switch --detach ${{ steps.getMostRecentRelease.outputs.VERSION }}
- uses: ./.github/actions/composite/buildAndroidE2EAPK
- uses: Expensify/App/.github/actions/composite/buildAndroidE2EAPK@main
with:
ARTIFACT_NAME: baseline-apk-${{ steps.getMostRecentRelease.outputs.VERSION }}
PACKAGE_SCRIPT_NAME: android-build-e2e
Expand Down Expand Up @@ -114,7 +114,7 @@ jobs:
- name: Checkout "delta ref"
run: git checkout ${{ steps.getDeltaRef.outputs.DELTA_REF }}

- uses: ./.github/actions/composite/buildAndroidE2EAPK
- uses: Expensify/App/.github/actions/composite/buildAndroidE2EAPK@main
with:
ARTIFACT_NAME: delta-apk-${{ steps.getDeltaRef.outputs.DELTA_REF }}
PACKAGE_SCRIPT_NAME: android-build-e2edelta
Expand Down Expand Up @@ -200,26 +200,66 @@ jobs:
if: failure()
run: |
echo ${{ steps.schedule-awsdf-main.outputs.data }}
cat "./mainResults/Host_Machine_Files/\$WORKING_DIRECTORY/Test spec output.txt"
unzip "Customer Artifacts.zip" -d mainResults
cat ./mainResults/Host_Machine_Files/\$WORKING_DIRECTORY/debug.log
cat "./mainResults/Host_Machine_Files/\$WORKING_DIRECTORY/logcat.txt" || true
cat ./mainResults/Host_Machine_Files/\$WORKING_DIRECTORY/debug.log || true
cat "./mainResults/Host_Machine_Files/\$WORKING_DIRECTORY/Test spec output.txt" || true
- name: Announce failed workflow in Slack
if: failure()
uses: 8398a7/action-slack@v3
with:
status: custom
custom_payload: |
{
channel: '#expensify-margelo',
attachments: [{
color: 'danger',
text: `💥 ${process.env.AS_REPO} E2E Test run failed failed on <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.workflow }}> workflow 💥`,
}]
}
env:
GITHUB_TOKEN: ${{ github.token }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

- name: Unzip AWS Device Farm results
if: ${{ always() }}
if: always()
run: unzip "Customer Artifacts.zip"

- name: Print AWS Device Farm run results
if: ${{ always() }}
if: always()
run: cat "./Host_Machine_Files/\$WORKING_DIRECTORY/output.md"

- name: Check if test failed, if so post the results and add the DeployBlocker label
id: checkIfRegressionDetected
run: |
if grep -q '🔴' ./output.md; then
# Create an output to the GH action that the test failed:
echo "performanceRegressionDetected=true" >> "$GITHUB_OUTPUT"
gh pr edit ${{ inputs.PR_NUMBER }} --add-label DeployBlockerCash
gh pr comment ${{ inputs.PR_NUMBER }} -F ./output.md
gh pr comment ${{ inputs.PR_NUMBER }} -b "@Expensify/mobile-deployers 📣 Please look into this performance regression as it's a deploy blocker."
else
echo "performanceRegressionDetected=false" >> "$GITHUB_OUTPUT"
echo '✅ no performance regression detected'
fi
env:
GITHUB_TOKEN: ${{ github.token }}

- name: 'Announce regression in Slack'
if: ${{ steps.checkIfRegressionDetected.outputs.performanceRegressionDetected == 'true' }}
uses: 8398a7/action-slack@v3
with:
status: custom
custom_payload: |
{
channel: '#newdot-performance',
attachments: [{
color: 'danger',
text: `🔴 Performance regression detected in PR ${{ inputs.PR_NUMBER }}\nDetected in <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.workflow }}> workflow.`,
}]
}
env:
GITHUB_TOKEN: ${{ github.token }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
96 changes: 96 additions & 0 deletions .github/workflows/failureNotifier.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: Notify on Workflow Failure

on:
workflow_run:
workflows: ["Process new code merged to main"]
types:
- completed

permissions:
issues: write

jobs:
notifyFailure:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
steps:
- name: Fetch Workflow Run Jobs
id: fetch-workflow-jobs
uses: actions/github-script@v7
with:
script: |
const runId = "${{ github.event.workflow_run.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 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;
const prMerger = "${{ github.event.workflow_run.actor.login }}";
const failureLabel = 'Workflow Failure';
for (let i = 0; i < jobs.total_count; i++) {
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 annotations = await github.rest.checks.listAnnotations({
owner: context.repo.owner,
repo: context.repo.repo,
check_run_id: jobs.jobs[i].id,
});
let errorMessage = "";
for(let j = 0; j < annotations.data.length; j++) {
errorMessage += annotations.data[j].annotation_level + ": ";
errorMessage += annotations.data[j].message + "\n";
}
const issueTitle = `Investigate workflow job failing on main: ${ jobName }`;
const issueBody = `🚨 **Failure Summary** 🚨:\n\n` +
`- **📋 Job Name**: [${ jobName }](${ jobLink })\n` +
`- **🔧 Failure in Workflow**: Process new code merged to main\n` +
`- **🔗 Triggered by PR**: [PR Link](${ prLink })\n` +
`- **👤 PR Author**: @${ prAuthor }\n` +
`- **🤝 Merged by**: @${ prMerger }\n` +
`- **🐛 Error Message**: \n ${errorMessage}\n\n` +
`⚠️ **Action Required** ⚠️:\n\n` +
`🛠️ A recent merge appears to have caused a failure in the job named [${ jobName }](${ jobLink }).\n` +
`This issue has been automatically created and labeled with \`${ failureLabel }\` for investigation. \n\n` +
`👀 **Please look into the following**:\n` +
`1. **Why the PR caused the job to fail?**\n` +
`2. **Address any underlying issues.**\n\n` +
`🐛 We appreciate your help in squashing this bug!`;
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: issueTitle,
body: issueBody,
labels: [failureLabel, 'Daily'],
assignees: [prMerger]
});
}
}
}
1 change: 1 addition & 0 deletions .github/workflows/preDeploy.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Reminder: If this workflow's name changes, update the name in the dependent workflow at .github/workflows/failureNotifier.yml.
name: Process new code merged to main

on:
Expand Down
2 changes: 1 addition & 1 deletion .storybook/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module.exports = ({config}) => {
config.resolve.alias = {
'react-native-config': 'react-web-config',
'react-native$': 'react-native-web',
'@react-native-community/netinfo': path.resolve(__dirname, '../__mocks__/@react-native-community/netinfo.js'),
'@react-native-community/netinfo': path.resolve(__dirname, '../__mocks__/@react-native-community/netinfo.ts'),
'@react-navigation/native': path.resolve(__dirname, '../__mocks__/@react-navigation/native'),

// Module alias support for storybook files, coping from `webpack.common.js`
Expand Down
19 changes: 0 additions & 19 deletions __mocks__/@react-native-community/netinfo.js

This file was deleted.

31 changes: 31 additions & 0 deletions __mocks__/@react-native-community/netinfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {NetInfoCellularGeneration, NetInfoStateType} from '@react-native-community/netinfo';
import type {addEventListener, configure, fetch, NetInfoState, refresh, useNetInfo} from '@react-native-community/netinfo';

const defaultState: NetInfoState = {
type: NetInfoStateType.cellular,
isConnected: true,
isInternetReachable: true,
details: {
isConnectionExpensive: true,
cellularGeneration: NetInfoCellularGeneration['3g'],
carrier: 'T-Mobile',
},
};

type NetInfoMock = {
configure: typeof configure;
fetch: typeof fetch;
refresh: typeof refresh;
addEventListener: typeof addEventListener;
useNetInfo: typeof useNetInfo;
};

const netInfoMock: NetInfoMock = {
configure: () => {},
fetch: () => Promise.resolve(defaultState),
refresh: () => Promise.resolve(defaultState),
addEventListener: () => () => {},
useNetInfo: () => defaultState,
};

export default netInfoMock;
5 changes: 0 additions & 5 deletions __mocks__/@react-native-community/push-notification-ios.js

This file was deleted.

7 changes: 0 additions & 7 deletions __mocks__/@react-native-firebase/crashlytics.js

This file was deleted.

15 changes: 15 additions & 0 deletions __mocks__/@react-native-firebase/crashlytics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type {FirebaseCrashlyticsTypes} from '@react-native-firebase/crashlytics';

type CrashlyticsModule = Pick<FirebaseCrashlyticsTypes.Module, 'log' | 'recordError' | 'setCrashlyticsCollectionEnabled'>;

type CrashlyticsMock = () => CrashlyticsModule;

// <App> uses <ErrorBoundary> and we need to mock the imported crashlytics module
// due to an error that happens otherwise https://github.com/invertase/react-native-firebase/issues/2475
const crashlyticsMock: CrashlyticsMock = () => ({
log: jest.fn(),
recordError: jest.fn(),
setCrashlyticsCollectionEnabled: jest.fn(),
});

export default crashlyticsMock;
5 changes: 5 additions & 0 deletions __mocks__/@react-native-firebase/perf.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type PerfMock = () => void;

const perfMock: PerfMock = () => {};

export default perfMock;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {useIsFocused as realUseIsFocused} from '@react-navigation/native';

// We only want this mocked for storybook, not jest
const useIsFocused = process.env.NODE_ENV === 'test' ? realUseIsFocused : () => true;
const useIsFocused: typeof realUseIsFocused = process.env.NODE_ENV === 'test' ? realUseIsFocused : () => true;

export * from '@react-navigation/core';
export * from '@react-navigation/native';
Expand Down
5 changes: 0 additions & 5 deletions __mocks__/push-notification-ios.js

This file was deleted.

6 changes: 0 additions & 6 deletions __mocks__/react-freeze.js

This file was deleted.

8 changes: 8 additions & 0 deletions __mocks__/react-freeze.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type {Freeze as FreezeComponent} from 'react-freeze';

const Freeze: typeof FreezeComponent = (props) => props.children as JSX.Element;

export {
// eslint-disable-next-line import/prefer-default-export
Freeze,
};
1 change: 0 additions & 1 deletion __mocks__/react-native-blob-util.js

This file was deleted.

5 changes: 5 additions & 0 deletions __mocks__/react-native-blob-util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type RNFetchBlob from 'react-native-blob-util';

const ReactNativeBlobUtilMock: Partial<typeof RNFetchBlob> = {};

export default ReactNativeBlobUtilMock;
3 changes: 0 additions & 3 deletions __mocks__/react-native-dev-menu.js

This file was deleted.

11 changes: 11 additions & 0 deletions __mocks__/react-native-dev-menu.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type {addItem} from 'react-native-dev-menu';

type ReactNativeDevMenuMock = {
addItem: typeof addItem;
};

const reactNativeDevMenuMock: ReactNativeDevMenuMock = {
addItem: jest.fn(),
};

export default reactNativeDevMenuMock;
3 changes: 0 additions & 3 deletions __mocks__/react-native-device-info.js

This file was deleted.

6 changes: 6 additions & 0 deletions __mocks__/react-native-device-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type DeviceInfoModule from 'react-native-device-info';
import MockDeviceInfo from 'react-native-device-info/jest/react-native-device-info-mock';

const DeviceInfo: typeof DeviceInfoModule = MockDeviceInfo;

export default DeviceInfo;
3 changes: 0 additions & 3 deletions __mocks__/react-native-localize.js

This file was deleted.

3 changes: 3 additions & 0 deletions __mocks__/react-native-localize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import mockRNLocalize from 'react-native-localize/mock';

module.exports = mockRNLocalize;
Loading

0 comments on commit 62e03ba

Please sign in to comment.