
fastlane ã䜿çšããã¢ãã€ã« ã¢ããªã®ç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³ãšããªããªãŒã«ã€ããŠã話ãããããšæããŸãããã¹ãŠã®ã¢ãã€ã« ã¢ããªã±ãŒã·ã§ã³ã« CI/CD ãå®è£
ããæ¹æ³ãããã«è³ããŸã§ã®çµç·¯ããããŠæçµçã«äœãèµ·ãã£ããã«ã€ããŠèª¬æããŸãã
åœåã¯äžè¶³ããŠããããŒã«ã«é¢ããè³æã¯ãã§ã«ã€ã³ã¿ãŒãããäžã«ããããããã®ã§ãããã§ã¯ãããŠããŒã«ã®è©³çްã«ã€ããŠèª¬æãããåœæç§ãã¡ãæã£ãŠãããã®ã«ã€ããŠã®ã¿èšåããŸãã
ãã®èšäºã¯ XNUMX ã€ã®éšåã§æ§æãããŠããŸãã
- äŒæ¥ã«ãããã¢ãã€ã«CI/CDã®ç»å Žã®èæ¯
- Nã¢ããªã±ãŒã·ã§ã³ãžã®CI/CDã®å±éã®ããã®æè¡ãœãªã¥ãŒã·ã§ã³
æåã®éšåã¯æãžã®æããããæãããããã®ã§ã2 çªç®ã®éšåã¯èªåèªèº«ã«é©çšã§ããäœéšã§ãã
æŽå²çã«ã¯ãããªã£ã
幎2015
ç§ãã¡ã¯ã¢ãã€ã«ã¢ããªã®éçºãå§ããã°ããã§ãç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³ãDevOpsããã®ä»ã®é«åºŠãªæè¡ã«ã€ããŠã¯äœãç¥ããŸããã§ãããã¢ããªã®ã¢ããããŒãã¯ãã¹ãŠéçºè
èªèº«ãèªåã®ãã·ã³ããè¡ã£ãŠããŸããã Android éåžžã«ã·ã³ãã«ã§ããåéã眲å .apk ãããŠããã Google Developer Console ã«æå
¥ããiOS ã®å Žå㯠Xcode çµç±ã®é
åžããŒã«ã§çŽ æŽãããå€ãéãããŸãããã¢ãŒã«ã€ããããŠã³ããŒãããããšãããšãšã©ãŒã§çµäºããããšãå€ããå詊è¡ããå¿
èŠããããŸãããæãåªããéçºè
ã¯æã«æ°åã³ãŒããæžãã®ã§ã¯ãªããã¢ããªã±ãŒã·ã§ã³ã®ãªãªãŒã¹ã«åŸäºããŠããããšãããããŸããã
幎2016
ç§ãã¡ã¯æé·ãããªãªãŒã¹ã®ããã«éçºè ãäžžäžæ¥è§£æŸããæ¹æ³ã«ã€ããŠãã§ã«èããŠããŸãããã2 çªç®ã®ã¢ããªã±ãŒã·ã§ã³ãç»å Žããèªååã«åããŠããã«åé²ããŸãããåã幎ã«ãç§ãã¡ã¯åã㊠Jenkins ãã€ã³ã¹ããŒã«ããfastlane ã®ããã¥ã¡ã³ãã«ç€ºãããŠãããã®ãšéåžžã«ãã䌌ããéãã¹ã¯ãªããã倧éã«æžããŸããã
$ 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ããŒã®ååä»ãã ããæç¢ºã«ãªããŸãã
ä»åã¯ãgym ãšçµã¿èŸŒã¿ã® xcpretty ãã©ãŒããã¿ã®ãããã§ããã«ã ãã°ãã¯ããã«æç¢ºã«ãªããŸãããããã«ãããå£ãããã«ããä¿®æ£ããæéãç¯çŽããããªãªãŒã¹ ããŒã ãç¬èªã«åé¡ã解決ã§ããå ŽåããããŸããã
æ®å¿µãªãããçµã¿ç«ãŠéåºŠã®æž¬å®ã¯ãããŸããã xcodebuild О gym ç§ãã¡ã¯ãããå®è¡ããŸããã§ããããããã¥ã¡ã³ããä¿¡é ŒããŸã - æå€§ 30% ã®å éã
ãã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ãåäžã®ããã»ã¹ã§å®è¡
2018幎çŸåš
2018 幎ãŸã§ã«ãã¢ããªã±ãŒã·ã§ã³ã®æ§ç¯ãšå±éã®ããã»ã¹ã¯å®å šã« Jenkins ã«ç§»è¡ããéçºè ã¯èªåã®ãã·ã³ããã®ãªãªãŒã¹ã忢ãããªãªãŒã¹ ããŒã ã®ã¿ããªãªãŒã¹æš©éãæã€ããã«ãªããŸããã
ç§ãã¡ã¯ãã§ã«ãã¹ããšéçåæã®èµ·åã埮調æŽããããšèããŠãããã¹ã¯ãªããã¯ã©ãã©ã倧ãããªã£ãŠãããŸãããç§ãã¡ã®ã¢ããªã±ãŒã·ã§ã³ãšãšãã«æé·ããå€åããŸããããã®æã®å¿åã¯10ä»¶ãããã§ããããã©ãããã©ãŒã ã 20 ã€ããããšãèãããšãçŽ XNUMX åã®ãã©ã€ããã¹ã¯ãªããã«ãªããŸãã
ã¹ã¯ãªããã«æ°ããã¹ãããã远å ãããã³ã«ããã¹ãŠã®ã·ã§ã« ã¹ã¯ãªããã«éšåãã³ããŒããŠè²Œãä»ããå¿ èŠããããŸããããããããã£ãšæ³šææ·±ãäœæ¥ããããšãå¯èœã ã£ãã®ã§ããããããããã倿Žã¯ãã°ãã°ã¿ã€ããã¹ã«çµããããªãªãŒã¹ ããŒã ãäœå€ããããŠã¹ã¯ãªãããä¿®æ£ãã誰ããã®ã³ãã³ãã远å ããã®ãããŸããã®ã³ãã³ããäœãããã®ãã調ã¹ãããšã«ãªããŸãããäžè¬ã«ã1 ã€ã®ãã©ãããã©ãŒã ã®ã¢ã»ã³ããªã®ã¹ã¯ãªãããäœããã®ç¹ã§é¡äŒŒããŠãããšã¯èšããŸããã確ãã«åœŒãã¯åãããšãããã®ã§ãã
æ°ããã¢ããªã±ãŒã·ã§ã³ã®ããã»ã¹ãéå§ããã«ã¯ããããã®ã¹ã¯ãªãããããæ°ãããããŒãžã§ã³ãéžæãããããã°ããŠãã¯ããåäœããŸãããšèšãã®ã« 1 æ¥ãè²»ããå¿ èŠããããŸããã
2018 幎ã®å€ãç§ãã¡ã¯ãŸã çºå±éäžã®ãã¡ã¹ãã¬ãŒã³ãæ¹ããŠèŠçŽããŸããã
ã¿ã¹ã¯1: ãã¹ãŠã®ã¹ã¯ãªããã¹ããããèŠçŽããFastfileã«æžãçŽã
äœæ¥ãéå§ããåœåãã¹ã¯ãªãã㯠Jenkins ã® 1 ã€ã®ã·ã§ã« ã¹ã¯ãªããã«ãã¹ãŠã®ã¹ããããšããã¯ãè©°ã蟌ãŸããæ··ä¹±ãããã®ã®ããã«èŠããŸããããŸã ãã€ãã©ã€ã³ãšã¹ããŒãžããšã®åå²ã«åãæ¿ããŠããŸããã
ç§ãã¡ã¯çŸç¶ã確èªããCI/CD ã®èª¬æã«é©åãã 4 ã€ã®ã¹ããããç¹å®ããŸããã
- ãã«ã - äŸåé¢ä¿ãã€ã³ã¹ããŒã«ããã¢ãŒã«ã€ãããã«ããã
- ãã¹ã - éçºè ãŠããããã¹ãã®å®è¡ãã«ãã¬ããžã®èšç®ã
- sonar â ãã¹ãŠã®ãªã³ã¿ãŒãèµ·åããSonarQubeã«ã¬ããŒããéä¿¡ããŸãã
- ããã〠- ææç©ãã¢ã«ãã¡ç (TestFlight) ã«éä¿¡ããŸãã
詳现ã«ç«ã¡å ¥ãããã¢ã¯ã·ã§ã³ã§äœ¿çšãããããŒãçç¥ãããšã次ã®ãã㪠Fastfile ãäœæãããŸãã
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å®éããŸã å¿ èŠãªããã¯ãã眮ãæãããããã©ã¡ãŒã¿ã®æ°ãèãããšãæåã® Fastfile ã¯ã¢ã³ã¹ã¿ãŒã®ãããªãã®ã«ãªã£ãŠããŸããŸããã
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äžèšã®äŸã§ã¯ãæå®ããå¿
èŠããããã©ã¡ãŒã¿ã¯ããã«ããã©ã¡ãŒã¿ïŒã¹ããŒã ãæ§æãããããžã§ãã³ã°ãããã¡ã€ã«åïŒãšé
åžãã©ã¡ãŒã¿ïŒéçºè
ã¢ã«ãŠã³ãã® Apple IDããã¹ã¯ãŒããã¢ããªã±ãŒã·ã§ã³ ID ãªã©ïŒã®ã¿ã§ããæåã®è¿äŒŒãšããŠããããã®ããŒããã¹ãŠç¹å¥ãªãã¡ã€ã«ã«ä¿åããŸã - Gymfile, Matchfile О Appfile.
Jenkinsã§ã¯ããã¥ãŒãããŒãããããšãªãç®ã§èªã¿ãããçãã³ãã³ããåŒã³åºãããšãã§ããŸãã
# fastlane ios <lane_name>
$ fastlane ios build
$ fastlane ios test
$ fastlane ios run_sonar
$ fastlane ios deployãã£ããŒãé 調ã ãïŒ
äœãããããŸãããïŒãã¹ãŠã®ã¹ãããã®æç¢ºãªã³ãã³ãããã¡ããšããã¹ã¯ãªããããFastlane ãã¡ã€ã«ã«ãã¡ããšã¬ã€ã¢ãŠããããŠããŸããç§ãã¡ã¯å€§åã³ããŠãå¿ èŠãªãã®ããã¹ãŠãªããžããªã«è¿œå ããããéçºè ã«äŸé ŒããŸããã
ãããããããŠç§ãã¡ã¯åãå°é£ã«çŽé¢ããã ãããšèªèããŸãããã€ãŸããäŸç¶ãšã㊠20 åã®ãã«ã ã¹ã¯ãªãããããããç¬èªã®åäœãéå§ããã¹ã¯ãªããããªããžããªã«ç§»åãããŠã¢ã¯ã»ã¹ã§ããªããªããããç·šéãããã«å°é£ã«ãªããšããããšã§ãããããŠãäžè¬çã«ããã®æ¹æ³ã§ç§ãã¡ã®èŠçã解決ããããšã¯äžå¯èœã§ãããã

