Skip to content

Commit 0b8785c

Browse files
committed
Merge branch 'main' into fix/84022
2 parents 04d009e + 20f2fef commit 0b8785c

1,630 files changed

Lines changed: 63492 additions & 28061 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.

.claude/skills/coding-standards/SKILL.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ Coding standards for the Expensify App. Each standard is a standalone file in `r
1313
| Category | Prefix | Focus |
1414
|----------|--------|-------|
1515
| Performance | `PERF-*` | Render optimization, memo patterns, useEffect hygiene, data selection |
16-
| Consistency | `CONSISTENCY-*` | Platform checks, magic values, unused props, ESLint discipline |
17-
| Clean React Patterns | `CLEAN-REACT-PATTERNS-*` | Composition, component ownership, state structure |
16+
| Consistency | `CONSISTENCY-*` | Platform checks, magic values, unused props, ESLint discipline, localization, file naming, JSDoc |
17+
| Clean React Patterns | `CLEAN-REACT-PATTERNS-*` | Composition, component ownership, state structure, prop typing, function components |
18+
| UI | `UI-*` | Loading indicators, scrollable pages, styling conventions |
1819

1920
## Quick Reference
2021

@@ -42,6 +43,11 @@ Coding standards for the Expensify App. Each standard is a standalone file in `r
4243
- [CONSISTENCY-4](rules/consistency-4-no-unused-props.md) — No unused props
4344
- [CONSISTENCY-5](rules/consistency-5-justify-eslint-disable.md) — Justify ESLint disables
4445
- [CONSISTENCY-6](rules/consistency-6-proper-error-handling.md) — Proper error handling
46+
- [CONSISTENCY-7](rules/consistency-7-localize-copy.md) — Localize all user-visible copy
47+
- [CONSISTENCY-8](rules/consistency-8-localize-numbers-dates.md) — Localize numbers, amounts, dates and phone numbers
48+
- [CONSISTENCY-9](rules/consistency-9-file-naming.md) — Name files after what they export
49+
- [CONSISTENCY-10](rules/consistency-10-jsdoc.md) — Follow the JSDoc style guidelines
50+
- [CONSISTENCY-11](rules/consistency-11-no-todo-comments.md) — Track future work in an issue, not a TODO comment
4551

