概要
appstoreおよびplay storeにデプロイを自動化するコマンドを定義できます。
弊社環境では同じプロジェクトにios,android両方のアプリを設定しているため、同時に設定しています。
fastlaneの環境変数設定
fastlane/.env または、 fastlane/.env.defaultに設定するとfastlane実行時に読まれます。
以下例。
FASTLANE_USER=
FASTLANE_PASSWORD=
FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD=
SLACK_URL=
MATCH_PASSWORD=
FASTLANE_SESSION=
ENV=
上記はAppleの二段階認証などに使われるパラメータなどを設定しています。
fastlaneを使うと証明書発行とbuildおよび、TestFlightおよび、App Store Connectのコードuploadまでの処理を自動化できます。
手っ取り早く設定のtemplateは以下のように作成しています。
以下の例ではデプロイ失敗に備えて、increment_version_numberとcommitの順番を制御できるように設定していますが書き方は自由です。
build versionはアプリがappstore connectにアップロードされている場合は同じbuild versionでコードをあげられなくるため、incrementし続けるようにしていますが、versionの更新と同時に1に戻すようにしたりもできます。
fastlane_version '2.129.0'
default_platform :ios
before_all do |lane|
ensure_git_branch(branch: '(develop|release|\d{0,4}\.\d{0,4}\.\d{0,4})')
ensure_git_status_clean
git_pull
if lane == :release or lane == :beta
ENV["ENV"] = 'production'
elsif lane == :appcenter
ENV["ENV"] = 'staging'
else
ENV["ENV"] = 'development'
end
end
platform :ios do
# iOS Lanes
desc 'Fetch certificates and provisioning profiles'
lane :certificates do |options|
if ENV["ENV"] == 'production'
match(app_identifier: 'jp.sample.app', type: 'appstore', readonly: true)
elsif ENV["ENV"] == 'staging'
match(app_identifier: 'jp.sample.staging.app', type: 'adhoc',)
else
match(app_identifier: 'jp.sample.app', type: 'development')
end
end
desc 'Build each Scheme'
lane :build do |options|
Dir.chdir("../") do
# code here runs in the parent directory
sh('./appcenter-pre-build.sh')
end
cocoapods(
podfile: "./ios/Podfile"
)
certificates
if ENV["ENV"] == 'production'
gym(scheme:'sample-production', workspace:'./ios/sample.xcworkspace',export_method: "app-store")
elsif ENV["ENV"] == 'staging'
gym(scheme:'sample-staging', workspace:'./ios/sample.xcworkspace',export_method: "ad-hoc")
else
gym(scheme:'sample-development', workspace:'./ios/sample.xcworkspace',export_method: "development")
end
increment_build_number(xcodeproj: './ios/sample.xcodeproj')
end
desc 'deploy to TestFlight'
lane :beta do |options|
build
commit_version_bump(message: 'success test flight commit', xcodeproj: './ios/sample.xcodeproj')
pilot
push_to_git_remote
end
desc 'deploy to app store connect'
lane :release do |options|
build
unless options[:no_version_up]
if options[:version]
increment_version_number(
version_number: options[:version],
xcodeproj: './ios/sample.xcodeproj'
)
else
bump_type = options[:bump_type] || 'minor'
increment_version_number(bump_type: bump_type, xcodeproj: './ios/sample.xcodeproj')
end
commit_version_bump(message: 'release commit', xcodeproj: './ios/sample.xcodeproj')
end
deliver
end
end
platform :android do
# Android Lanes
# Android Lanes
desc "Deploy a new version to the Google Play"
lane :release do |options|
gradle(task: 'clean', project_dir: 'android/')
increment_version(options)
gradle(task: 'bundle', build_type: 'Release', project_dir: 'android/')
supply(package_name: 'jp.sample.app',track: 'beta', track_promote_to: 'beta', skip_upload_apk: true)
git_commit(path: './android/*', message: "upload aab google play")
push_to_git_remote
end
desc "version increment"
lane :increment_version do |options|
# bump_type: major,minor,patch
gradle(task: 'incrementVersion', properties: { version_number: options[:version_number], bump_type: options[:bump_type] }, project_dir: 'android/')
end
end
after_all do |lane|
slack(
success: true,
channel: 'fastlane',
message: "#{lane} has suceeded."
)
end
error do |lane, exception, options|
if options[:debug]
puts "some output"
else
slack(
success: false,
channel: 'fastlane',
message: "#{lane}:#{exception.to_s} :\n#{exception.backtrace}"
)
end
end
appcenter-pre-build.shはAppcenterでbuildの初期設定を行なっている、自前のスクリプトを使いまわして実行しています。このように任意の設定processを組み込めます。
次に、Appfileで、アプリの情報とアプリをビルドするApple IDアカウントの情報を設定しておきます。
app_identifier "jp.sample.app" # The bundle identifier of your app
apple_id "hoge@example.com" # Your Apple email address
team_id "fugfuga" # Developer Portal Team ID
for_platform :ios do
app_identifier "jp.sample.debug.app"
for_lane :release do
app_identifier "jp.sample.app"
end
for_lane :beta do
app_identifier "jp.sample.app"
end
end
matchファイルはコマンド実行時に自動で生成されます。
既存の証明書を使いたい場合やエフェメラルに使いたくない場合は、certとsighを使うと、mathの代用ができます。
git_url("git@github.com:hoge/samplerepo.git")
type("development") # The default type, can be: appstore, adhoc, enterprise or development
# app_identifier(["tools.fastlane.app", "tools.fastlane.app2"])
# username("user@fastlane.tools") # Your Apple Developer Portal username
# For all available options run `fastlane match --help`
# Remove the # in the beginning of the line to enable the other options
Android
ぶっちゃけgradleのビルドタスクが同じ役割を果たすので、fastlaneで設定しなくても良いのですが、デプロイのメンテ性の向上やgitへのコミットpushをiOSと管理を共通化する程度の利用目的で使っています。
service accoutの登録
以下の手順を実行して、service accoutを取得したのちにAppfileに適応します。
json_key_file "./fastlane/example.service-account.json"
androidはincrement versionのapiが存在しないので、自前で実装する。
以下はgradle.propertiesからversionNameとversionCodeを取得し、global変数にexportするコード。
def setVersion(bump_type) {
def versionNums = VERSION_NAME.split('\\.')
def result = VERSION_NAME
println(versionNums.length)
println(VERSION_NAME)
switch (bump_type) {
case 'patch':
versionNums[2] = (Integer.parseInt(versionNums[2]) + 1).toString()
result = versionNums.join('.')
break
case 'minor':
versionNums[1] = (Integer.parseInt(versionNums[1]) + 1).toString()
result = versionNums.join('.')
break
case 'major':
versionNums[0] = (Integer.parseInt(versionNums[0]) + 1).toString()
result = versionNums.join('.')
break
default:
break
}
result
}
task('incrementVersion') {
description= "Increments Version"
doLast {
def versionCode = Integer.parseInt(VERSION_CODE) + 1
def versionName = version_number ?: setVersion(bump_type)
ant.propertyfile(file: "../gradle.properties") {
entry(key: "VERSION_CODE", value: versionCode)
entry(key: "VERSION_NAME", value: versionName)
}
}
}
以上のコードをapp/build.gradleから読み込む。
// ...略
apply from: './incrementVersion.gradle'
// ...略
defaultConfig {
//...
versionCode Integer.parseInt(VERSION_CODE)
versionName VERSION_NAME
}
これでbuildのgradleタスクを設定して呼び出すと、バージョン更新が適用されます。
supplyのパラメータを変えるとリリースプロセスを選べます。
その他補足
laneについて
fastlaneにおけるプロセスの単位。rubyのProc形式で拡張定義できる。
既存のlane
- cocoapods: pod install
- match: 証明書の取得及びsigning
- gym: ios appのビルド設定
- pilot: TestFlightへのuploade
- deliver: App Connect Storeへのuploade
- increment_build_number: xcode projectのビルド回数を変更する
- increment_version_number: Bundle versions string, shortのバージョン番号を変更する
- commit_version_bump: fastlaneの実行中に発生したdiffをコミットメッセージを指定してコミットしてくれる。