react-nativeexpogithub-actionsfastlanecd

Expo env variable is cached in CI/CI since v52 update


We have a GitHub Action self-hosted runner compiler our app automatically, with a configuration looking like this:

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

Everything was working perfectly with EXPO_PUBLIC_ENV, until we updated Expo from v51 to v52, and discovered a few days later that production was broken since it was pointing to staging server...

Any way to fix this?

We are consuming the EXPO_PUBLIC_ENV env variable in typescript with process.env. EXPO_PUBLIC_ENV, so nothing wrong on this side.

Also, here is the fastlane config:

platform :ios do

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

    lane :production do
        distribute(app_identifier: "bundle_id.staging")
    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

Solution

  • I made a script to clean the cache manually. It's a bit hacky but it's the only way to clean the cache apparently (there is not way to do it without starting the app)

    #! /bin/bash
    set -m
    
    # To clean the cache, we start with reset cache and kill it after 5 seconds
    kill $(lsof -t -i:8081)
    npm start -- --reset-cache &
    sleep 5
    kill -9 %1
    

    I call the script in the Fastlane script before building the app.

    I regret native development where everything was easy, you just read Info.plist or android flavor. No other middle software that breaks production.