Section 9/181 menit
9. Fastlane: Automasi Deployment
9. Fastlane: Automasi Deployment
Fastlane mengotomasi sertifikat, build, test, screenshot, dan upload ke App Store.
swift
# Install
gem install fastlane
# Setup
cd MyApp
fastlane init
# → Pilih "Automate App Store distribution"
Fastfile: Definisi Lanes
swift
# fastlane/Fastfile
default_platform(:ios)
platform :ios do
# Shared setup — dijalankan sebelum setiap lane
before_all do
ensure_git_status_clean # gagal jika ada uncommitted changes
cocoapods if File.exist?("Podfile")
end
# Lane: run tests
desc "Run unit dan UI tests"
lane :test do
run_tests(
project: "MyApp.xcodeproj",
scheme: "MyApp",
devices: ["iPhone 15 Pro"],
clean: true,
output_directory: "fastlane/test_output",
output_types: "html,junit"
)
end
# Lane: build untuk internal testing
desc "Build dan upload ke TestFlight (beta)"
lane :beta do
# Sync certificates dari git repo privat
match(
type: "appstore",
app_identifier: "com.mycompany.myapp",
readonly: is_ci # di CI: hanya baca, tidak buat baru
)
# Bump build number otomatis
increment_build_number(
build_number: latest_testflight_build_number + 1
)
# Build
gym(
scheme: "MyApp",
configuration: "Release",
export_method: "app-store",
output_directory: "./build",
include_symbols: true,
include_bitcode: false
)
# Upload ke TestFlight
pilot(
skip_waiting_for_build_processing: true,
changelog: last_git_commit[:message]
)
# Commit build number change
commit_version_bump(
message: "Bump build number [skip ci]",
force: true
)
push_to_git_remote
end
# Lane: full release ke App Store
desc "Submit ke App Store untuk review"
lane :release do
match(type: "appstore", readonly: true)
# Pastikan version number sudah diupdate
version = get_version_number(target: "MyApp")
UI.confirm("Release version #{version}?")
gym(scheme: "MyApp", configuration: "Release")
deliver(
submit_for_review: true,
automatic_release: false,
force: true,
metadata_path: "./fastlane/metadata",
screenshots_path: "./fastlane/screenshots",
skip_binary_upload: false
)
end
# Lane: generate screenshots
desc "Generate App Store screenshots otomatis"
lane :screenshots do
capture_screenshots(
scheme: "MyAppUITests",
devices: [
"iPhone 15 Pro",
"iPhone SE (3rd generation)",
"iPad Pro (12.9-inch) (6th generation)"
],
languages: ["id-ID", "en-US"],
output_directory: "./fastlane/screenshots",
clear_previous_screenshots: true
)
frame_screenshots(
white: false,
path: "./fastlane/screenshots"
)
end
after_all do |lane|
slack(
message: "Lane #{lane} berhasil!",
channel: "#ios-builds"
) if is_ci
end
error do |lane, exception|
slack(
message: "Lane #{lane} gagal: #{exception.message}",
channel: "#ios-builds",
success: false
) if is_ci
end
end
Match: Manage Certificates & Profiles
swift
# fastlane/Matchfile
git_url("https://github.com/myorg/ios-certificates.git")
git_branch("main")
storage_mode("git")
type("appstore") # development, adhoc, appstore, enterprise
app_identifier([
"com.mycompany.myapp",
"com.mycompany.myapp.widget",
"com.mycompany.myapp.notification-service"
])
team_id("ABCDEF1234")
swift
# Pertama kali: setup certificates (developer yang punya Apple Developer access)
fastlane match appstore --generate_apple_certs
# CI/CD: read-only
fastlane match appstore --readonly
# Nuke & regenerate semua (jika ada masalah)
fastlane match nuke development
fastlane match development