@@ -36,32 +36,56 @@ jobs:
3636 OP_SERVICE_ACCOUNT_TOKEN : ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
3737 SETUP_AS_APP : false
3838
39- - name : Update submodule to latest Mobile-Expensify main
40- run : git submodule update --remote
39+ - name : Record submodule gitlink and update Mobile-Expensify to latest main
40+ id : submoduleRemote
41+ run : |
42+ RECORDED_SHA=$(git rev-parse HEAD:Mobile-Expensify)
43+ echo "Submodule commit recorded on App: $RECORDED_SHA"
44+ echo "RECORDED_SHA=$RECORDED_SHA" >> "$GITHUB_OUTPUT"
45+
46+ git submodule update --remote
47+
48+ ACTUAL_SHA=$(git -C Mobile-Expensify rev-parse HEAD)
49+ echo "Mobile-Expensify after remote update: $ACTUAL_SHA"
50+ echo "ACTUAL_SHA=$ACTUAL_SHA" >> "$GITHUB_OUTPUT"
4151
42- - name : Check current versions
52+ - name : Check sync state ( versions + submodule pointer)
4353 id : checkVersions
4454 run : |
4555 APP_VERSION=$(jq -r .version package.json)
4656 ME_VERSION=$(jq -r .meta.version Mobile-Expensify/app/config/config.json)
57+ RECORDED_SHA="${{ steps.submoduleRemote.outputs.RECORDED_SHA }}"
58+ ACTUAL_SHA="${{ steps.submoduleRemote.outputs.ACTUAL_SHA }}"
59+
4760 echo "E/App version: $APP_VERSION"
4861 echo "Mobile-Expensify version: $ME_VERSION"
4962 echo "APP_VERSION=$APP_VERSION" >> "$GITHUB_OUTPUT"
5063 echo "ME_VERSION=$ME_VERSION" >> "$GITHUB_OUTPUT"
51-
52- if [ "$APP_VERSION" == "$ME_VERSION" ]; then
53- echo "::notice::✅ Versions are already in sync: $APP_VERSION"
64+
65+ if [[ "$RECORDED_SHA" != "$ACTUAL_SHA" ]]; then
66+ echo "::warning::⚠️ Submodule pointer is behind Mobile-Expensify main (recorded $RECORDED_SHA, latest $ACTUAL_SHA)"
67+ fi
68+
69+ if [[ "$APP_VERSION" == "$ME_VERSION" && "$RECORDED_SHA" == "$ACTUAL_SHA" ]]; then
70+ echo "::notice::✅ Versions and submodule are in sync ($APP_VERSION @ $ACTUAL_SHA)"
5471 echo "IN_SYNC=true" >> "$GITHUB_OUTPUT"
72+ echo "NEED_FULL_VERSION_SYNC=false" >> "$GITHUB_OUTPUT"
5573 else
56- echo "::warning::⚠️ Versions are out of sync - E/App: $APP_VERSION, Mobile-Expensify: $ME_VERSION"
5774 echo "IN_SYNC=false" >> "$GITHUB_OUTPUT"
75+ if [[ "$APP_VERSION" != "$ME_VERSION" ]]; then
76+ echo "::warning::⚠️ Versions are out of sync - E/App: $APP_VERSION, Mobile-Expensify: $ME_VERSION"
77+ echo "NEED_FULL_VERSION_SYNC=true" >> "$GITHUB_OUTPUT"
78+ else
79+ echo "::notice::Versions match ($APP_VERSION) but App must record the latest submodule commit"
80+ echo "NEED_FULL_VERSION_SYNC=false" >> "$GITHUB_OUTPUT"
81+ fi
5882 fi
5983
6084 - name : Determine target version
61- if : steps.checkVersions.outputs.IN_SYNC != 'true'
85+ if : steps.checkVersions.outputs.IN_SYNC != 'true' && steps.checkVersions.outputs.NEED_FULL_VERSION_SYNC == 'true'
6286 id : targetVersion
6387 run : |
64- if [ -n "${{ inputs.TARGET_VERSION }}" ]; then
88+ if [[ -n "${{ inputs.TARGET_VERSION }}" ] ]; then
6589 echo "Using provided target version: ${{ inputs.TARGET_VERSION }}"
6690 echo "VERSION=${{ inputs.TARGET_VERSION }}" >> "$GITHUB_OUTPUT"
6791 else
@@ -71,69 +95,109 @@ jobs:
7195 fi
7296
7397 - name : Setup Node
74- if : steps.checkVersions.outputs.IN_SYNC != 'true'
98+ if : steps.checkVersions.outputs.IN_SYNC != 'true' && steps.checkVersions.outputs.NEED_FULL_VERSION_SYNC == 'true'
7599 uses : ./.github/actions/composite/setupNode
76100
77101 - name : Sync E/App to target version
78- if : steps.checkVersions.outputs.IN_SYNC != 'true'
102+ if : steps.checkVersions.outputs.IN_SYNC != 'true' && steps.checkVersions.outputs.NEED_FULL_VERSION_SYNC == 'true'
79103 run : |
80104 TARGET="${{ steps.targetVersion.outputs.VERSION }}"
81105 echo "::notice::Syncing E/App to version $TARGET"
82-
106+
83107 # Update version using npm (this updates package.json and package-lock.json)
84108 npm --no-git-tag-version version "$TARGET"
85-
109+
86110 # Extract version components for native file updates
87111 SHORT_VERSION="${TARGET%-*}" # e.g., "9.3.11" from "9.3.11-48"
88112 BUILD_NUMBER="${TARGET#*-}" # e.g., "48" from "9.3.11-48"
89113 CF_VERSION="${SHORT_VERSION}.${BUILD_NUMBER}" # e.g., "9.3.11.48"
90-
114+
91115 # Pad build number components for Android version code (prefix 10 for E/App)
92116 IFS='.' read -r MAJOR MINOR PATCH <<< "$SHORT_VERSION"
93117 ANDROID_VERSION_CODE="10$(printf '%02d' "$MAJOR")$(printf '%02d' "$MINOR")$(printf '%02d' "$PATCH")$(printf '%02d' "$BUILD_NUMBER")"
94-
118+
95119 echo "Updating Android build.gradle with versionName=$TARGET, versionCode=$ANDROID_VERSION_CODE"
96120 sed -i '' "s/versionName \"[0-9.-]*\"/versionName \"$TARGET\"/" android/app/build.gradle
97121 sed -i '' "s/versionCode [0-9]*/versionCode $ANDROID_VERSION_CODE/" android/app/build.gradle
98-
122+
99123 echo "Updating iOS plists with CFBundleShortVersionString=$SHORT_VERSION, CFBundleVersion=$CF_VERSION"
100124 /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $SHORT_VERSION" ios/NewExpensify/Info.plist
101125 /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $CF_VERSION" ios/NewExpensify/Info.plist
102126 /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $SHORT_VERSION" ios/NotificationServiceExtension/Info.plist
103127 /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $CF_VERSION" ios/NotificationServiceExtension/Info.plist
104128 /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $SHORT_VERSION" ios/ShareViewController/Info.plist
105129 /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $CF_VERSION" ios/ShareViewController/Info.plist
106-
130+
107131 # Commit version changes
108132 git add package.json package-lock.json android/app/build.gradle ios/*/Info.plist
109133 git commit -m "Update version to $TARGET (sync recovery)"
110-
134+
111135 # Update submodule reference
112136 git add Mobile-Expensify
113137 git commit -m "Update Mobile-Expensify submodule version to $TARGET (sync recovery)"
114-
138+
115139 # Push changes
116140 if ! git push origin main; then
117141 echo "::warning::Push failed, attempting rebase..."
118142 git fetch origin main
119143 git rebase origin/main
120144 git push origin main
121145 fi
122-
146+
123147 echo "::notice::✅ Successfully synced E/App to version $TARGET"
124148
149+ - name : Bump Mobile-Expensify submodule only
150+ if : steps.checkVersions.outputs.IN_SYNC != 'true' && steps.checkVersions.outputs.NEED_FULL_VERSION_SYNC != 'true'
151+ run : |
152+ EXPECTED_SHA="${{ steps.submoduleRemote.outputs.ACTUAL_SHA }}"
153+ CURRENT_SHA=$(git -C Mobile-Expensify rev-parse HEAD)
154+ if [[ "$CURRENT_SHA" != "$EXPECTED_SHA" ]]; then
155+ echo "::error::Mobile-Expensify checkout ($CURRENT_SHA) does not match expected main ($EXPECTED_SHA)"
156+ exit 1
157+ fi
158+
159+ echo "::notice::Recording Mobile-Expensify submodule at $CURRENT_SHA (versions already matched ${{ steps.checkVersions.outputs.APP_VERSION }})"
160+ git add Mobile-Expensify
161+ git commit -m "Bump Mobile-Expensify submodule to latest main ($CURRENT_SHA)"
162+
163+ if ! git push origin main; then
164+ echo "::warning::Push failed, attempting rebase..."
165+ git fetch origin main
166+ git rebase origin/main
167+ git submodule update --remote
168+ git add Mobile-Expensify
169+ if ! git diff --staged --quiet; then
170+ git commit -m "Bump Mobile-Expensify submodule to latest main after rebase ($(git -C Mobile-Expensify rev-parse HEAD))"
171+ fi
172+ git push origin main
173+ fi
174+
175+ echo "::notice::✅ Submodule pointer updated on App main"
176+
125177 - name : Verify sync completed
178+ id : verifySync
126179 if : steps.checkVersions.outputs.IN_SYNC != 'true'
127180 run : |
128181 APP_VERSION=$(jq -r .version package.json)
129182 ME_VERSION=$(jq -r .meta.version Mobile-Expensify/app/config/config.json)
130-
131- if [ "$APP_VERSION" != "$ME_VERSION" ]; then
183+
184+ if [[ "$APP_VERSION" != "$ME_VERSION" ] ]; then
132185 echo "::error::Sync failed! Versions still don't match"
133186 echo "::error::E/App: $APP_VERSION, Mobile-Expensify: $ME_VERSION"
134187 exit 1
135188 fi
136- echo "::notice::✅ Versions verified: $APP_VERSION"
189+
190+ git -C Mobile-Expensify fetch origin
191+
192+ RECORDED=$(git rev-parse HEAD:Mobile-Expensify)
193+ REMOTE_SHA=$(git -C Mobile-Expensify rev-parse origin/main)
194+ if [[ "$RECORDED" != "$REMOTE_SHA" ]]; then
195+ echo "::error::Submodule on App main ($RECORDED) still differs from Mobile-Expensify origin/main ($REMOTE_SHA)"
196+ exit 1
197+ fi
198+
199+ echo "POST_SYNC_APP_VERSION=$APP_VERSION" >> "$GITHUB_OUTPUT"
200+ echo "::notice::✅ Verified versions ($APP_VERSION) and submodule match Mobile-Expensify main ($RECORDED)"
137201
138202 - name : Announce sync in Slack
139203 if : steps.checkVersions.outputs.IN_SYNC != 'true'
@@ -146,7 +210,7 @@ jobs:
146210 channel: '#deployer',
147211 attachments: [{
148212 color: "good",
149- text: `✅ Version sync completed. E/App and Mobile-Expensify are now both at version ${{ steps.targetVersion .outputs.VERSION }}`
213+ text: `✅ Version sync completed. E/App and Mobile-Expensify are at ${{ steps.verifySync .outputs.POST_SYNC_APP_VERSION }}; submodule matches Mobile-Expensify main. `
150214 }]
151215 }
152216 env :
0 commit comments