ã¿ã¹ã¯ #2: N åã®ã¢ããªã±ãŒã·ã§ã³ã«å¯ŸããŠåäžã® Fastfile ãååŸãã
ä»ã§ã¯ãåé¡ã解決ããã®ã¯ããã»ã©é£ãããªãããã§ãã倿°ãèšå®ããŠãå§ããŸããããã¯ããå®éç§ãã¡ã¯ãã®ããã«ããŠåé¡ã解決ããŸããããããããããå®è£ ããŠããåœæã¯ãfastlane èªäœã®å°éç¥èããfastlane ãèšè¿°ãããŠãã Ruby ã®å°éç¥èããWeb äžã®æçšãªäŸããããŸããã§ãããåœæ fastlane ã«ã€ããŠæžãã人ã¯çã1 人ã®éçºè åãã® 1 ã€ã®ã¢ããªã±ãŒã·ã§ã³ã®äŸã«éå®ããŠããŸããã
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.
ãããŠãç§ãã¡ã¯ãã®ã©ã€ãã©ãªãå°ãéã£ãæ¹æ³ã§äœ¿çšããããšã«ããŸãããéçºè
ã®ãªããžããªã«ã¯ãFastlaneã®ã¹ã¯ãªãããšãã®ã¡ã¿æ
å ±ã§ã¯ãªãããã®ã¢ããªã±ãŒã·ã§ã³ã®äžæã®ããŒããã¡ã€ã«ã«æ ŒçŽããŸãããã .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.
ãªãªãŒã¹ ããŒã ãæ°ããã¹ãããã远å ãããå Žåãã¹ã¯ãªããã®å€æŽã¯ git ã® MR ãä»ããŠèšé²ããããããå£ããã¹ã¯ãªããã®åå ãæ¢ãå¿ èŠããªããªããäžè¬çã«ãä»ããã«ãããå£ãã«ã¯ã詊ããŠã¿ãå¿ èŠããããŸãã
ããã§å šãŠã¯ç¢ºå®ã
以åã¯ããã¹ãŠã®ã¹ã¯ãªããã®ä¿å®ãæŽæ°ãããã³æŽæ°ã«ãããã¹ãŠã®çµæã®ä¿®æ£ã«æéãè²»ãããŠããŸããããšã©ãŒããªãªãŒã¹ã®ããŠã³ã¿ã€ã ã®åå ããã·ã§ã« ã¹ã¯ãªããã®æ··ä¹±ã®äžã§è¿œè·¡ããã®ãéåžžã«å°é£ãªåçŽãªã¿ã€ããã¹ã§ãã£ããšãã¯ãéåžžã«ã€ã©ã€ã©ããŸãããçŸåšã§ã¯ããã®ãããªãšã©ãŒã¯æå°éã«æããããŠããŸãã倿Žã¯ãã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ã«äžåºŠã«å±éãããŸãããŸããããã»ã¹ã«æ°ããã¢ããªã±ãŒã·ã§ã³ã远å ããã«ã¯ãCI ã§ãã³ãã¬ãŒã ãã€ãã©ã€ã³ãèšå®ããéçºè ãªããžããªã«ããŒã远å ããã ãã§ 15 åããããŸãã
Fastfileã«é¢ãããã€ã³ãã¯æªã ã«èª¬æãããŠããªãããã§ãã Android ãããŠãã¢ããªã±ãŒã·ã§ã³ã®çœ²åã«ã€ããŠãè§ŠããŠããŸãããã®èšäºã奜è©ã§ããã°ãç¶ç·šãå·çããŸãããã®åé¡ã®è§£æ±ºçã«ã€ããŠãã質åããææ¡ããããŸããããã³ã¡ã³ãæ¬ãŸãã¯Telegramã«ãŠãå¯ããã ããã .
åºæïŒ habr.com
