[IONIC] fastlane 적용2. 운영버전

jae hwan choo·2021년 12월 25일

아이오닉

목록 보기
3/6

개발버전을 성공했으니 운영버전을 기록한다.

플러그인

Android 운영버전

여기에서 시키는대로 개발버전을 적용하면 AAb 파일이 나온다.
현재 하려는 앱은 내부 배포이기 때문에 apk가 필요한데,
적혀있는 옵션을 보면 android_package_type 옵션으로 선택빌드가
가능하다고 되어 있으나 실제로 해보면 안된다.

오랜 검색끝에, 찾아낸 결과
$gem install fastlane-plugin-ionic
빌드로 설치되는 버전은 0.1.0
현재 github의 버전을 보면 readme에 나온 기능은 0.2.0 이다.

원인을 알았으니 해결 해보면.
1. 수동으로 gem, git 설치: 실패 - 안된다.
2. 파일을 복사해서 넣기: 실패 - 에러난다.

에휴...
코드에 문제가 있다고 판단되어
한줄한줄 0.1.0 -> 0.2.0 기능에 필요한 부분만 카피한다.

rvm을 사용한 gem 설치 위치
/Users/(나의계정)/.rvm/gems/ruby-2.7.2/gems/fastlane-plugin-ionic-0.1.0/lib/fastlane/plugin/ionic/actions/ionic_action.rb

해당 'ionic_action.rb' 파일을 수정해서 apk 빌드가 되게 만든다.
파일첨부가 안된다. 파일의 내용은 글 맨 아래 붙여 넣는다.

platform :android do
  desc "Build Release"
  lane :prod do
    ionic(
      platform: 'android',
      prod: true,
      release: true,
      android_package_type: 'apk',
      keystore_path: 'app_android_key',
      keystore_password: '패스워드',
      keystore_alias: 'app_alias_key',
      key_password: '패스워드'
    )
  end
end

운영 빌드 완료 - 릴리즈 버전의 apk가 나온다.
여담으로, 플러그인 마지막 업데이트가 3년전이다.

IOS 운영 빌드 하기

www 폴더 경로 잘 확인 해준다.
auto 인증서라면 크게 문제가 없다.
provisioning_profile 을 사용 한다면 UUID를 적어 주어야 한다.

platform :ios do
  desc "Build Release"
  lane :prod do
    ionic(
      platform: 'ios',
      release: true,
      type: 'enterprise',
      provisioning_profile: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
      team_id: 'xxxxxxxxxx'
    )
  end
end

ionic_action.rb 파일 내용

