
แแฃแ แแ แ แแ แแ แตแแแฃแญแ แ แแแฌแฝแแฝ แตแ แแฃแญ แแ
แฐแต แฅแ แแตแจแต แแแซแต แฅแแแแแแข แ แแแ แจแแฃแญแ แ แแแฌแฝแแฝ แแญ CI/CD แฅแแดแต แฅแแฐแแแฐแแฅแจแแฃ แฅแแดแต แฅแแฐแฐแจแตแ แฅแ แ แแจแจแป แแ แฅแแฐแฐแแ แจแข
แ แแณแชแซแ แแญ แ แ แแณแจ แแจแก แแญ แแตแแแ แ แ แแณแแต แ แ แฃ แฅแ แแแแชแซ แแญ แจแแฐแแ แฃ แตแแแแ แแฃแชแซแแ แแ แฅแฌ แ แแญแแญ แ แแแแฝแ แฃ แแ แซแ แซแแแ แฅแป แฅแ แ แณแแ แข
แฝแแ แแแต แญแแแฝแ แซแแ แแ-
- แ แฉแฃแแซแ แแตแฅ แจแแฃแญแ CI / แฒแฒ แแจแฐแต แณแซ
- แแคแ-แแฐแแ แชแซแแฝ CI/CD แ แแแแแ แดแญแแซแ แแแตแ
แจแแแแชแซแ แญแแ แแ แฎแแ แแแต แจแ แแ แแแแต แแ, แแแฐแแ แฐแแ แแซแตแ แแแแจแต แจแแฝแแต แแแต แแ.
แ แณแชแญ แฅแแฒแ แแ
2015 แ.แ
แจแแฃแญแ แแฐแแ แชแซแแฝแ แแแแแต แแแจแ แแ แญแฃ แฅแ แตแ แแฃแญแแต แซแแ แแ
แฐแตแฃ DevOps แแญแ แแแฝ แตแแ
แแแฎแฝ แแแ แจแแแแแ แแแญ แจแแแข แฅแซแแณแแฑ แจแแฐแแ แชแซ แแแ แ แแแขแ แซแฑ แจแซแฑ แแฝแ แฐแแแแข แฅแ แ Android แ แฃแ แแแ แแ - แฐแฐแฅแตแฆแฃ แฐแแญแแ .apk แฅแ แแฐ แแแ แแแข แฎแแถแ แฐแ
แแ แจแ แแ แญแฆแคแต แจแแซแ แแ แ Xcode แแจแแแซ แแณแชแซ แฅแฉ แแฝแถแฝแ แตแถแแแ - แแ
แฐแฉแ แแแแจแต แจแฐแฐแจแแ แแจแซ แฅแ แแ แ แตแ
แฐแต แซแ แแ แฅแ แฅแแฐแแ แแแจแญ แแ แจแฅแแข แ แฃแ แจแแ แแแข แ แแญ แแตแฅ แฅแ แแ แฎแต แ แญแฝแแ แฃ แญแแแแ แแฐแแ แชแซแแ แญแแแแแข
2016 แ.แ
แ แฐแแ แฃ แแแขแแฝแ แแแแต แแ แแ แฅแแดแต แแ แแตแจแ แฅแแฐแแแฝแ แ แตแแตแแ แ แตแ แ แแ แญ แฃ แฅแ แแแฐแ แแฐแแ แชแซ แฅแแฒแ แณแจ แฃ แญแ แ แจแ แแ แแฐ แ แแถแแฝแ แฅแป แแแแข แ แแซแ แแแตแฃ แแแแแชแซ แแ แแแชแแตแ แซแแ แฅแ แแตแตแแ แ แฐแแฑ แแตแฅ แจแแซแณแจแ แแญ แฐแแณแณแญ แจแแ แ แตแแช แตแญแชแแถแฝแ แปแแแข
$ xcodebuild clean archive -archivePath build/MyApp
-scheme MyApp
$ xcodebuild -exportArchive
-exportFormat ipa
-archivePath "build/MyApp.xcarchive"
-exportPath "build/MyApp.ipa"
-exportProvisioningProfile "ProvisioningProfileName"
$ cd /Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/
$ ./altool โupload-app
-f {abs path to your project}/build/{release scheme}.ipa
-u "appleId@example.com"
-p "PASS_APPLE_ID"แฅแแฐ แ แแแณแฐแ แแ แฅแตแจ แ แแ แตแจแต แจแฅแ แแแขแแฝ แฅแป แฅแแแ แตแญแชแแถแฝ แฅแแดแต แฅแแฐแแ แฉ แฅแ แแแ แญแ แแแแซ แจแแแ แจแแแ แแแ แฅแแฐแแซแตแแแ แซแแ แแ แญแฃ แฅแ แจแแ แแแญ แฅแแฐแแ แฒแฐแ แญแฃ แแแแฆแฝแ แแแฐแแฐแ โแ แแฎแฝ แแฝแถแฝโ แ แแแฐแแแข
2017 แ.แ
แ แแ แ แแต แแตแตแแญแ แจแแฃแ แแแญ แฅแแณแ แฐแแจแแแข แ แแ แซแแแ แซแ แ แฅแ แแจแ แ แแแ แจแ - แฅแแดแต แฅแแฐแแแแญ แฃ แฅแแดแต แฅแแฐแแ แแแ แตแข แฅแ แแณแชแซแ แ แแ แแ แแ แซแแ แฐแ แแ แญแก แจแแซแแญแฅ แตแ แฐแถแฝ แฅแแ แ แณแแแ แฅแ แแ แ แแกแต แ แตแแณแ แ แแถแแฒแญ แแแ แจแฃแต แแ แญแข
แแแ แแ, แ fastlane แฎแญ แแตแฅ แจแฐแซแฐแฑแต แแ แแ แแแแแซแแฝ แแธแ gym ะธ pilot, แแแแแญ แฝแแแ.
แจแฅแ แตแญแชแแถแฝ แตแแฝ แฐแปแฝแแแแข
$ fastlane gym โ-workspace "Example.xcworkspace"
--scheme "AppName"
โ-buildlog_path "/tmp"
-โcleanแแแ แ แตแแแ แแแชแซแแฝ แตแแแแ แฅแป แฐแปแฝแแแ xcodebuildแแแแจแต แซแตแแแแแณแ - gym แจแต แฅแ แแ แฅแแณแ แ แแ แญแแแแฃแแข แฅแ แแ แแ แแตแฐแซแจแซแฃ แแญ แฅแแฐ แแตแฅ แซแ แฐแแณแณแญ แแแแฝแ แแแแฝ แญแฝแแแข xcodebuildแฃ แจแแแแน แตแซแ แฅแป แจแ แแ แแแ
แแแข
แ แแ แแแฃ แแแ แฅแ แ แฅแฎแแแฅ แจ xcpretty formatter แแตแแ แญแแฃแแ แจแแแฃแณ แแแแฅ แแตแณแแปแแฝ แจแ แแ แฐแแฃแข แแแแแข แญแ แจแฐแ แแน แตแฅแฐแฃแแฝแ แแแตแฐแซแจแ แแแ แแแ แฅ แแแจ แฅแ แ แแณแแต แแ แจแฐแแแแ แกแตแ แ แซแฑ แแแแแ แ แญแฝแแแข
แฅแแฐ แ แแแณแฐแ แแ แจแแฐแฅแฐแขแซ แแฅแแต แแแชแซแแฝ xcodebuild ะธ gym แฅแ แ แแฐแจแแแแแฃ แแแญ แแ แฐแแถแนแ แฅแแแแแ - แฅแตแจ 30% แแฅแแตแข
แแ แ แแฐแต แแแแ แแฐแแ แชแซแแฝ
2018 แฅแ แ แแ
แฅ.แค.แ . แ 2018 แฃ แแฐแแ แชแซแแฝแ แจแแแแฃแต แฅแ แจแแฐแซแจแต แแฐแต แแ แ แแ แแฐ แแแชแแต แฐแแแฏแ แฃ แแแขแแฝ แจแแฝแแปแธแ แแแแ แ แแ แฅแ แจแแแแแซ แกแตแ แฅแป แจแแแแ แแฅแต แแ แจแแข
แ แตแแตแแ แจแแฐแแแฝแ แแแแญ แฅแ แจแแญแแแณแแต แตแแณแ แแปแปแ แฅแแแแแแแฃ แฅแ แจแฅแ แตแญแชแแถแฝ แ แฐแ แฅแ แ แฐแแข แจแแฐแแ แชแซแแปแฝแ แแญ แ แฐแ แฅแ แฐแแแงแแข แ แแซแ แแ แแฐ 10 แจแแ แ แแฐแแ แชแซแแฝ แแ แฉ. แแแต แแตแจแฎแฝ แฅแแณแแ แแแต แแตแฅ แ แแตแแฃแต 20 แซแ แ "แแซแ" แตแญแชแแถแฝ แแธแ.
แแฐ แตแญแชแแฑ แ แฒแต แฐแจแ แแแจแแญ แ แแแแ แแฅแญ แแญแฅแซแฎแนแ แแฐ แแแ แจแผแ แตแญแชแแถแฝ แแ แณแต แแ แจแฅแแข แแแแฃแต แจแ แแ แ แฅแแแ แแแฐแซ แฅแแฝแ แแ แญแฃ แแแญ แแ แฅแ แแ แฅแแฐแแ แ แญแแต แแแฆแฝ แ แ แปแปแ แตแแต แ แฅแ แฐแแแฃ แญแ แ แแฐแแแแ แกแตแ แตแญแชแแถแฝแ แแแตแฐแซแจแ แฅแ แจแตแแ แฅแแ แฐแ แญแ แ แตแฅแแ แฅแแฐแจแแจ แฅแ แแ แฅแแฐแแฐแซ แแแแ แแฐ แแฝแต แฐแแแ แข แ แ แ แแแญ แแ แแต แแตแจแญ แจแแฐแฅแฐแขแซ แตแญแชแแถแฝ แขแซแแต แ แฐแแฐแ แแแฉ แฐแแณแณแญ แแ แฉ แแแต แ แญแปแแแข แแแ แฅแแณแ แ แฅแญแแ แแแต แฐแแณแณแญ แแแญ แขแซแฐแญแแ.
แแ แฒแต แ แแแฌแฝแ แแฐแต แแแแแญ แจแฅแแแ แ แตแญแชแแถแฝ โแตแฉแตโ แตแชแต แแแแจแฅ แ แแต แแ แแณแแแฃ แแจแ แฅแ โแ แ แญแฐแซแโ แแแต แ แตแแแ แแ แญแข
แฅ.แค.แ . แ 2018 แจแ แ แแ แตแฃ แ แแแ แ แแฐแ แแญ แแณแแ แจแแตแตแแ แ แ แฃแซ แฅแแฐแแ แฐแแแจแตแแข
แฐแแฃแญ #1แก แแแแ แจแตแญแชแแต แฐแจแแแฝ แ แ แแ แ แตแญแแ แ Fastfile แแตแฅ แแแธแ
แตแแแแญแฃ แจแฅแ แตแญแชแแถแฝ แ แแแชแแต แแตแฅ แ แ แแต แจแผแ แตแญแชแแต แแตแฅ แซแแตแ แแแแ แฐแจแแแฝ แฅแ แญแซแแฝ แซแแ แจแฅแแญ แแฅแต แญแแตแ แแ แญแข แฅแตแซแแ แแฐ แงแแง แแตแแญ แฅแ แ แฐแจแ แญแแแ แ แแแจแญแแแข
แซแแแ แฐแแแญแฐแแ แฅแ แจแฒแ แญแค/แฒแฒ แแแแซ แแญ แจแแตแแ 4 แฐแจแแแฝแ แแญแฐแแแข
- แแแแฃแต - แฅแแแแฝแ แแซแ, แแ แฐแฉแ แแฐแฅแฐแฅ,
- แแจแซ - แจแแแข แญแแ แแจแซแแฝแ แแซแแต แฃ แฝแแแ แแตแแต แฃ
- sonar - แแแแ แแแฐแฎแฝแ แซแตแแณ แฅแ แชแแญแถแฝแ แแฐ SonarQube แญแแซแ แฃ
- แแฐแแซแต - แ แญแต แแฐ แ แแ (แจแแจแซ แ แจแซ) แแแญแข
แฅแ แ แตแญแแต แแตแฅ แฅแ แ แแญ แจแแแตแ แแแแฝ แ แแฐแ แแฐ แแญแแฎแฝ แซแแแฃแ แญแ แ แแฃแ แแญแ แณแแแแ แก-
default_platform(:ios)
platform :ios do
before_all do
unlock
end
desc "Build stage"
lane :build do
match
prepare_build
gym
end
desc "Prepare build stage: carthage and cocoapods"
lane :prepare_build do
pathCartfile = ""
Dir.chdir("..") do
pathCartfile = File.join(Dir.pwd, "/Cartfile")
end
if File.exist?(pathCartfile)
carthage
end
pathPodfile = ""
Dir.chdir("..") do
pathPodfile = File.join(Dir.pwd, "/Podfile")
end
if File.exist?(pathPodfile)
cocoapods
end
end
desc "Test stage"
lane :test do
scan
xcov
end
desc "Sonar stage (after run test!)"
lane :run_sonar do
slather
lizard
swiftlint
sonar
end
desc "Deploy to testflight stage"
lane :deploy do
pilot
end
desc "Unlock keychain"
private_lane :unlock do
pass = ENV['KEYCHAIN_PASSWORD']
unlock_keychain(
password: pass
)
end
endแ แฅแแแฑแฃ แ แแแ แจแแแแแแธแแ แ แแณแแต แญแซแแฝ แฅแ แจแฐแซแแธแ แจแแแชแซแแฝ แฅแแต แแแต แแตแฅ แ แแตแแฃแต แจแแแแชแซแ แแตแตแแญแแฝแ แ แตแแช แแแข
lane :build do
carthage(
command: "update",
use_binaries: false,
platform: "ios",
cache_builds: true)
cocoapods(
clean: true,
podfile: "./Podfile",
use_bundle_exec: false)
gym(
workspace: "MyApp.xcworkspace",
configuration: "Release",
scheme: "MyApp",
clean: true,
output_directory: "/build",
output_name: "my-app.ipa")
end
lane :deploy do
pilot(
username: "appleId@example.com",
app_identifier: "com.example.app",
dev_portal_team_id: "TEAM_ID_NUMBER_DEV",
team_id: "ITS_TEAM_ID")
endแจแแญ แฃแแ แแณแ แแตแฅ แฅแ แแแแแฝแแธแ แจแแแกแ แจแแแชแซแแฝ แญแแ แฅแป แฅแแแ
แจแแแฃแณ แแแชแซแแฝ แแธแ - แแตแ แฃ แแ
แญ แฃ แจแ แ
แญแฆแต แแแแซ แตแแฝ แฃ แฅแแฒแแ แจแตแญแญแต แแแชแซแแฝ - แจแแแข แแแซ แ แแ แแณแแแซ แฃ แจแญแแ แแ แฃ แจแแฐแแ แชแซ แแณแแแซ แฅแ แจแแณแฐแแตแข แแญ แฅแแฐ แแแแชแซแ แแแต แฃ แฅแแแ
แ แแ แแแแฝ แ แแฉ แแญแแฝ แแตแฅ แฅแแตแแแฃแธแแแ - Gymfile, Matchfile ะธ Appfile.
แ แแ แ แแแชแแต แฅแญแณแ แจแแซแฐแ แแ แฅแ แ แแแ แ แ แญแ แแแ แก แจแแฝแ แ แซแญแญ แตแแแแฝแ แแฐแแ แญแฝแแ-
# fastlane ios <lane_name>
$ fastlane ios build
$ fastlane ios test
$ fastlane ios run_sonar
$ fastlane ios deployแแฌ แ แชแ แแ
แแ แ แแแ ? แแฅแซแแณแแฑ แฅแญแแ แตแแแแฝแ แซแฝแฑแข แจแธแฑ แตแญแชแแถแฝแฃ แ แแตแตแแญแ แแญแแฝ แแตแฅ แ แฅแฉ แแแณ แจแฐแฐแจแฐแฉแข แ แแฐแฐแตแฃ แแฐ แแแขแแน แจแแซแตแแแแธแแ แแ แแฐ แแจแแปแธแ แฅแแฒแจแแฉ แ แจแ แแธแแข
แแ แฐแแณแณแญ แฝแแฎแฝ แฅแแฐแแซแแฅแแ แ แแ แฐแแแแฅแ - แ แแแ แขแแ 20 แจแตแฅแฐแฃ แตแญแชแแถแฝ แญแแฉแแ แ แ แแตแ แแ แ แแ แแแแต แจแซแณแธแแ แแญแแต แแแซแต แญแแแซแ แฃ แตแญแชแแถแน แแฐ แแ แซแแแซแแฝ แตแแแแแแฉ แฅแแฑแ แแแจแ แจแ แแ แจแฃแต แญแแแ แข แฅแ แฅแแซ แแตแจแต แ แแปแแแแข แฅแ แ แ แ แแแญ แ แแแฝแแ แ แแ แแแแต แแแณแต แ แญแปแแแข