4652
### Clean React Patterns
4753
- [CLEAN-REACT-PATTERNS-0](rules/clean-react-0-compiler.md) — React Compiler compliance
@@ -50,6 +56,15 @@ Coding standards for the Expensify App. Each standard is a standalone file in `r
5056
- [CLEAN-REACT-PATTERNS-3](rules/clean-react-3-context-free-contracts.md) — Context-free component contracts
5157
- [CLEAN-REACT-PATTERNS-4](rules/clean-react-4-no-side-effect-spaghetti.md) — No side-effect spaghetti
5258
- [CLEAN-REACT-PATTERNS-5](rules/clean-react-5-narrow-state.md) — Keep state narrow
59+
- [CLEAN-REACT-PATTERNS-6](rules/clean-react-6-no-componentprops.md) — Import the exported prop type instead of ComponentProps
60+
- [CLEAN-REACT-PATTERNS-7](rules/clean-react-7-no-inline-prop-types.md) — Do not inline prop types on exported components
61+
- [CLEAN-REACT-PATTERNS-8](rules/clean-react-8-no-class-components.md) — Use function components, not class components
62+
- [CLEAN-REACT-PATTERNS-9](rules/clean-react-9-no-proptypes.md) — Use TypeScript types, not propTypes or defaultProps
63+
64+
### UI
65+
- [UI-1](rules/ui-1-correct-loading-indicator.md) — Use the correct loading indicator based on navigation context
66+
- [UI-2](rules/ui-2-new-page-scrollview.md) — New pages must be scrollable
67+
- [UI-3](rules/ui-3-no-inline-styles.md) — Do not use inline style objects
5368

5469
## Usage
5570

.claude/skills/coding-standards/rules/clean-react-6-no-componentprops.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
2-
ruleId: CLEAN-REACT-6
2+
ruleId: CLEAN-REACT-PATTERNS-6
33
title: Import the exported prop type instead of ComponentProps
44
---
55

6-
## [CLEAN-REACT-6] Import the exported prop type instead of ComponentProps
6+
## [CLEAN-REACT-PATTERNS-6] Import the exported prop type instead of ComponentProps
77

88
### Reasoning
99

.claude/skills/coding-standards/rules/clean-react-7-no-inline-prop-types.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
2-
ruleId: CLEAN-REACT-7
2+
ruleId: CLEAN-REACT-PATTERNS-7
33
title: Do not inline prop types on exported components
44
---
55

6-
## [CLEAN-REACT-7] Do not inline prop types on exported components
6+
## [CLEAN-REACT-PATTERNS-7] Do not inline prop types on exported components
77

88
### Reasoning
99

.claude/skills/coding-standards/rules/clean-react-8-no-class-components.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
2-
ruleId: CLEAN-REACT-8
2+
ruleId: CLEAN-REACT-PATTERNS-8
33
title: Use function components, not class components
44
---
55

6-
## [CLEAN-REACT-8] Use function components, not class components
6+
## [CLEAN-REACT-PATTERNS-8] Use function components, not class components
77

88
### Reasoning
99

.claude/skills/coding-standards/rules/clean-react-9-no-proptypes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
2-
ruleId: CLEAN-REACT-9
2+
ruleId: CLEAN-REACT-PATTERNS-9
33
title: Use TypeScript types, not propTypes or defaultProps
44
---
55

6-
## [CLEAN-REACT-9] Use TypeScript types, not propTypes or defaultProps
6+
## [CLEAN-REACT-PATTERNS-9] Use TypeScript types, not propTypes or defaultProps
77

88
### Reasoning
99

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Upload build to Sentry for size analysis
2+
description: |
3+
Download a platform binary and upload it to Sentry for size analysis. The binary is sourced
4+
from either the current workflow run's artifacts (cherry-pick prod deploys, which build natively)
5+
or the matching staging GitHub Release (re-promotion prod deploys, which do not build natively).
6+
7+
inputs:
8+
platform:
9+
description: "Platform label used in the GH Actions notice (e.g. 'Android' or 'iOS')"
10+
required: true
11+
asset-name:
12+
description: "Filename of the binary on disk and as the GH Release asset (e.g. 'Expensify-release.aab')"
13+
required: true
14+
artifact-name:
15+
description: "Name of the GH Actions artifact to download for cherry-pick deploys (e.g. 'androidBuild-artifact')"
16+
required: true
17+
staging-release-tag:
18+
description: "Tag of the staging GH Release to download from for re-promotion deploys (e.g. '9.4.13-0-staging')"
19+
required: true
20+
is-cherry-pick:
21+
description: "'true' when this deploy is a cherry-pick (binary is in the current run); 'false' otherwise (binary is on the staging release)"
22+
required: true
23+
24+
outputs:
25+
SENTRY_URL:
26+
description: URL to the Sentry size analysis for the uploaded build (empty if upload failed or quota exhausted)
27+
value: ${{ steps.upload.outputs.SENTRY_URL }}
28+
29+
runs:
30+
using: composite
31+
steps:
32+
- name: Setup Node
33+
uses: ./.github/actions/composite/setupNode
34+
35+
- name: Download binary from current workflow run (cherry-pick path)
36+
if: ${{ inputs.is-cherry-pick == 'true' }}
37+
continue-on-error: true
38+
# v7
39+
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131
40+
with:
41+
name: ${{ inputs.artifact-name }}
42+
path: ./
43+
44+
- name: Download binary from the staging GitHub Release (re-promotion path)
45+
if: ${{ inputs.is-cherry-pick != 'true' }}
46+
continue-on-error: true
47+
shell: bash
48+
env:
49+
TAG: ${{ inputs.staging-release-tag }}
50+
ASSET: ${{ inputs.asset-name }}
51+
run: |
52+
gh release download "$TAG" --pattern "$ASSET" --output "$ASSET"
53+
[ -s "$ASSET" ] || { echo "::error::Failed to obtain $ASSET from $TAG"; exit 1; }
54+
55+
- name: Upload to Sentry
56+
id: upload
57+
if: ${{ hashFiles(inputs.asset-name) != '' }}
58+
continue-on-error: true
59+
shell: bash
60+
env:
61+
ASSET: ${{ inputs.asset-name }}
62+
PLATFORM: ${{ inputs.platform }}
63+
run: |
64+
OUTPUT=$(npx sentry-cli build upload "$ASSET" \
65+
--org expensify --project app --build-configuration Release --log-level info 2>&1)
66+
echo "$OUTPUT"
67+
SENTRY_URL=$(echo "$OUTPUT" | grep -oE 'https://expensify\.sentry\.io/[^ )"}]+' | head -1)
68+
if [ -n "$SENTRY_URL" ]; then
69+
echo "::notice::${PLATFORM} Sentry size analysis: $SENTRY_URL"
70+
echo "SENTRY_URL=$SENTRY_URL" >> "$GITHUB_OUTPUT"
71+
fi

.github/workflows/buildAdHoc.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454
owner: context.repo.owner,
5555
repo: context.repo.repo,
5656
issue_number: ${{ inputs.APP_PR_NUMBER || 0 }},
57-
body: `🚧 @${{ github.actor }} has triggered a test Expensify/App build. You can view the [workflow run here](${workflowURL}).`
57+
body: `🚧 ${{ github.actor }} has triggered a test Expensify/App build. You can view the [workflow run here](${workflowURL}).`
5858
});
5959
6060
- name: Add build start comment to Expensify/Mobile-Expensify PR
@@ -69,7 +69,7 @@ jobs:
6969
owner: context.repo.owner,
7070
repo: 'Mobile-Expensify',
7171
issue_number: ${{ inputs.MOBILE_EXPENSIFY_PR || 0 }},
72-
body: `🚧 @${{ github.actor }} has triggered a test Expensify/Mobile-Expensify build. You can view the [workflow run here](${workflowURL}).`
72+
body: `🚧 ${{ github.actor }} has triggered a test Expensify/Mobile-Expensify build. You can view the [workflow run here](${workflowURL}).`
7373
});
7474
7575
buildAndroid:

.github/workflows/buildAndroid.yml

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ on:
3535
ROCK_ARTIFACT_URL:
3636
description: URL to download the ad-hoc build artifact (adhoc only)
3737
value: ${{ jobs.build.outputs.ROCK_ARTIFACT_URL }}
38-
SENTRY_URL:
39-
description: URL to Sentry size analysis
40-
value: ${{ jobs.build.outputs.SENTRY_URL }}
4138
AAB_FILENAME:
4239
description: Filename of the AAB artifact (empty if no AAB was produced)
4340
value: ${{ jobs.build.outputs.AAB_FILENAME }}
@@ -60,7 +57,6 @@ jobs:
6057
outputs:
6158
VERSION_CODE: ${{ steps.getAndroidVersion.outputs.VERSION_CODE }}
6259
ROCK_ARTIFACT_URL: ${{ steps.set-artifact-url.outputs.ARTIFACT_URL }}
63-
SENTRY_URL: ${{ steps.sentry-upload.outputs.SENTRY_URL }}
6460
AAB_FILENAME: ${{ steps.collectArtifacts.outputs.AAB_FILENAME }}
6561
APK_FILENAME: ${{ steps.collectArtifacts.outputs.APK_FILENAME }}
6662
SOURCEMAP_FILENAME: index.android.bundle.map
@@ -195,22 +191,6 @@ jobs:
195191
if: ${{ inputs.variant == 'Adhoc' }}
196192
run: echo "ARTIFACT_URL=$ARTIFACT_URL" >> "$GITHUB_OUTPUT"
197193

198-
- name: Upload Android build to Sentry for size analysis
199-
id: sentry-upload
200-
if: ${{ inputs.variant == 'Release' && env.ARTIFACT_PATH != '' }}
201-
continue-on-error: true
202-
timeout-minutes: 5
203-
run: |
204-
OUTPUT=$(npx sentry-cli build upload "$ARTIFACT_PATH" --org expensify --project app --build-configuration Release --log-level debug 2>&1)
205-
echo "$OUTPUT"
206-
SENTRY_URL=$(echo "$OUTPUT" | grep -oE 'https://expensify\.sentry\.io/[^ ]+' | head -1)
207-
if [ -n "$SENTRY_URL" ]; then
208-
echo "::notice::Android Sentry size analysis: $SENTRY_URL"
209-
echo "SENTRY_URL=$SENTRY_URL" >> "$GITHUB_OUTPUT"
210-
fi
211-
env:
212-
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
213-
214194
- name: Upload Gradle profile report
215195
if: always()
216196
# v6

.github/workflows/buildIOS.yml

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ on:
3535
ROCK_ARTIFACT_URL:
3636
description: URL to download the ad-hoc build artifact (adhoc only)
3737
value: ${{ jobs.build.outputs.ROCK_ARTIFACT_URL }}
38-
SENTRY_URL:
39-
description: URL to Sentry size analysis
40-
value: ${{ jobs.build.outputs.SENTRY_URL }}
4138
IPA_FILENAME:
4239
description: Filename of the IPA artifact produced by the build
4340
value: ${{ jobs.build.outputs.IPA_FILENAME }}
@@ -58,7 +55,6 @@ jobs:
5855
outputs:
5956
IOS_VERSION: ${{ steps.getIOSVersion.outputs.IOS_VERSION }}
6057
ROCK_ARTIFACT_URL: ${{ steps.set-artifact-url.outputs.ARTIFACT_URL }}
61-
SENTRY_URL: ${{ steps.sentry-upload.outputs.SENTRY_URL }}
6258
IPA_FILENAME: ${{ steps.set-ipa-filename.outputs.IPA_FILENAME }}
6359
DSYM_FILENAME: ${{ steps.set-ipa-filename.outputs.DSYM_FILENAME }}
6460
SOURCEMAP_FILENAME: main.jsbundle.map
@@ -244,22 +240,6 @@ jobs:
244240
comment-bot: false
245241
custom-identifier: ${{ steps.computeIdentifier.outputs.IDENTIFIER }}
246242

247-
- name: Upload iOS build to Sentry for size analysis
248-
id: sentry-upload
249-
if: ${{ inputs.variant == 'Release' && env.ARTIFACT_PATH != '' }}
250-
continue-on-error: true
251-
timeout-minutes: 5
252-
run: |
253-
OUTPUT=$(npx sentry-cli build upload "$ARTIFACT_PATH" --org expensify --project app --build-configuration Release --log-level debug 2>&1)
254-
echo "$OUTPUT"
255-
SENTRY_URL=$(echo "$OUTPUT" | grep -oE 'https://expensify\.sentry\.io/[^ ]+' | head -1)
256-
if [ -n "$SENTRY_URL" ]; then
257-
echo "::notice::iOS Sentry size analysis: $SENTRY_URL"
258-
echo "SENTRY_URL=$SENTRY_URL" >> "$GITHUB_OUTPUT"
259-
fi
260-
env:
261-
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
262-
263243
- name: Set artifact URL output
264244
id: set-artifact-url
265245
if: ${{ inputs.variant == 'Adhoc' }}

.github/workflows/buildVictoryChartRenderer.yml

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
- name: Log victory-chart-renderer build failure
5252
if: failure() || cancelled()
5353
run: |
54-
echo "::error::victory-chart-renderer Linux x64 build did not succeed for release ${{ inputs.release-tag }}. GitHub Release will not include victory-chart-renderer-linux-x64."
54+
echo "::error::victory-chart-renderer Linux x64 build did not succeed for release ${{ inputs.release-tag }}. The deploy GitHub Release will not be created."
5555
5656
- name: Announce victory-chart-renderer build failure in Slack
5757
if: failure() || cancelled()
@@ -63,8 +63,26 @@ jobs:
6363
{
6464
channel: '#announce',
6565
attachments: [{
66-
color: 'warning',
67-
text: `⚠️ ${process.env.AS_REPO} <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|victory-chart-renderer build> failed for deploy release <https://github.com/Expensify/App/releases/tag/${{ inputs.release-tag }}|${{ inputs.release-tag }}>. victory-chart-renderer-linux-x64 will not be attached.`,
66+
color: '#DB4545',
67+
text: `💥 ${process.env.AS_REPO} <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|victory-chart-renderer build> failed for deploy release <https://github.com/Expensify/App/releases/tag/${{ inputs.release-tag }}|${{ inputs.release-tag }}>. The deploy GitHub Release was blocked.`,
68+
}]
69+
}
70+
env:
71+
GITHUB_TOKEN: ${{ github.token }}
72+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
73+
74+
- name: Announce victory-chart-renderer build failure in deployer Slack
75+
if: failure()
76+
# v3
77+
uses: 8398a7/action-slack@1750b5085f3ec60384090fb7c52965ef822e869e
78+
with:
79+
status: custom
80+
custom_payload: |
81+
{
82+
channel: '#deployer',
83+
attachments: [{
84+
color: '#DB4545',
85+
text: `💥 ${process.env.AS_REPO} <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|victory-chart-renderer build> failed for deploy release <https://github.com/Expensify/App/releases/tag/${{ inputs.release-tag }}|${{ inputs.release-tag }}>. The deploy GitHub Release was blocked.`,
6886
}]
6987
}
7088
env:

0 commit comments

Comments
 (0)