Skip to content

Commit

Permalink
Merge pull request #52629 from software-mansion-labs/feat/old-dot-sub…
Browse files Browse the repository at this point in the history
…module

[NoQA] [HybridApp] Add Mobile-Expensify submodule and build HybridApp on both platforms
  • Loading branch information
Julesssss authored Dec 11, 2024
2 parents fb35d5c + 791dbee commit 890806d
Show file tree
Hide file tree
Showing 26 changed files with 298 additions and 292 deletions.
66 changes: 14 additions & 52 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,46 +163,25 @@ jobs:
name: Build and deploy Android HybridApp
needs: prep
runs-on: ubuntu-latest-xl
defaults:
run:
working-directory: Mobile-Expensify/react-native
steps:
- name: Checkout App repo
uses: actions/checkout@v4

- name: Checkout Mobile-Expensify repo
- name: Checkout App and Mobile-Expensify repo
uses: actions/checkout@v4
with:
repository: 'Expensify/Mobile-Expensify'
submodules: true
path: 'Mobile-Expensify'
token: ${{ secrets.OS_BOTIFY_TOKEN }}
# fetch-depth: 0 is required in order to fetch the correct submodule branch
fetch-depth: 0

- name: Update submodule
- name: Update submodule to match main
run: |
git submodule update --init
# Update submodule to latest on staging
git fetch
git checkout staging
git submodule update --init --remote
- name: Configure MapBox SDK
run: ./scripts/setup-mapbox-sdk.sh ${{ secrets.MAPBOX_SDK_DOWNLOAD_TOKEN }}

- uses: actions/setup-node@v4
with:
node-version-file: 'Mobile-Expensify/react-native/.nvmrc'
cache: npm
cache-dependency-path: 'Mobile-Expensify/react-native'

- name: Install node modules
run: |
npm install
cd .. && npm install
# Fixes https://github.com/Expensify/App/issues/51682
npm run grunt:build:shared
- name: Setup Node
id: setup-node
uses: ./.github/actions/composite/setupNode

- name: Setup Java
uses: actions/setup-java@v4
Expand All @@ -214,7 +193,6 @@ jobs:
uses: ruby/[email protected]
with:
bundler-cache: true
working-directory: 'Mobile-Expensify/react-native'

- name: Install New Expensify Gems
run: bundle install
Expand All @@ -229,7 +207,7 @@ jobs:
op document get --output ./upload-key.keystore upload-key.keystore
op document get --output ./android-fastlane-json-key.json android-fastlane-json-key.json
# Copy the keystore to the Android directory for Fullstory
cp ./upload-key.keystore ../Android
cp ./upload-key.keystore Mobile-Expensify/Android
- name: Load Android upload keystore credentials from 1Password
id: load-credentials
Expand Down Expand Up @@ -496,47 +474,31 @@ jobs:
runs-on: macos-13-xlarge
env:
DEVELOPER_DIR: /Applications/Xcode_15.2.0.app/Contents/Developer
defaults:
run:
working-directory: Mobile-Expensify/react-native
steps:
- name: Checkout
uses: actions/checkout@v4
with:
repository: 'Expensify/Mobile-Expensify'
submodules: true
path: 'Mobile-Expensify'
token: ${{ secrets.OS_BOTIFY_TOKEN }}
# fetch-depth: 0 is required in order to fetch the correct submodule branch
fetch-depth: 0

- name: Update submodule
run: |
git submodule update --init
# Update submodule to latest on staging
git fetch
git checkout staging
git submodule update --init --remote
- name: Configure MapBox SDK
run: |
./scripts/setup-mapbox-sdk.sh ${{ secrets.MAPBOX_SDK_DOWNLOAD_TOKEN }}
- uses: actions/setup-node@v4
- name: Setup Node
id: setup-node
with:
node-version-file: 'Mobile-Expensify/react-native/.nvmrc'
cache-dependency-path: 'Mobile-Expensify/react-native'

- name: Install node modules
run: |
npm install
cd .. && npm install
uses: ./.github/actions/composite/setupNode

- name: Setup Ruby
uses: ruby/[email protected]
with:
bundler-cache: true
working-directory: 'Mobile-Expensify/react-native'

- name: Install New Expensify Gems
run: bundle install
Expand All @@ -545,20 +507,20 @@ jobs:
uses: actions/cache@v4
id: pods-cache
with:
path: ios/Pods
key: ${{ runner.os }}-pods-cache-${{ hashFiles('ios/Podfile.lock', 'firebase.json') }}
path: Mobile-Expensify/ios/Pods
key: ${{ runner.os }}-pods-cache-${{ hashFiles('Mobile-Expensify/ios/Podfile.lock', 'firebase.json') }}