แฐแแฃแญ #2แก แแคแ แแฐแแ แชแซแแฝ แ แแต แแ แ แแฃแ แแญแ แซแแ
แ แแ แฝแแฉแ แแแณแต แ แฃแ แจแฃแต แ แญแฐแแ - แฐแแแแฎแฝแ แซแแแ แฅแ แฅแแแต แข แ แ, แ แฅแแแฑ, แฝแแฉ แจแฐแแณแ แ แแ แแแแต แแ. แแแญ แแ แฃแแณแแ แต แฐแ แต แ แซแฑ แ แแตแตแแญแ แแญแ แแตแตแแ แ แแแแ แต แ แฉแข แแตแฅแ แแ แ แแตแแญแฉ แแญ แ แแ แแณแแแฝ แจแแแแข แ แแต แแแข.
Fastlane แจแ แซแฃแข แฐแแแแฎแฝแ แแตแฐแแแต แญแฝแแแฃ แฅแ แญแ แแ แ แตแแตแแ แจ Keychain แญแแ แแ แ แแแแแต แแญแจแแแแก-
ENV['KEYCHAIN_PASSWORD']แจแฅแแ แตแญแชแแถแฝ แจแฐแแแจแตแ แ แแ แจแฐแแแฑ แญแแแฝแ แแญแฐแแ-
#for build, test and deploy
APPLICATION_SCHEME_NAME=appScheme
APPLICATION_PROJECT_NAME=app.xcodeproj
APPLICATION_WORKSPACE_NAME=app.xcworkspace
APPLICATION_NAME=appName
OUTPUT_IPA_NAME=appName.ipa
#app info
APP_BUNDLE_IDENTIFIER=com.example.appName
APPLE_ID=appleID@example.com
TEAM_ID=ABCD1234
FASTLANE_ITC_TEAM_ID=123456789แ แแแฃ แฅแแแ
แ แแแแฝ แ fastlane แแญแแฝ แแตแฅ แแ แแ แแแแแญแฃ แฅแแดแต แฅแแซ แแตแจแต แฅแแณแแฅแ แแแ
แแ แจแฅแแข Fastlane แแแ
แแแตแ แ แแแก- . แฐแแฑ แแฐแแซแฉ แแแแแฝ แแแแฝแ แแซแ แแฅแญแตแ แ แตแแแ แจแแ แ fastlane แแแซ แแตแฅ แฅแ แจแแ
แจแต แแญแแฝแ แญแแ แฉ แญแแแข .env, .env.default, .env.development.
แฅแ แจแแซ แญแ
แ แคแฐ-แแฝแแแต แตแแฝ แแจแต แฃแ แแแฉ แแแ แแ แแฐแแ. แ แแแขแแฝ แแจแแป แแตแฅ แจแแฃแ แตแญแชแแถแฝแ แฅแ แจแแณ แแจแแแ แณแญแแ แจแแ
แแฐแแ แชแซ แแฉ แแแแฝแ แ แแญแ แแตแฅ แฅแแตแแแฅ .env.appName.
แฅแซแณแธแแ Fastfile, Appfile, Matchfile ะธ Gymfile, แ แฐแแจ แแจแแป แแตแฅ แฐแ แ
แแ. แจแแแฝ แ แแแแแถแฝ แจแญแแ แแ แแแแฝ แซแแ แฐแจแแช แแญแ แฅแแซ แฐแฐแฅแแ - .env.
แ แแต แแณแ แแจแต แญแฝแแ .

