FastlaneでCIの上でフラッタアプリを構築して、いくつかのコードを再利用する方法


使用するfastlane 我々のフラッターアプリのために、IOSとAndroidビルドのために、セットアップと再利用コードを定義するために、我々は共通の言語を与えます:
  • ChangeLogスタイルに基づくchangelogの生成
  • コードスタイル、書式設定、およびlintの検証
  • 単体テスト
  • プロジェクトの自動生成コードが作成されていることを確認します.
  • プロジェクトが各プラットフォームに対してうまくビルドされることを確認します.
  • テストのためのFireBaseアプリケーション配布への配備
  • 各アプリケーションストアへの展開
  • これを行うにはいくつかのトリックがあります.
  • 親を作るfastfile プラットフォームごとに再利用可能なロジックと1を持っているところios/fastfile and android/fastfile .
  • プロジェクトのルートからタスクを実行する簡単な方法がありますsh_on_root 各プラットフォームからすべてのフラッタコマンドを実行するにはfastfile .
  • クリエイトアGemfile 各プラットフォームと定義.ruby-version ファイルを実行するために定義された環境を持っています.そこでFastlaneを走らせるために特定のRubyバージョンを必要とするCIサーバの問題を回避するのを助けます.
  • 我々が気づいたもう一つのものは--no-pub --suppress-analytics あなたがそれが良いスタートであることを試みたいならば、FlutterコマンドからのParamsはCIで我々に若干の時間を保存しました.
    私はいくつかのusefullレーンの例とそれらのためのいくつかのワークフローを示します、あなたはあなたのニーズについて考えなければならなくて、あなたが各々のステップのために必要とするレーンを呼ぶべきです、しかし、各々のプラットホームのために再利用しようとしてくださいfastfile ファイル.

    セットアップを見せてください
  • クリエイトGemfile ホームごとに
  • android/Gemfile
  • ios/Gemfile
  • 目次:
    source "https://rubygems.org"
    
    gem 'cocoapods'
    gem "fastlane"
    
    plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
    eval_gemfile(plugins_path) if File.exist?(plugins_path)
    
  • クリエイト.ruby-version したがって、ci(私たちのケースのbitriseで)はどのRubyバージョンを使用するべきかの手がかりを持っています
  • ios/.ruby-version
  • android/.ruby-version
  • 目次:
    2.6.5
    
  • 3つのFastlaneファイルを作成してください、そして、1が各々のプラットホームのために再利用される1と各々のプラットホームのために1import "../../scripts/Fastfile" )
  • fastfile :
  • opt_out_usage
    
    # Have an easy way to get the root of the project
    def root_path
      Dir.pwd.sub(/.*\Kfastlane/, '').sub(/.*\Kandroid/, '').sub(/.*\Kios/, '').sub(/.*\K\/\//, '')
    end
    
    # Have an easy way to run flutter tasks on the root of the project
    lane :sh_on_root do |options|
      command = options[:command]
      sh("cd #{root_path} && #{command}")
    end
    
    # Tasks to be reused on each platform flow
    lane :fetch_dependencies do
      sh_on_root(command: "flutter pub get --suppress-analytics")
    end
    
    # Tasks to be reused on each platform flow
    lane :build_autogenerated_code do
      sh_on_root(command: "flutter pub run intl_utils:generate && flutter pub run build_runner build --delete-conflicting-outputs")
    end
    
    # Tasks to be reused on each platform flow
    lane :lint do
      sh_on_root(command: "flutter format --suppress-analytics --set-exit-if-changed -n lib/main.dart lib/src/ test/")
    end
    
    # Tasks to be reused on each platform flow
    lane :test do |options|
      sh_on_root(command: "flutter test --no-pub --coverage --suppress-analytics")
    end
    
  • ios/fastfile :
  • import "../../scripts/Fastfile"
    
    default_platform(:ios)
    
    platform :ios do
      # Updates XCode project settings to use a different code signing based on method
      private_lane :archive do |options|
        method = options[:method]
    
        profile_name = method == 'ad-hoc' ? "Distribution - Staging (adhoc)" : "Production"
        update_code_signing_settings(profile_name: profile_name)
    
        build_app(export_method: method)
      end
    
      private_lane :authenticate_apple_store do
        p8_path = path_for_secret("your .p8 file path")
    
        app_store_connect_api_key(
          key_id: "your key id",
          issuer_id: "your used id",
          key_filepath: p8_path,
          duration: 1200, # optional
          in_house: false,
        )
      end
    
      lane :build do |options|
        # Reuse parent fastfile tasks
        fetch_dependencies
        build_autogenerated_code
    
    
        sign_enabled = options[:sign_enabled] || false
        sign_param = sign_enabled ? '' : '--no-codesign'
    
        config_only = options[:config_only] || false
        config_param = config_only ? '--config-only' : ''
    
        sh_on_root(command: "flutter build ios --no-pub --suppress-analytics --release #{sign_param} #{config_param}")
      end
    
      lane :deploy_staging do
        build(sign_enabled: true)
        archive(method: "ad-hoc")
    
        upload_symbols_to_crashlytics(dsym_path: "your.app.dSYM.zip")
    
        firebase_app_distribution(
          app: "yours app id from firebase",
          ipa_path: "your.ipa",
          groups: "developers, staging",
          release_notes: changelog
        )
      end
    
      lane :deploy_staging_testflight do
        build(sign_enabled: true)
        archive(method: "app-store")
    
        authenticate_apple_store
    
        # Reuse parent fastfile tasks
        test
    
        upload_to_testflight(
          ipa: "your.ipa",
          reject_build_waiting_for_review: true,
          skip_waiting_for_build_processing: false,
          distribute_external: true,
          notify_external_testers: true,
          groups: "Your testers"
        )
      end
    
      lane :deploy_production do
        sh_on_root(command: "sh scripts/cp_env.sh")
    
        # All certificates and .p8 file should be fine on runnning machine
        build(sign_enabled: true, config_only: true)
        archive(method: "app-store")
        authenticate_apple_store
    
        # Reuse parent fastfile tasks
        test
    
        deliver(
          ipa: "your.ipa",
          skip_metadata: true,
          skip_screenshots: true,
          submit_for_review: false,
          force: false,
          automatic_release: false,
          submission_information: {
            add_id_info_serves_ads: false,
            add_id_info_uses_idfa: false,
            export_compliance_uses_encryption: false,
          },
          precheck_include_in_app_purchases: false,
        )
      end
    end
    
  • android/fastfile
  • import "../../scripts/Fastfile"
    
    default_platform(:android)
    
    platform :android do
      private_lane :build_apk do
        # Reuse parent fastfile tasks
        fetch_dependencies
        build_autogenerated_code
    
        sh_on_root(command: "flutter build apk --release")
      end
    
      lane :build do
        # Reuse parent fastfile tasks
        fetch_dependencies
        build_autogenerated_code
    
        sh_on_root(command: "flutter build appbundle --no-pub --release --suppress-analytics")
      end
    
      lane :deploy_staging do
        build_apk
    
        # Reuse parent fastfile tasks
        test
    
        firebase_app_distribution(
          app: "your app id",
          groups: "your testers",
          android_artifact_type: "APK",
          android_artifact_path: "#{root_path}/build/app/outputs/flutter-apk/app-release.apk",
          firebase_cli_path: "/usr/local/bin/firebase"
        )
      end
    
      lane :deploy_production do
        build
    
        # Reuse parent fastfile tasks
        test
    
        supply(
          track: 'beta',
          aab: "../build/app/outputs/bundle/release/app-release.aab",
          json_key: path_for_secret("your play store.json"),
          skip_upload_apk: true, # Upload the aab instead of apk
          skip_upload_metadata: true,
          skip_upload_changelogs: true,
          skip_upload_images: true,
          skip_upload_screenshots: true
        )
      end
    end