allow changes in ota.config.js #55
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Push OTA Update (Test) | |
| on: | |
| push: | |
| branches: | |
| - wsun/ota-update-exp-workflow | |
| # workflow_dispatch: | |
| # inputs: | |
| # channel: | |
| # description: 'Update channel (e.g., preview, production)' | |
| # required: true | |
| # type: string | |
| # default: 'preview' | |
| # message: | |
| # description: 'Update message/description' | |
| # required: false | |
| # type: string | |
| # default: 'Manual update from GitHub Actions' | |
| # branch: | |
| # description: 'Branch name to include in update' | |
| # required: false | |
| # type: string | |
| # default: '' | |
| permissions: | |
| contents: read | |
| id-token: write | |
| env: | |
| TARGET_PR_NUMBER: '22840' | |
| jobs: | |
| fingerprint-comparison: | |
| name: Compare Expo Fingerprints | |
| runs-on: ubuntu-latest | |
| env: | |
| BASE_BRANCH_REF: 'wsun/eas-updates-key-signing' | |
| outputs: | |
| branch_fingerprint: ${{ steps.branch_fingerprint.outputs.fingerprint }} | |
| main_fingerprint: ${{ steps.main_fingerprint.outputs.fingerprint }} | |
| fingerprints_equal: ${{ steps.compare.outputs.equal }} | |
| steps: | |
| - name: Checkout target PR branch | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: refs/pull/${{ env.TARGET_PR_NUMBER }}/head | |
| fetch-depth: 0 | |
| - name: Checkout base branch snapshot | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ env.BASE_BRANCH_REF }} | |
| path: main | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'yarn' | |
| - name: Install dependencies (workflow branch) | |
| run: | | |
| echo "📦 Installing dependencies for current branch..." | |
| yarn install --immutable | |
| - name: Generate fingerprint (workflow branch) | |
| id: branch_fingerprint | |
| run: | | |
| echo "🧬 Generating fingerprint for current branch..." | |
| FINGERPRINT=$(yarn fingerprint:generate) | |
| echo "fingerprint=$FINGERPRINT" >> "$GITHUB_OUTPUT" | |
| echo "Target PR fingerprint: $FINGERPRINT" | |
| echo "Writing detailed fingerprint file to fingerprint-pr.json" | |
| npx @expo/fingerprint ./ > fingerprint-pr.json | |
| - name: Install dependencies (base branch) | |
| working-directory: main | |
| run: | | |
| echo "📦 Installing dependencies for base branch snapshot (${BASE_BRANCH_REF})..." | |
| yarn install --immutable | |
| - name: Generate fingerprint (base branch) | |
| id: main_fingerprint | |
| working-directory: main | |
| run: | | |
| echo "🧬 Generating fingerprint for base branch (${BASE_BRANCH_REF})..." | |
| FINGERPRINT=$(yarn fingerprint:generate) | |
| echo "fingerprint=$FINGERPRINT" >> "$GITHUB_OUTPUT" | |
| echo "Base branch fingerprint: $FINGERPRINT" | |
| echo "Writing detailed fingerprint file to ../fingerprint-base.json" | |
| npx @expo/fingerprint ./ > ../fingerprint-base.json | |
| - name: Compare fingerprints | |
| id: compare | |
| env: | |
| BRANCH_FP: ${{ steps.branch_fingerprint.outputs.fingerprint }} | |
| MAIN_FP: ${{ steps.main_fingerprint.outputs.fingerprint }} | |
| BASE_BRANCH_REF: ${{ env.BASE_BRANCH_REF }} | |
| run: | | |
| if [ -z "$BRANCH_FP" ] || [ -z "$MAIN_FP" ]; then | |
| echo "❌ Fingerprint generation failed." >&2 | |
| exit 1 | |
| fi | |
| echo "Target PR fingerprint: $BRANCH_FP" | |
| echo "Base branch fingerprint: $MAIN_FP" | |
| if [ "$BRANCH_FP" = "$MAIN_FP" ]; then | |
| echo "✅ Fingerprints match. No native changes detected." | |
| echo "equal=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "⚠️ Fingerprints differ. Inspecting changes..." | |
| BASE_BRANCH="$BASE_BRANCH_REF" | |
| if [[ "$BASE_BRANCH" == refs/heads/* ]]; then | |
| BASE_BRANCH="${BASE_BRANCH#refs/heads/}" | |
| fi | |
| git fetch origin "$BASE_BRANCH" --depth=1 | |
| CHANGED_FILES=$(git diff --name-only HEAD "origin/$BASE_BRANCH" || true) | |
| echo "Files changed vs origin/$BASE_BRANCH:" | |
| if [ -n "$CHANGED_FILES" ]; then | |
| echo "$CHANGED_FILES" | |
| else | |
| echo "<none>" | |
| fi | |
| ALLOWED_PATTERN='^(ota\.config\.js)$' | |
| ALLOWED_ONLY=true | |
| if [ -n "$CHANGED_FILES" ]; then | |
| while IFS= read -r file; do | |
| [ -z "$file" ] && continue | |
| if ! echo "$file" | grep -Eq "$ALLOWED_PATTERN"; then | |
| ALLOWED_ONLY=false | |
| break | |
| fi | |
| done <<< "$CHANGED_FILES" | |
| fi | |
| if [ "$ALLOWED_ONLY" = true ] && [ -n "$CHANGED_FILES" ]; then | |
| echo "ℹ️ Fingerprint diff caused only by allowed files; treating as compatible." | |
| echo "equal=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "❌ Fingerprint diff includes disallowed changes." | |
| echo "equal=false" >> "$GITHUB_OUTPUT" | |
| if [ -f fingerprint-base.json ] && [ -f fingerprint-pr.json ]; then | |
| echo "Fingerprint differences:" | |
| npx @expo/fingerprint ./ fingerprint-base.json fingerprint-pr.json || true | |
| else | |
| echo "Detailed fingerprint files not found; skipping diff." | |
| fi | |
| exit 0 | |
| - name: Record fingerprint summary | |
| env: | |
| BRANCH_FP: ${{ steps.branch_fingerprint.outputs.fingerprint }} | |
| MAIN_FP: ${{ steps.main_fingerprint.outputs.fingerprint }} | |
| MATCHES: ${{ steps.compare.outputs.equal }} | |
| TARGET_PR_NUMBER: ${{ env.TARGET_PR_NUMBER }} | |
| BASE_BRANCH_REF: ${{ env.BASE_BRANCH_REF }} | |
| run: | | |
| { | |
| echo "### Expo Fingerprint Comparison" | |
| echo "" | |
| echo "- Target PR (#$TARGET_PR_NUMBER) fingerprint: \`$BRANCH_FP\`" | |
| echo "- Base branch (\`$BASE_BRANCH_REF\`) fingerprint: \`$MAIN_FP\`" | |
| echo "- Match: \`$MATCHES\`" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| # approval: | |
| # name: Require OTA Update Approval | |
| # needs: fingerprint-comparison | |
| # if: ${{ needs.fingerprint-comparison.outputs.fingerprints_equal == 'true' }} | |
| # runs-on: ubuntu-latest | |
| # steps: | |
| # - name: Await approval from mobile platform team | |
| # uses: op5dev/require-team-approval@dfd7b8b9a88bf82a955c103f7e19642b0411aecd | |
| # with: | |
| # team: mobile-platform | |
| # pr-number: 22748 | |
| # token: ${{ secrets.METAMASK_MOBILE_ORG_READ_TOKEN }} | |
| push-update: | |
| name: Push EAS Update | |
| runs-on: ubuntu-latest | |
| environment: expo-update | |
| needs: | |
| - fingerprint-comparison | |
| # - approval | |
| if: ${{ needs.fingerprint-comparison.outputs.fingerprints_equal == 'true' }} | |
| env: | |
| EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }} | |
| EXPO_PROJECT_ID: ${{ secrets.EXPO_PROJECT_ID }} | |
| EXPO_CHANNEL: ${{ vars.EXPO_CHANNEL }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: refs/pull/${{ env.TARGET_PR_NUMBER }}/head | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'yarn' | |
| - name: Install dependencies | |
| run: | | |
| echo "📦 Installing dependencies..." | |
| yarn install --immutable | |
| - name: Setup project | |
| run: | | |
| echo "🔧 Running setup for GitHub CI..." | |
| yarn setup:github-ci | |
| - name: Display configuration | |
| run: | | |
| TARGET_RUNTIME_VERSION=$(node -p "require('./package.json').version") | |
| TARGET_PROJECT_ID=$(node -p "require('./ota.config.js').PROJECT_ID") | |
| echo "🔧 Configuration:" | |
| echo " Channel: ${EXPO_CHANNEL:-<not set>}" | |
| echo " Channel (vars.EXPO_CHANNEL): ${{ vars.EXPO_CHANNEL }}" | |
| echo " Message: test eas update workflow" | |
| echo " Runtime Version (target): ${TARGET_RUNTIME_VERSION}" | |
| # Fingerprint comparison temporarily disabled | |
| echo "" | |
| echo "📱 Project Info:" | |
| echo " Project ID (target branch): ${TARGET_PROJECT_ID}" | |
| echo " EXPO_PROJECT_ID (from secrets): $EXPO_PROJECT_ID" | |
| echo " EXPO_TOKEN (from secrets): $EXPO_TOKEN" | |
| - name: Prepare Expo update signing key | |
| env: | |
| EXPO_KEY_PRIV: ${{ secrets.EXPO_KEY_PRIV }} | |
| run: | | |
| if [ -z "${EXPO_KEY_PRIV}" ]; then | |
| echo "::error title=Missing EXPO_KEY_PRIV::EXPO_KEY_PRIV secret is not configured. Cannot sign update." >&2 | |
| exit 1 | |
| fi | |
| mkdir -p keys | |
| echo "Writing Expo private key to ./keys/private-key.pem" | |
| printf '%s' "${EXPO_KEY_PRIV}" > keys/private-key.pem | |
| - name: Push EAS Update | |
| env: | |
| # Skip linting during Metro transform in CI (linting already done separately) | |
| SKIP_TRANSFORM_LINT: 'true' | |
| # Increase Node heap to avoid OOM during Expo export in CI | |
| NODE_OPTIONS: '--max_old_space_size=8192' | |
| # Disable LavaMoat sandbox to prevent duplicate bundle executions in CI | |
| EXPO_NO_LAVAMOAT: '1' | |
| run: | | |
| echo "🚀 Publishing EAS update..." | |
| if [ -z "${EXPO_CHANNEL}" ]; then | |
| echo "::error title=Missing EXPO_CHANNEL::EXPO_CHANNEL environment variable is not set. Cannot publish update." >&2 | |
| exit 1 | |
| fi | |
| if [ ! -f keys/private-key.pem ]; then | |
| echo "::error title=Missing signing key::keys/private-key.pem not found. Ensure the signing key step ran successfully." >&2 | |
| exit 1 | |
| fi | |
| echo "ℹ️ Git head: $(git rev-parse HEAD)" | |
| echo "ℹ️ Checking for eas script in package.json..." | |
| if ! grep -q '"eas": "eas"' package.json; then | |
| echo "::error title=Missing eas script::package.json does not include an \"eas\" script. Commit hash: $(git rev-parse HEAD)." >&2 | |
| exit 1 | |
| fi | |
| echo "ℹ️ Available yarn scripts containing eas:" | |
| yarn run --json | grep '"name":"eas"' || true | |
| yarn run eas update \ | |
| --channel "${EXPO_CHANNEL}" \ | |
| --private-key-path "./keys/private-key.pem" \ | |
| --message "test eas update workflow" \ | |
| --non-interactive | |
| - name: Update summary | |
| if: success() | |
| run: | | |
| echo "### ✅ EAS Update Published Successfully" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Channel:** \`${EXPO_CHANNEL:-<not set>}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "**Message:** test eas update workflow" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Users on the \`${EXPO_CHANNEL:-<not set>}\` channel will receive this update on their next app launch." >> $GITHUB_STEP_SUMMARY | |
| - name: Update summary on failure | |
| if: failure() | |
| run: | | |
| echo "### ❌ EAS Update Failed" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Check the logs above for error details." >> $GITHUB_STEP_SUMMARY | |
| fingerprint-mismatch: | |
| name: Fingerprint Mismatch Guard | |
| needs: fingerprint-comparison | |
| if: ${{ needs.fingerprint-comparison.outputs.fingerprints_equal != 'true' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Fail on native changes | |
| run: | | |
| echo "::error title=Fingerprint mismatch::Current branch fingerprint differs from main. Native changes detected; aborting workflow." | |
| echo "Current fingerprint: ${{ needs.fingerprint-comparison.outputs.branch_fingerprint }}" | |
| echo "Main fingerprint: ${{ needs.fingerprint-comparison.outputs.main_fingerprint }}" | |
| exit 1 |