แ CI แแญแฃ แฅแชแ แฅแแ แ แแฐแแแ แแค แแ แแต แจแฐแแฐแ แแฐแแ แชแซ แจแแแแชแซ แแแ แณแญแแแก-
# fastlane ios <lane_name> --env appName
$ fastlane ios build --env appName
$ fastlane ios test --env appName
$ fastlane ios run_sonar --env appName
$ fastlane ios deploy --env appNameแตแฅแแแนแ แจแแตแฌแตแ แ แแตแฃ แแจแแปแฝแแ แ แตแญแชแแต แฅแแญแแแแแข แ แฃแ แฅแฉ แ แญแแตแแ:
git clone git@repository.com/FastlaneCICD.git fastlane_temp
cp ./fastlane_temp/fastlane/* ./fastlane/
cp ./fastlane_temp/fastlane/.env fastlane/.envแแแ แฅแแณแ Fastlane Fastfile แ แ แ แฉแ แแแแจแต แแแตแ แขแแจแแ แญแ
แแ แแแตแ แแ แแ แฐแแแข import_from_git, แแ แ Fastfile แฅแป แแ แจแแฐแซแ, แแ แแแแฝ แแญแแฝ แ แญแฐแแ. "แ แฅแญแแฅ แแแ" แจแแแ, แจแซแตแแ แแปแ แญแฝแแ action.
แฐแแณแณแญ แตแฅแตแฅ แฐแแแ
แทแ แ Android แแฐแแ แชแซแแฝ แฅแ ReactNativeแฃ แแญแแน แ แฐแแณแณแญ แแจแแป แแตแฅ แแธแแฃ แแ แ แฐแแซแฉ แ
แญแแซแแฝ แแตแฅ แแธแ iOS, android ะธ react_native.
แจแฐแแแแ แกแตแ แ แฒแต แฅแญแแ แแแจแแญ แฒแแแ แ แตแญแชแแฑ แแญ แจแฐแฐแจแ แแแฆแฝ แ MR in git แ แฉแ แญแแแแฃแ แฃแจแฐแ แแน แตแญแชแแถแฝแ แแแแแแฝ แแแแ แ แซแตแแแแ แฃ แฅแ แ แ แ แแแญ แฃ แ แแ แฅแฑแ แแแตแ แญ แแแจแญ แ แแฅแแตแข
แ แแ แซ แฅแญแแ แ แแแข
แจแแ แแฐแ แแแแ แตแญแชแแถแฝ แ แแ แ แ แฃ แ แแแแ แฅแ แแแแ แจแแแแแฝ แแแ แแแตแฐแซแจแ แแ แ แณแแแแแข แจแตแ แฐแถแฝ แฅแ แจแแแแแซ แแแแฝ แแญแแซแถแฝ แ แผแ แตแญแชแแถแฝ แแตแฅ แแแจแณแฐแ แ แฃแ แ แตแธแแช แจแแ แแแ แจแแฐแ แตแ แฐแถแฝ แฒแแ แ แฃแ แฐแตแ แ แตแแซแญ แแ แญแข แ แแ แฅแแฐแแ แซแ แตแ แฐแถแฝ แ แตแแน แญแแแณแ. แแแฆแฝ แ แ แแต แแ แแแแ แแฐแแ แชแซแแฝ แญแแแแแข แฅแ แ แแฐแฑ แแตแฅ แ แฒแต แแฐแแ แชแซแ แแแตแแฃแต 15 แฐแแแแฝแ แญแแตแณแ - แจแ แฅแแต แงแแง แแตแแญ แ CI แแญ แซแแแ แฅแ แแแแฝแ แแฐ แแแขแ แแจแแป แซแญแแข
แจFastfile แแฅแฅ แฅแตแซแแ แซแแฐแฅแซแซ แญแแตแแแข Android แฅแ แจแ แแแฌแฝแแน แแญแแข แฝแแ แ แตแฐแณแฝ แจแแแฃ แฐแจแณแญ แฝแแ แฅแฝแแแแข แญแ แแ แฝแแญ แฅแแดแต แฅแแฐแแแฑ แฅแซแแแฝแแ แแญแ แ แตแฐแซแจแถแฝแแ แ แ แตแฐแซแจแถแฝ แแญแ แ แดแแแซแ แแญ แแตแแต แฅแแแแแแข .
แแแญ: hab.com