- name: Compare Podfile.lock and Manifest.lock
id: compare-podfile-and-manifest
run: echo "IS_PODFILE_SAME_AS_MANIFEST=${{ hashFiles('ios/Podfile.lock') == hashFiles('ios/Pods/Manifest.lock') }}" >> "$GITHUB_OUTPUT"
run: echo "IS_PODFILE_SAME_AS_MANIFEST=${{ hashFiles('Mobile-Expensify/ios/Podfile.lock') == hashFiles('Mobile-Expensify/ios/Pods/Manifest.lock') }}" >> "$GITHUB_OUTPUT"

- name: Install cocoapods
uses: nick-fields/retry@3f757583fb1b1f940bc8ef4bf4734c8dc02a5847
if: steps.pods-cache.outputs.cache-hit != 'true' || steps.compare-podfile-and-manifest.outputs.IS_PODFILE_SAME_AS_MANIFEST != 'true' || steps.setup-node.outputs.cache-hit != 'true'
with:
timeout_minutes: 10
max_attempts: 5
command: cd Mobile-Expensify/iOS && pod install
command: npm run pod-install

- name: Install 1Password CLI
uses: 1password/install-cli-action@v1
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "Mobile-Expensify"]
path = Mobile-Expensify
url = https://github.com/Expensify/Mobile-Expensify.git
1 change: 1 addition & 0 deletions Mobile-Expensify
Submodule Mobile-Expensify added at 7df7a0
96 changes: 96 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,102 @@ export default withOnyx({
1. The application uses [`react-navigation`](https://reactnavigation.org/) for navigating between parts of the app.
1. [Higher Order Components](https://reactjs.org/docs/higher-order-components.html) are used to connect React components to persistent storage via [`react-native-onyx`](https://github.com/Expensify/react-native-onyx).
----
# HybridApp
Currently, the production Expensify app contains both "Expensify Classic" and "New Expensify". The file structure is as follows:
- 📂 [**App**](https://github.com/Expensify/App)
- 📂 [**android**](https://github.com/Expensify/App/tree/main/android): New Expensify Android specific code (not a part of HybridApp native code)
- 📂 [**ios**](https://github.com/Expensify/App/tree/main/ios): New Expensify iOS specific code (not a part of HybridApp native code)
- 📂 [**src**](https://github.com/Expensify/App/tree/main/src): New Expensify TypeScript logic
- 📂 [**Mobile-Expensify**](https://github.com/Expensify/Mobile-Expensify): `git` submodule that is pointed to [Mobile-Expensify](https://github.com/Expensify/Mobile-Expensify)
- 📂 [**Android**](https://github.com/Expensify/Mobile-Expensify/tree/main/Android): Expensify Classic Android specific code
- 📂 [**iOS**](https://github.com/Expensify/Mobile-Expensify/tree/main/iOS): Expensify Classic iOS specific code
- 📂 [**app**](https://github.com/Expensify/Mobile-Expensify/tree/main/app): Expensify Classic JavaScript logic (aka YAPL)
You can only build HybridApp if you have been granted access to [`Mobile-Expensify`](https://github.com/Expensify/Mobile-Expensify). For most contributors, you will be working on the standalone NewDot application.
## Getting started with HybridApp
1. If you haven't, please follow [these instructions](https://github.com/Expensify/App?tab=readme-ov-file#getting-started) to setup the NewDot local environment.
2. Run `git submodule update --init` to download the `Mobile-Expensify` sourcecode.
- If you have access to `Mobile-Expensify` and the command fails with a https-related error add this to your `~/.gitconfig` file:

```
[url "ssh://[email protected]/"]
insteadOf = https://github.com/
```

At this point, the default behavior of some `npm` scripts will change to target HybridApp:
- `npm run android` - build HybridApp for Android
- `npm run ios` - build HybridApp for iOS
- `npm run ipad` - build HybridApp for iPad
- `npm run ipad-sm` - build HybridApp for small iPad
- `npm run pod-install` - install pods for HybridApp
- `npm run clean` - clean native code of HybridApp

If for some reason, you need to target the standalone NewDot application, you can append `*-standalone` to each of these scripts (eg. `npm run ios-standalone` will build NewDot instead of HybridApp).

## Working with HybridApp
Day-to-day work with HybridApp shouldn't differ much from the work on the standalone NewDot repo.
The main difference is that the native code which runs React Native is located in `./Mobile-Expensify/Android` and `./Mobile-Expensify/iOS` directories. It means, that changes in `./android` and `./ios` folders in the root **won't affect the HybridApp build**.

In that case, if you'd like to eg. remove `Pods`, you need to do it in `./Mobile-Expensify/iOS`. The same rule applies to Android builds - if you'd like to delete `.cxx`, `build` or `.gradle` directories, you need to go to `./Mobile-Expensify/android` first.

Additionally, If you'd like to open the HybridApp project in Android Studio or XCode, you **must choose a workspace located in the `Mobile-Expensify`** directory:
- Android: `./Mobile-Expensify/Android`
- iOS: `./Mobile-Expensify/iOS/Expensify.xcworkspace`
### Updating the Mobile-Expensify submodule
`Mobile-Expensify` directory is a git submodule. It means, that it points to a specific commit on the `Mobile-Expensify` repository. If you'd like to download the most recent changes from `main`, please use the following command:

`git submodule update --remote`

### Modifying Mobile-Expensify code

It's important to emphasise that a git submodule is just a **regular git repository** after all. It means that you can switch branches, pull the newest changes, and execute all regular git commands within the `Mobile-Expensify` directory.
> [!Note]
> #### For external contributors
>
> If you'd like to modify the `Mobile-Expensify` source code, it is best that you create your own fork. Then, you can swap origin of the remote repository by executing this command:
>
> `cd Mobile-Expensify && git remote set-url origin <YOUR_FORK_URL>`
>
> This way, you'll attach the submodule to your fork repository.
### Adding HybridApp-related patches
Applying patches from the `patches` directory is performed automatically with the `npm install` command executed in `Expensify/App`.
If you'd like to add HybridApp-specific patches, use the `--patch-dir` flag:

`npx patch-package <PACKAGE_NAME> --patch-dir Mobile-Expensify/patches`

### HybridApp troubleshooting

#### Cleaning the repo
- `npm run clean` - deep clean of all HybridApp artifacts (including NewDot's `node_modules`)
- `npm run clean -- --ios` - clean only iOS HybridApp artifacts (`Pods`, `build` folder, `DerivedData`)
- `npm run clean -- --android` - clean only Android HybridApp artifacts (`.cxx`, `build`, and `.gradle` folders, execute `./gradlew clean`)
If you'd like to do it manually, remember to `cd Mobile-Expensify` first!

#### Common errors
1. **Please check your internet connection** - set `_isOnDev` in `api.js` to always return `false`
2. **CDN: trunk URL couldn't be downloaded** - `cd Mobile-Expensify/iOS && pod repo remove trunk`
3. **Task :validateSigningRelease FAILED** - open `Mobile-Expensify/Android/build.gradle` and do the following:
```
- signingConfig signingConfigs.release
+ signingConfig signingConfigs.debug
```
4. **Build service could not create build operation: unknown error while handling message: MsgHandlingError(message: "unable to initiate PIF transfer session (operation in progress?)")** - reopen XCode
----
# Philosophy
Expand Down
16 changes: 8 additions & 8 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ platform :android do

desc "Generate a production HybridApp AAB"
lane :build_hybrid do
ENV["ENVFILE"]="../.env.production.hybridapp"
ENV["ENVFILE"]="Mobile-Expensify/.env.production.hybridapp"
gradle(
project_dir: '../Android',
project_dir: 'Mobile-Expensify/Android',
task: "bundleRelease",
flags: "--refresh-dependencies",
properties: {
Expand Down Expand Up @@ -118,7 +118,7 @@ platform :android do
lane :build_local_hybrid do
ENV["ENVFILE"]=".env.production"
gradle(
project_dir: '../Android',
project_dir: 'Mobile-Expensify/Android',
task: 'assemble',
flavor: 'Production',
build_type: 'Release',
Expand Down Expand Up @@ -372,7 +372,7 @@ platform :ios do

desc "Build an iOS HybridApp production build"
lane :build_hybrid do
ENV["ENVFILE"]="../.env.production.hybridapp"
ENV["ENVFILE"]="Mobile-Expensify/.env.production.hybridapp"

setupIOSSigningCertificate()

Expand All @@ -389,7 +389,7 @@ platform :ios do
)

build_app(
workspace: "../iOS/Expensify.xcworkspace",
workspace: "Mobile-Expensify/iOS/Expensify.xcworkspace",
scheme: "Expensify",
output_name: "Expensify.ipa",
export_method: "app-store",
Expand Down Expand Up @@ -418,9 +418,9 @@ platform :ios do

desc "Build an unsigned iOS HybridApp production build"
lane :build_unsigned_hybrid do
ENV["ENVFILE"]="../Mobile-Expensify/.env.production.hybridapp"
ENV["ENVFILE"]="./Mobile-Expensify/.env.production.hybridapp"
build_app(
workspace: "../Mobile-Expensify/iOS/Expensify.xcworkspace",
workspace: "./Mobile-Expensify/iOS/Expensify.xcworkspace",
scheme: "Expensify"
)
setIOSBuildOutputsInEnv()
Expand Down Expand Up @@ -537,7 +537,7 @@ platform :ios do
dsym_path: ENV[KEY_DSYM_PATH],
gsp_path: "./ios/GoogleService-Info.plist",
# Assuming we are running this from the react-native submodule directory for HybridApp
binary_path: "../iOS/Pods/FirebaseCrashlytics/upload-symbols"
binary_path: "./Mobile-Expensify/iOS/Pods/FirebaseCrashlytics/upload-symbols"
)
end

Expand Down
2 changes: 2 additions & 0 deletions ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ require File.join(File.dirname(`node --print "require.resolve('expo/package.json
# This value is used by $RNMapboxMaps
$RNMapboxMapsImpl = 'mapbox'
$VCDisableFrameProcessors = true
ENV['PROJECT_ROOT_PATH'] = "./";

def node_require(script)
# Resolve script with node to allow for hoisting
Expand Down Expand Up @@ -82,6 +83,7 @@ target 'NewExpensify' do
# ENV Variable enables/disables TurboModules
ENV['RCT_NEW_ARCH_ENABLED'] = '1';


use_react_native!(
:path => config[:reactNativePath],
# An absolute path to your application root.
Expand Down
2 changes: 1 addition & 1 deletion ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3290,6 +3290,6 @@ SPEC CHECKSUMS:
VisionCamera: c95a8ad535f527562be1fb05fb2fd324578e769c
Yoga: a1d7895431387402a674fd0d1c04ec85e87909b8

PODFILE CHECKSUM: 15e2f095b9c80d658459723edf84005a6867debf
PODFILE CHECKSUM: 615266329434ea4a994dccf622008a2197313c88

COCOAPODS: 1.15.2
16 changes: 11 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@
"setupNewDotWebForEmulators": "./scripts/setup-newdot-web-emulators.sh",
"startAndroidEmulator": "./scripts/start-android.sh",
"postinstall": "./scripts/postInstall.sh",
"clean": "npx react-native clean-project-auto",
"android": "./scripts/set-pusher-suffix.sh && npx react-native run-android --mode=developmentDebug --appId=com.expensify.chat.dev --active-arch-only",
"ios": "./scripts/set-pusher-suffix.sh && npx react-native run-ios --list-devices --mode=\"DebugDevelopment\" --scheme=\"New Expensify Dev\"",
"clean": "./scripts/clean.sh",
"clean-standalone": "./scripts/clean.sh --new-dot",
"android": "./scripts/set-pusher-suffix.sh && ./scripts/run-build.sh --android",
"android-standalone": "./scripts/set-pusher-suffix.sh && ./scripts/run-build.sh --android --new-dot",
"ios": "./scripts/set-pusher-suffix.sh && ./scripts/run-build.sh --ios",
"ios-standalone": "./scripts/set-pusher-suffix.sh && ./scripts/run-build.sh --ios --new-dot",
"pod-install": "./scripts/pod-install.sh",
"ipad": "concurrently \"npx react-native run-ios --simulator=\\\"iPad Pro (12.9-inch) (6th generation)\\\" --mode=\\\"DebugDevelopment\\\" --scheme=\\\"New Expensify Dev\\\"\"",
"ipad-sm": "concurrently \"npx react-native run-ios --simulator=\\\"iPad Pro (11-inch) (4th generation)\\\" --mode=\\\"DebugDevelopment\\\" --scheme=\\\"New Expensify Dev\\\"\"",
"pod-install-standalone": "./scripts/pod-install.sh --new-dot",
"ipad": "concurrently \"./scripts/run-build.sh --ipad\"",
"ipad-standalone": "concurrently \"./scripts/run-build.sh --ipad --new-dot\"",
"ipad-sm": "concurrently \"./scripts/run-build.sh --ipad-sm\"",
"ipad-sm-standalone": "concurrently \"./scripts/run-build.sh --ipad-sm --new-dot\"",
"start": "npx react-native start",
"web": "./scripts/set-pusher-suffix.sh && concurrently npm:web-proxy npm:web-server",
"web-proxy": "ts-node web/proxy.ts",
Expand Down
2 changes: 1 addition & 1 deletion patches/@onfido+react-native-sdk+10.6.0.patch
Original file line number Diff line number Diff line change
Expand Up @@ -1252,7 +1252,7 @@ index a9de0d0..da83d9f 100644
- s.dependency "Onfido", "~> 29.6.0"
+ s.dependency "Onfido", "~> 29.7.0"
+
+ if ENV['USE_FRAMEWORKS'] == '1'
+ if ENV['USE_FRAMEWORKS'] != nil
+ s.pod_target_xcconfig = {
+ "OTHER_CFLAGS" => "$(inherited) -DUSE_FRAMEWORKS",
+ "OTHER_CPLUSPLUSFLAGS" => "$(inherited) -DUSE_FRAMEWORKS",
Expand Down

This file was deleted.

Loading

0 comments on commit 890806d

Please sign in to comment.