module Fastlane
  module Actions
    module SharedValues
      CORDOVA_IOS_RELEASE_BUILD_PATH = :CORDOVA_IOS_RELEASE_BUILD_PATH
      CORDOVA_ANDROID_RELEASE_BUILD_PATH = :CORDOVA_ANDROID_RELEASE_BUILD_PATH
    end

    class IonicAction < Action
      # valid action params

      ANDROID_ARGS_MAP = {
        keystore_path:        'keystore',
        keystore_password:    'storePassword',
        key_password:         'password',
        keystore_alias:       'alias',
        build_number:         'versionCode',
        min_sdk_version:      'gradleArg=-PcdvMinSdkVersion',
        cordova_no_fetch:     'cordovaNoFetch',
        android_package_type: 'packageType'
      }

      IOS_ARGS_MAP = {
        type:                 'packageType',
        team_id:              'developmentTeam',
        provisioning_profile: 'provisioningProfile',
        build_flag:           'buildFlag'
      }

      # extract arguments only valid for the platform from all arguments
      # + map action params to the cli param they will be used for
      def self.get_platform_args(params, args_map)
        platform_args = []
        args_map.each do |action_key, cli_param|
          param_value = params[action_key]

          # handle `build_flag` being an Array
          if action_key.to_s == 'build_flag' && param_value.kind_of?(Array)
            unless param_value.empty?
              param_value.each do |flag|
                platform_args << "--#{cli_param}=#{flag.shellescape}"
              end
            end
          # handle all other cases
          else
            unless param_value.to_s.empty?
              platform_args << "--#{cli_param}=#{Shellwords.escape(param_value)}"
            end
          end
        end

        return platform_args.join(' ')
      end

      def self.get_android_args(params)
        if params[:key_password].empty?
          params[:key_password] = params[:keystore_password]
        end

        return self.get_platform_args(params, ANDROID_ARGS_MAP)
      end

      def self.get_ios_args(params)
        app_identifier = CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier)

        if params[:provisioning_profile].empty?
          # If `match` or `sigh` were used before this, use the certificates returned from there
          params[:provisioning_profile] = ENV['SIGH_UUID'] || ENV["sigh_#{app_identifier}_#{params[:type].sub('-', '')}"]
        end

        if params[:type] == 'adhoc'
          params[:type] = 'ad-hoc'
        end
        if params[:type] == 'appstore'
          params[:type] = 'app-store'
        end

        return self.get_platform_args(params, IOS_ARGS_MAP)
      end

      # add platform if missing (run step #1)
      def self.check_platform(params)
        platform = params[:platform]
        if platform && !File.directory?("./platforms/#{platform}")
          if params[:cordova_no_fetch]
            sh "ionic cordova platform add #{platform} --no-interactive --nofetch"
          else
            sh "ionic cordova platform add #{platform} --no-interactive"
          end
        end
      end

      # app_name
      def self.get_app_name
        config = REXML::Document.new(File.open('config.xml'))
        return config.elements['widget'].elements['name'].first.value # TODO: Simplify!? (Check logic in cordova)
      end

      # actual building! (run step #2)
      def self.build(params)
        args = [params[:release] ? '--release' : '--debug']
        args << '--device' if params[:device]
        args << '--prod' if params[:prod]
        args << '--browserify' if params[:browserify]
        args << '--verbose' if params[:verbose]

        if !params[:cordova_build_config_file].to_s.empty?
          args << "--buildConfig=#{Shellwords.escape(params[:cordova_build_config_file])}"
        end

        android_args = self.get_android_args(params) if params[:platform].to_s == 'android'
        ios_args = self.get_ios_args(params) if params[:platform].to_s == 'ios'

        if params[:cordova_prepare]
          # TODO: Remove params not allowed/used for `prepare`
          sh "ionic cordova prepare #{params[:platform]} --no-interactive #{args.join(' ')}"
        end

        # special handling for `build_number` param
        if params[:platform].to_s == 'ios' && !params[:build_number].to_s.empty?
          cf_bundle_version = params[:build_number].to_s
          Actions::UpdateInfoPlistAction.run(
            xcodeproj: "./platforms/ios/#{self.get_app_name}.xcodeproj",
            plist_path: "#{self.get_app_name}/#{self.get_app_name}-Info.plist",
            block: lambda { |plist|
              plist['CFBundleVersion'] = cf_bundle_version
            }
          )
        end

        if params[:platform].to_s == 'ios'
          sh "ionic cordova compile #{params[:platform]} --no-interactive #{args.join(' ')} -- #{ios_args}" 
        elsif params[:platform].to_s == 'android'
          sh "ionic cordova compile #{params[:platform]} --no-interactive #{args.join(' ')} -- -- #{android_args}" 
        end
      end

      # export build paths (run step #3)
      def self.set_build_paths(is_release)
        app_name = self.get_app_name
        build_type = is_release ? 'release' : 'debug'

        ENV['CORDOVA_ANDROID_RELEASE_BUILD_PATH'] = "./platforms/android/app/build/outputs/apk/#{build_type}/app-#{build_type}.apk"
        ENV['CORDOVA_IOS_RELEASE_BUILD_PATH'] = "./platforms/ios/build/device/#{app_name}.ipa"

        # TODO: https://github.com/bamlab/fastlane-plugin-cordova/issues/7
        # TODO: Set env vars that gym and Co automatically use
      end

      def self.run(params)
        self.check_platform(params)
        self.build(params)
        self.set_build_paths(params[:release])
      end

      #####################################################
      # @!group Documentation
      #####################################################

      def self.description
        "Build your Ionic app"
      end

      def self.details
        "Easily integrate your Ionic build into a Fastlane setup"
      end

      def self.available_options
        [
          FastlaneCore::ConfigItem.new(
            key: :platform,
            env_name: "CORDOVA_PLATFORM",
            description: "Platform to build on. Should be either android or ios",
            is_string: true,
            default_value: '',
            verify_block: proc do |value|
              UI.user_error!("Platform should be either android or ios") unless ['', 'android', 'ios'].include? value
            end
          ),
          FastlaneCore::ConfigItem.new(
            key: :release,
            env_name: "CORDOVA_RELEASE",
            description: "Build for release if true, or for debug if false",
            is_string: false,
            default_value: true,
            verify_block: proc do |value|
              UI.user_error!("Release should be boolean") unless [false, true].include? value
            end
          ),
          FastlaneCore::ConfigItem.new(
            key: :device,
            env_name: "CORDOVA_DEVICE",
            description: "Build for device",
            is_string: false,
            default_value: true,
            verify_block: proc do |value|
              UI.user_error!("Device should be boolean") unless [false, true].include? value
            end
          ),
          FastlaneCore::ConfigItem.new(
            key: :prod,
            env_name: "IONIC_PROD",
            description: "Build for production",
            is_string: false,
            default_value: false,
            verify_block: proc do |value|
              UI.user_error!("Prod should be boolean") unless [false, true].include? value
            end
          ),
          FastlaneCore::ConfigItem.new(
            key: :type,
            env_name: "CORDOVA_IOS_PACKAGE_TYPE",
            description: "This will determine what type of build is generated by Xcode. Valid options are development, enterprise, adhoc, and appstore",
            is_string: true,
            default_value: 'appstore',
            verify_block: proc do |value|
              UI.user_error!("Valid options are development, enterprise, adhoc, and appstore.") unless ['development', 'enterprise', 'adhoc', 'appstore', 'ad-hoc', 'app-store'].include? value
            end
          ),
          FastlaneCore::ConfigItem.new(
            key: :verbose,
            env_name: "CORDOVA_VERBOSE",
            description: "Pipe out more verbose output to the shell",
            default_value: false,
            is_string: false,
            verify_block: proc do |value|
              UI.user_error!("Verbose should be boolean") unless [false, true].include? value
            end
          ),
          FastlaneCore::ConfigItem.new(
            key: :team_id,
            env_name: "CORDOVA_IOS_TEAM_ID",
            description: "The development team (Team ID) to use for code signing",
            is_string: true,
            default_value: CredentialsManager::AppfileConfig.try_fetch_value(:team_id)
          ),
          FastlaneCore::ConfigItem.new(
            key: :provisioning_profile,
            env_name: "CORDOVA_IOS_PROVISIONING_PROFILE",
            description: "GUID of the provisioning profile to be used for signing",
            is_string: true,
            default_value: ''
          ),
          FastlaneCore::ConfigItem.new(
            key: :android_package_type,
            env_name: "CORDOVA_ANDROID_PACKAGE_TYPE",
            description: "This will determine what type of Android build is generated. Valid options are apk or bundle",
            default_value: 'apk',
            verify_block: proc do |value|
              UI.user_error!("Valid options are apk or bundle.") unless ['apk', 'bundle'].include? value
            end
          ),
          FastlaneCore::ConfigItem.new(
            key: :keystore_path,
            env_name: "CORDOVA_ANDROID_KEYSTORE_PATH",
            description: "Path to the Keystore for Android",
            is_string: true,
            default_value: ''
          ),
          FastlaneCore::ConfigItem.new(
            key: :keystore_password,
            env_name: "CORDOVA_ANDROID_KEYSTORE_PASSWORD",
            description: "Android Keystore password",
            is_string: true,
            default_value: ''
          ),
          FastlaneCore::ConfigItem.new(
            key: :key_password,
            env_name: "CORDOVA_ANDROID_KEY_PASSWORD",
            description: "Android Key password (default is keystore password)",
            is_string: true,
            default_value: ''
          ),
          FastlaneCore::ConfigItem.new(
            key: :keystore_alias,
            env_name: "CORDOVA_ANDROID_KEYSTORE_ALIAS",
            description: "Android Keystore alias",
            is_string: true,
            default_value: ''
          ),
          FastlaneCore::ConfigItem.new(
            key: :build_number,
            env_name: "CORDOVA_BUILD_NUMBER",
            description: "Sets the build number for iOS and version code for Android",
            optional: true,
            is_string: false
          ),
          FastlaneCore::ConfigItem.new(
            key: :browserify,
            env_name: "CORDOVA_BROWSERIFY",
            description: "Specifies whether to browserify build or not",
            default_value: false,
            is_string: false
          ),
          FastlaneCore::ConfigItem.new(
            key: :cordova_prepare,
            env_name: "CORDOVA_PREPARE",
            description: "Specifies whether to run `ionic cordova prepare` before building",
            default_value: true,
            is_string: false
          ),
          FastlaneCore::ConfigItem.new(
            key: :min_sdk_version,
            env_name: "CORDOVA_ANDROID_MIN_SDK_VERSION",
            description: "Overrides the value of minSdkVersion set in AndroidManifest.xml",
            default_value: '',
            is_string: false
          ),
          FastlaneCore::ConfigItem.new(
            key: :cordova_no_fetch,
            env_name: "CORDOVA_NO_FETCH",
            description: "Call `cordova platform add` with `--nofetch` parameter",
            default_value: false,
            is_string: false
          ),
          FastlaneCore::ConfigItem.new(
            key: :cordova_no_resources,
            env_name: "CORDOVA_NO_RESOURCES",
            description: "Call `cordova platform add` with `--no-resources` parameter",
            default_value: false,
            is_string: false
          ),
          FastlaneCore::ConfigItem.new(
            key: :build_flag,
            env_name: "CORDOVA_IOS_BUILD_FLAG",
            description: "An array of Xcode buildFlag. Will be appended on compile command",
            is_string: false,
            optional: true,
            default_value: []
          ),
          FastlaneCore::ConfigItem.new(
            key: :cordova_build_config_file,
            env_name: "CORDOVA_BUILD_CONFIG_FILE",
            description: "Call `ionic cordova compile` with `--buildConfig=<ConfigFile>` to specify build config file path",
            is_string: true,
            optional: true,
            default_value: ''
          )
        ]
      end

      def self.output
        [
          ['CORDOVA_ANDROID_RELEASE_BUILD_PATH', 'Path to the signed release APK or AAB if it was generated'],
          ['CORDOVA_IOS_RELEASE_BUILD_PATH', 'Path to the signed release IPA if it was generated']
        ]
      end

      def self.authors
        ['Jan Piotrowski']
      end

      def self.is_supported?(platform)
        true
      end

      def self.example_code
        [
          "ionic(
            platform: 'ios'
          )",
          "ionic(
            platform: 'android',
            keystore_path: './staging.keystore',
            keystore_alias: 'alias_name',
            keystore_password: 'store_password'
          )"
        ]
      end

      def self.category
        :building
      end
    end
  end
end

0개의 댓글