You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expo v52升级后CI中EXPO_PUBLIC_ENV缓存致生产环境异常求助

问题:Expo v52升级后生产环境指向Staging服务器

我们使用GitHub Action自托管Runner自动编译应用,配置如下:

name: Build
jobs:
  deploy-ios:
    runs-on: [ self-hosted, macOS ]
    env:
      LANG: en_US.UTF-8
      MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
      P8_AUTH_KEY: ${{ secrets.P8_AUTH_KEY }}
      APPSTORE_KEY_ID: ${{ secrets.APPSTORE_KEY_ID }}
      APPSTORE_ISSUER_ID: ${{ secrets.APPSTORE_ISSUER_ID }}
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
      - uses: webfactory/ssh-agent@v0.5.0
        with:
          ssh-private-key: ${{ secrets.MATCH_REPO_KEY }}
      - name: Set up node environment
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      - name: Install dependencies
        run: npm install && npm install typescript -g && npx expo prebuild && bundle install
      - name: Install iOS dependencies
        run: cd ios && pod install
      - name: Setup keys
        run: |
          echo "${{ secrets.ENV_FILE }}" > .env
          echo "${{ secrets.P8_AUTH_KEY }}" | base64 -d > fastlane/key.p8
      - name: Build and deploy (STAGING)
        env:
          EXPO_PUBLIC_ENV: staging
        run: bundle exec fastlane ios staging
      - name: Build and deploy (PRODUCTION)
        env:
          EXPO_PUBLIC_ENV: production
        run: bundle exec fastlane ios production

原本EXPO_PUBLIC_ENV运行完全正常,但升级Expo到v52后,生产环境出现故障,原因是它指向了staging服务器。我们在TypeScript中通过process.env.EXPO_PUBLIC_ENV读取该环境变量,这部分逻辑没有问题。

以下是fastlane配置:

platform :ios do

    lane :staging do
        distribute(app_identifier: "bundle_id.staging")
    end

    lane :production do
        distribute(app_identifier: "bundle_id")
    end

    lane :distribute do |options|
        app_identifier = options[:app_identifier]
        scheme = "Scheme"
        xcodeproj = "ios/App.xcodeproj"
        workspace = "ios/App.xcworkspace"
        plist = "App/Info.plist"
        fullPlist = "ios/App/Info.plist"

        setup_ci
        api_key = app_store_connect_api_key(
            key_id: ENV["APPSTORE_KEY_ID"],
            issuer_id: ENV["APPSTORE_ISSUER_ID"],
            key_filepath: "fastlane/key.p8"
        )

        update_app_identifier(
            xcodeproj: xcodeproj,
            plist_path: plist,
            app_identifier: app_identifier
        )
        increment_build_number(
            build_number: number_of_commits,
            xcodeproj: xcodeproj
        )
        update_plist(
          plist_path: fullPlist,
          block: proc do |plist|
            plist[:ITSAppUsesNonExemptEncryption] = false
          end
        )

        match
        update_code_signing_settings(
            use_automatic_signing: false,
            team_id: "TEAM_ID",
            profile_name: "match AppStore #{app_identifier}",
            code_sign_identity: "iPhone Distribution",
            path: xcodeproj
        )
        build_app(
            clean: true,
            scheme: scheme,
            workspace: workspace,
            xcargs: "-allowProvisioningUpdates"
        )

        upload_to_testflight(
            api_key: api_key,
            app_identifier: app_identifier,
            skip_waiting_for_build_processing: true
        )

        clean_build_artifacts
    end

end

问题根源

Expo v52调整了EXPO_PUBLIC_*环境变量的处理逻辑:

  • v51及之前,这类变量会在构建阶段由Webpack动态注入
  • v52开始,expo prebuild会直接将EXPO_PUBLIC_*变量写入原生项目配置文件(如Info.plist),后续构建不再读取环境变量

你的原流程中expo prebuild只执行一次,且执行时未设置EXPO_PUBLIC_ENV;后续staging构建时设置的变量被写入配置后,production构建未重新执行prebuild,导致沿用了staging的变量值。


