Search code examples
fluttergithub-actionsfastlane

Flutter versioning CI/CD with Fastlane and Github Actions


I have implemented the configuration for fastlane and github actions in my flutter project for iOS, with some custom actions for incrementing the version and build number.

default_platform(:ios)

DEVELOPER_APP_ID = ENV['DEVELOPER_APP_ID']
DEVELOPER_APP_IDENTIFIER = ENV['DEVELOPER_APP_IDENTIFIER']
PROVISIONING_PROFILE_SPECIFIER = ENV['PROVISIONING_PROFILE_SPECIFIER']
TEMP_KEYCHAIN_USER = ENV['TEMP_KEYCHAIN_USER']
TEMP_KEYCHAIN_PASSWORD = ENV['TEMP_KEYCHAIN_PASSWORD']
Path = '/Users/*********'

def delete_temp_keychain(name)
  if File.exist? File.expand_path("~/Library/Keychains/#{name}-db")
    delete_keychain(
      name: name
    )
  end
end

def create_temp_keychain(name, password)
  print('name', name, 'password', password)
  create_keychain(
    name: name,
    password: password,
    unlock: false,
    timeout: 0
  )
end

def ensure_temp_keychain(name, password)
  delete_temp_keychain(name)
  create_temp_keychain(name, password)
end

def update_version(type)
  case type
  when 'major' then increment_version_number_in_xcodeproj(bump_type: 'major')
  when 'minor' then increment_version_number_in_xcodeproj(bump_type: 'minor')
  when 'patch' then increment_version_number_in_xcodeproj(bump_type: 'patch')
  else abort("Unknown version bump type: #{type}\nValid options: major, minor, patch.")
  end
end

platform :ios do
  lane :update_major do
    update_version('major')
    increment_build_number
  end
  lane :update_minor do
    update_version('minor')
    increment_build_number
  end
  lane :update_patch do
    # update_patch('patch')
    # increment_build_number
    
    script = 'perlscript.pl'
    latest
    exec("/usr/bin/perl #{script}")
    # perl -i -pe 's/^(version:\s+\d+\.\d+\.\d+\+)(\d+)$/$1.($2+1)/e' /Users/*******/Dev/******/pubspec.yaml")
 
  end

  
  lane :_release_candidate do
    keychain_name = TEMP_KEYCHAIN_USER
    keychain_password = TEMP_KEYCHAIN_PASSWORD
    # ensure_temp_keychain('fastlane_keychain_login', '!QA#ED4rf')
    ensure_temp_keychain(keychain_name, keychain_password)
    add_git_tag(
      grouping: 'fastlane-builds',
      includes_lane: true,
      prefix: 'v',
      build_number: get_build_number,
      postfix: "-RC#{get_build_number}"
    )

    push_to_git_remote # this will git-push the above newly created local git-tag
    # match(
    #   type: 'appstore',
    #   app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
    #   git_basic_authorization: Base64.strict_encode64(ENV['GIT_AUTHORIZATION']),
    #   readonly: true,
    #   keychain_name: keychain_name,
    #   keychain_password: keychain_password
    # )

    # gym(
    #   configuration: 'Release',
    #   workspace: 'Runner.xcworkspace',
    #   scheme: 'Runner',
    #   export_method: 'app-store',
    #   export_options: {
    #     provisioningProfiles: {
    #       DEVELOPER_APP_ID => PROVISIONING_PROFILE_SPECIFIER
    #     }
    #   }
    # )

    # pilot(
    #   apple_id: "#{DEVELOPER_APP_ID}",
    #   app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
    #   skip_waiting_for_build_processing: false,
    #   skip_submission: true,
    #   distribute_external: false,
    #   notify_external_testers: false,
    #   ipa: './Runner.ipa'
    # )

    delete_temp_keychain(keychain_name)
  end
end

as shown in the fastfile above I even tried to using perl to update the pubspec but I couldn't manage to pass the new value after incrementing it.

#!/bin/bash
# set -e

# Find and increment the version number.

perl -i -pe 's/^(version:\s+\d+\.\d+\.\d+\+)(\d+)$/$1.($2+1)/e' /Users/******/Dev/*******/pubspec.yaml

I am facing a problem updating the incremented number in xcode using increment_build_number action from fastlane, to pubspec.yaml version and syncing the changed files from the github action to the main repo or to my local repo, since the incrementation is occuring by running the lane in the github action.


Solution

  • I found one way to update the incremented build version by adding this code to the yml file for GitHub actions after the incrementing job:

    - uses: stefanzweifel/git-auto-commit-action@v4
      with:
        commit_message: Apply php-cs-fixer changes
    

    where it auto commit and pushes the changes to the repo, and from that point a pull request can be created and voila, you have the changes locally again to be synced with the actions triggered before.

    ++EDIT++

    you can check the full code in the github yml file, where i am triggering the script from the fastlane file based on keywords in the commit message:

    # cd.yml
    name: CD
    
    
    
    on:
      push:
        branches:
          - 'main'
          
    jobs:
     deploy_ios:
        name: Deploy beta build to TestFlight
        runs-on: macos-latest
        steps:
          - name: Checkout code from ref
            uses: actions/checkout@v2
            with:
              ref: ${{ github.ref }}
          - name: Run Flutter tasks
            uses: subosito/flutter-action@v1
            with:
              flutter-version: '3.0.3'
          - run: flutter pub get
          - run: flutter build ios --release --no-codesign 
          - name: increment major
            if: "contains(github.event.head_commit.message, 'major')"
            uses: maierj/[email protected]
            with: 
              lane: update_major
              subdirectory: ios
          - name: increment minor
            if: "contains(github.event.head_commit.message, 'minor')"
            uses: maierj/[email protected]
            with: 
              lane: update_minor
              subdirectory: ios
          - name: increment patch
            if: "contains(github.event.head_commit.message, 'patch')"
            uses: maierj/[email protected]
            with: 
              lane: update_patch
              subdirectory: ios
          - name: Deploy iOS Beta to TestFlight via Fastlane
            uses: maierj/[email protected]
            with:
              lane: _release_candidate
              subdirectory: ios
          - uses: stefanzweifel/git-auto-commit-action@v4
            with:
              commit_message: Auto Commit
    
          
            env:
              APP_STORE_CONNECT_TEAM_ID: '${{ secrets.APP_STORE_CONNECT_TEAM_ID }}'
              DEVELOPER_APP_ID: '${{ secrets.DEVELOPER_APP_ID }}'
              DEVELOPER_APP_IDENTIFIER: '${{ secrets.DEVELOPER_APP_IDENTIFIER }}'
              DEVELOPER_PORTAL_TEAM_ID: '${{ secrets.DEVELOPER_PORTAL_TEAM_ID }}'
              FASTLANE_APPLE_ID: '${{ secrets.FASTLANE_APPLE_ID }}'
              FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: '${{ secrets.FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD }}'
              MATCH_PASSWORD: '${{ secrets.MATCH_PASSWORD }}'
              GIT_AUTHORIZATION: '${{ secrets.GIT_AUTHORIZATION }}'
              PROVISIONING_PROFILE_SPECIFIER: '${{ secrets.PROVISIONING_PROFILE_SPECIFIER }}'
              TEMP_KEYCHAIN_PASSWORD: '${{ secrets.TEMP_KEYCHAIN_PASSWORD }}'
              TEMP_KEYCHAIN_USER: '${{ secrets.TEMP_KEYCHAIN_USER }}'