Skip to content

Mobile POS OTA - production #1

Mobile POS OTA - production

Mobile POS OTA - production #1

name: OTA Update Mobile POS
run-name: "Mobile POS OTA - production"
permissions:
id-token: write
contents: read
actions: read
on:
workflow_dispatch:
inputs:
message:
description: 'Update message (shown in EAS dashboard)'
required: false
type: string
default: ''
jobs:
publish-update:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup
uses: ./.github/actions/ci-setup
with:
root-path: dapps/pos-app
package-manager: npm
- name: Create env file
run: |
if [ -z "${{ secrets.POS_ENV_FILE }}" ]; then
echo "Error: POS_ENV_FILE secret is empty or not set"
exit 1
fi
echo "${{ secrets.POS_ENV_FILE }}" > dapps/pos-app/.env
- name: Compute current fingerprints
id: fingerprints
run: |
cd dapps/pos-app
ANDROID_FINGERPRINT=$(npx expo-updates fingerprint:generate --platform android 2>/dev/null | tail -1)
IOS_FINGERPRINT=$(npx expo-updates fingerprint:generate --platform ios 2>/dev/null | tail -1)
echo "android=$ANDROID_FINGERPRINT" >> "$GITHUB_OUTPUT"
echo "ios=$IOS_FINGERPRINT" >> "$GITHUB_OUTPUT"
echo "Current Android fingerprint: $ANDROID_FINGERPRINT"
echo "Current iOS fingerprint: $IOS_FINGERPRINT"
- name: Download last native build fingerprint (Android)
id: download-fingerprint-android
uses: dawidd6/action-download-artifact@bf251b5aa9c2f7eeb574a96ee720e24f801b7c11 # v6
with:
name: native-fingerprint-android-production
workflow: release-pos.yaml
if_no_artifact_found: warn
path: /tmp/native-fingerprint/android
- name: Download last native build fingerprint (iOS)
id: download-fingerprint-ios
uses: dawidd6/action-download-artifact@bf251b5aa9c2f7eeb574a96ee720e24f801b7c11 # v6
with:
name: native-fingerprint-ios-production
workflow: release-pos.yaml
if_no_artifact_found: warn
path: /tmp/native-fingerprint/ios
- name: Check for native changes
id: native-check
run: |
HAS_NATIVE_CHANGES=false
ANDROID_FINGERPRINT_PATH=/tmp/native-fingerprint/android/native-fingerprint.txt
IOS_FINGERPRINT_PATH=/tmp/native-fingerprint/ios/native-fingerprint.txt
if [ -f "$ANDROID_FINGERPRINT_PATH" ]; then
LAST_ANDROID_FINGERPRINT=$(cat "$ANDROID_FINGERPRINT_PATH")
CURRENT_ANDROID_FINGERPRINT="${{ steps.fingerprints.outputs.android }}"
echo "Last native Android fingerprint: $LAST_ANDROID_FINGERPRINT"
echo "Current Android fingerprint: $CURRENT_ANDROID_FINGERPRINT"
if [ "$LAST_ANDROID_FINGERPRINT" != "$CURRENT_ANDROID_FINGERPRINT" ]; then
HAS_NATIVE_CHANGES=true
echo "::error::Android native changes detected. Current fingerprint does not match the last native Android build."
fi
else
echo "⚠️ No previous native Android fingerprint found for channel 'production'."
fi
if [ -f "$IOS_FINGERPRINT_PATH" ]; then
LAST_IOS_FINGERPRINT=$(cat "$IOS_FINGERPRINT_PATH")
CURRENT_IOS_FINGERPRINT="${{ steps.fingerprints.outputs.ios }}"
echo "Last native iOS fingerprint: $LAST_IOS_FINGERPRINT"
echo "Current iOS fingerprint: $CURRENT_IOS_FINGERPRINT"
if [ "$LAST_IOS_FINGERPRINT" != "$CURRENT_IOS_FINGERPRINT" ]; then
HAS_NATIVE_CHANGES=true
echo "::error::iOS native changes detected. Current fingerprint does not match the last native iOS build."
fi
else
echo "⚠️ No previous native iOS fingerprint found for channel 'production'."
fi
if [ "$HAS_NATIVE_CHANGES" = "true" ]; then
echo "has_native_changes=true" >> "$GITHUB_OUTPUT"
echo "::error::Native changes detected. You must create a new native release before publishing an OTA update."
exit 1
fi
if [ ! -f "$ANDROID_FINGERPRINT_PATH" ] || [ ! -f "$IOS_FINGERPRINT_PATH" ]; then
echo "⚠️ At least one platform fingerprint is missing. This can happen after initial OTA setup."
echo "Proceeding with OTA publish."
fi
echo "has_native_changes=false" >> "$GITHUB_OUTPUT"
echo "✅ Fingerprints match for all available platform artifacts — safe to publish OTA update."
- name: Setup EAS CLI
run: npm install -g eas-cli
- name: Publish OTA update
id: eas-update
working-directory: dapps/pos-app
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
run: |
eas update \
--channel production \
--message "${{ inputs.message || format('OTA update from {0}', github.ref_name) }}" \
--non-interactive
- name: Send Slack notification
if: always() && !cancelled()
uses: slackapi/slack-github-action@v2.1.0
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
{
"text": "OTA Update Report - Mobile POS",
"blocks": [
{
"type": "header",
"text": { "type": "plain_text", "text": "📦 OTA Update Report - Mobile POS" }
},
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*Channel:*\n`production`" },
{ "type": "mrkdwn", "text": "*Branch:*\n`${{ github.ref_name }}`" },
{ "type": "mrkdwn", "text": "*Status:*\n`${{ steps.native-check.outputs.has_native_changes == 'true' && '❌ Blocked — native changes require full release' || (steps.eas-update.outcome == 'success' && '✅ Published' || '❌ Failed') }}`" },
{ "type": "mrkdwn", "text": "*Message:*\n`${{ inputs.message || 'No message' }}`" }
]
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "View Workflow Run" },
"url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
}
]
}
]
}