修复方案

方案1:拆分Staging与Production构建流程

将两个环境的构建拆分为独立Job,各自完整执行prebuild、依赖安装和构建步骤,彻底隔离环境变量:

name: Build
jobs:
  deploy-ios-staging:
    runs-on: [ self-hosted, macOS ]
    env:
      LANG: en_US.UTF-8
      MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
      P8_AUTH_KEY: ${{ secrets.P8_AUTH_KEY }}
      APPSTORE_KEY_ID: ${{ secrets.APPSTORE_KEY_ID }}
      APPSTORE_ISSUER_ID: ${{ secrets.APPSTORE_ISSUER_ID }}
      EXPO_PUBLIC_ENV: staging
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
      - uses: webfactory/ssh-agent@v0.5.0
        with:
          ssh-private-key: ${{ secrets.MATCH_REPO_KEY }}
      - name: Set up node environment
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      - name: Install dependencies
        run: npm install && npm install typescript -g && npx expo prebuild && bundle install
      - name: Install iOS dependencies
        run: cd ios && pod install
      - name: Setup keys
        run: |
          echo "${{ secrets.ENV_FILE }}" > .env
          echo "${{ secrets.P8_AUTH_KEY }}" | base64 -d > fastlane/key.p8
      - name: Build and deploy (STAGING)
        run: bundle exec fastlane ios staging

  deploy-ios-production:
    runs-on: [ self-hosted, macOS ]
    env:
      LANG: en_US.UTF-8
      MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
      P8_AUTH_KEY: ${{ secrets.P8_AUTH_KEY }}
      APPSTORE_KEY_ID: ${{ secrets.APPSTORE_KEY_ID }}
      APPSTORE_ISSUER_ID: ${{ secrets.APPSTORE_ISSUER_ID }}
      EXPO_PUBLIC_ENV: production
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
      - uses: webfactory/ssh-agent@v0.5.0
        with:
          ssh-private-key: ${{ secrets.MATCH_REPO_KEY }}
      - name: Set up node environment
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      - name: Install dependencies
        run: npm install && npm install typescript -g && npx expo prebuild && bundle install
      - name: Install iOS dependencies
        run: cd ios && pod install
      - name: Setup keys
        run: |
          echo "${{ secrets.ENV_FILE }}" > .env
          echo "${{ secrets.P8_AUTH_KEY }}" | base64 -d > fastlane/key.p8
      - name: Build and deploy (PRODUCTION)
        run: bundle exec fastlane ios production

方案2:每个构建步骤前重新执行Prebuild

如果不想拆分Job,可在每个构建步骤前清理并重新执行prebuild,确保环境变量正确注入:

# 前面步骤保持不变
      - name: Setup keys
        run: |
          echo "${{ secrets.ENV_FILE }}" > .env
          echo "${{ secrets.P8_AUTH_KEY }}" | base64 -d > fastlane/key.p8
      - name: Build and deploy (STAGING)
        env:
          EXPO_PUBLIC_ENV: staging
        run: |
          npx expo prebuild --clean
          cd ios && pod install
          bundle exec fastlane ios staging
      - name: Clean staging artifacts
        run: |
          rm -rf ios
          rm -rf node_modules/.cache
      - name: Build and deploy (PRODUCTION)
        env:
          EXPO_PUBLIC_ENV: production
        run: |
          npx expo prebuild --clean
          cd ios && pod install
          bundle exec fastlane ios production

方案3:通过XCArgs传递环境变量

修改fastlane的build_app步骤,通过xcargs直接传递环境变量,覆盖prebuild阶段的配置:

build_app(
    clean: true,
    scheme: scheme,
    workspace: workspace,
    xcargs: "-allowProvisioningUpdates EXPO_PUBLIC_ENV=#{ENV['EXPO_PUBLIC_ENV']}"
)

内容的提问来源于stack exchange,提问作者Nathan Fallet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 03:45:54