fastlane ã䜿çšããã¢ãã€ã« ã¢ããªã®ç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³ãšããªããªãŒã«ã€ããŠè©±ããããšæããŸãããã¹ãŠã®ã¢ãã€ã« ã¢ããªã±ãŒã·ã§ã³ã« CI/CD ãå®è£
ããæ¹æ³ãããã«è³ããŸã§ã®çµç·¯ããããŠæçµçã«äœãèµ·ãã£ããã
ãã®ããŒã«ã«ã€ããŠã¯ãããã¯ãŒã¯äžã«ãã§ã«ååãªè³æããããŸãããåœåã¯ãããäžè¶³ããŠããã®ã§ãæå³çã«ããŒã«ã®è©³çŽ°ã«ã€ããŠã¯èª¬æããŸããããåœæã®å 容ã«ã€ããŠã®ã¿èšåããŸãã
ãã¡ã¹ãã¬ãŒã³ã®å ¬åŒããã¥ã¡ã³ã ä»ç€Ÿã®äºäŸ Fastlane ã䜿çšã㊠iOS ã¢ããªã±ãŒã·ã§ã³ã®çµã¿ç«ãŠãèªååããŸã
ãã®èšäºã¯ XNUMX ã€ã®éšåã§æ§æãããŠããŸãã
- 瀟å ã«ã¢ãã€ã«CI/CDãç»å Žããèæ¯
- N ã¢ããªã±ãŒã·ã§ã³åãã® CI/CD ãå±éããããã®æè¡ãœãªã¥ãŒã·ã§ã³
æåã®éšåã¯æãžã®ãã¹ã¿ã«ãžãŒã§ãããäºçªç®ã®éšåã¯èªåèªèº«ã«é©çšã§ããçµéšã§ãã
æŽå²çã«ã¯ãããªã£ã
幎2015
ç§ãã¡ã¯ã¢ãã€ã« ã¢ããªã±ãŒã·ã§ã³ã®éçºãå§ããã°ããã§ãç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³ãDevOpsããã®ä»ã®æµè¡ã®ããšã«ã€ããŠã¯äœãç¥ããŸããã§ãããåã¢ããªã±ãŒã·ã§ã³ã®æŽæ°ã¯ãéçºè
èªèº«ãèªåã®ãã·ã³ããããŒã«ã¢ãŠãããŸããã Android ã®å Žåãããã¯éåžžã«ç°¡åã§ã - çµã¿ç«ãŠããã眲åãããŸã .apk
ããã Google Developer Console ã«ã¢ããããŒãããŠãããiOS ã®å Žåã¯ãXcode çµç±ã®é
åžããŒã«ã§çŽ æŽãããå€ãéããããšãã§ããŸãããã¢ãŒã«ã€ããããŠã³ããŒãããããšãããšããšã©ãŒã§çµäºããããšãå€ããåè©Šè¡ããå¿
èŠããããŸãããæå
端ã®éçºè
ã¯æã«æ°åã³ãŒããæžãã®ã§ã¯ãªããã¢ããªã±ãŒã·ã§ã³ããªãªãŒã¹ããããšãå€æããŸããã
幎2016
ç§ãã¡ã¯æé·ããéçºè ããªãªãŒã¹ã®ããã«äžžäžæ¥ãã解æŸããæ¹æ³ã«ã€ããŠãã§ã«èããŠããŸããããã㊠XNUMX çªç®ã®ã¢ããªã±ãŒã·ã§ã³ãç»å Žãããããç§ãã¡ãèªååãžãšããã«æšãé²ããŸãããå幎ãç§ãã¡ã¯åã㊠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 "[email protected]"
-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 åã«ãªããŸãã
ã¹ã¯ãªããã«æ°ããã¹ããããè¿œå ãããã³ã«ããã®éšåãã³ããŒããŠãã¹ãŠã®ã·ã§ã« ã¹ã¯ãªããã«è²Œãä»ããå¿ èŠããããŸããããã£ãšæ éã«äœæ¥ã§ãããããããŸãããããã®ãããªå€æŽã¯ã¿ã€ããã¹ã§çµããããšãå€ãããªãªãŒã¹ããŒã ãã¹ã¯ãªãããä¿®æ£ããã©ã®è³¢ã人ããã®ã³ãã³ããè¿œå ãããããããŠãããå®éã«äœãããã®ãã調ã¹ãããã«å€æ¹ã«ãªã£ãŠããŸããŸãããäžè¬ã«ããããã©ãããã©ãŒã ã®ã¢ã»ã³ããªçšã®ã¹ã¯ãªãããå°ãªããšãããçšåºŠäŒŒãŠãããšã¯èšããŸããã確ãã«åãããšãããŸãããã
æ°ããã¢ããªã±ãŒã·ã§ã³ã®ããã»ã¹ãéå§ããã«ã¯ããããã®ã¹ã¯ãªããã®ãæ°ãããããŒãžã§ã³ãéžæãããããã°ããŠãã¯ããåäœããŸãããšå€æãããŸã§ã« XNUMX æ¥ãè²»ããå¿ èŠããããŸããã
2018 幎ã®å€ãç§ãã¡ã¯åã³çºå±éäžã®ãã¡ã¹ãã¬ãŒã³ã«ç®ãåããŸããã
ã¿ã¹ã¯ #1: ãã¹ãŠã®ã¹ã¯ãªãã ã¹ããããèŠçŽããFastfile ã«æžãçŽã
ç§ãã¡ãå§ãããšããç§ãã¡ã®ã¹ã¯ãªããã¯ãJenkins ã® XNUMX ã€ã®ã·ã§ã« ã¹ã¯ãªããã«ãã¹ãŠã®ã¹ããããšæŸèæã§æ§æããã足åžã®ããã«èŠããŸããããŸã ãã€ãã©ã€ã³ãšæ®µéããšã®åå²ã«ã¯åãæ¿ããŠããŸããã
ç§ãã¡ã¯çŸç¶ãæ€èšãã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: "[email protected]",
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 åã®ã¢ããªã±ãŒã·ã§ã³ã«å¯Ÿã㊠XNUMX ã€ã® Fastfile ãååŸãã
ããŠãåé¡ã解決ããã®ã¯ããã»ã©é£ãããªãããã§ããå€æ°ãèšå®ããŠãå§ããŸããããã¯ããå®éãããã§åé¡ã¯è§£æ±ºãããŸãããããããç§ãã¡ã倱æããŠããæç¹ã§ã¯ãfastlane èªäœã®å°éç¥èããfastlane ãèšè¿°ãããŠãã Ruby ã®å°éç¥èãããããã¯ãŒã¯äžã®æçšãªäŸããããŸããã§ãããåœæãfastlane ã«ã€ããŠæžãã人ã¯çãXNUMX ã€ã®ã¢ããªã±ãŒã·ã§ã³ã®äŸã«éå®ãããŠããŸãããããéçºè ã«ãšã£ãŠã
Fastlane ã¯ç°å¢å€æ°ãåŠçã§ããããŒãã§ãŒã³ã®ãã¹ã¯ãŒããèšå®ããŠããããã§ã«è©ŠããŠããŸãã
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
[email protected]
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 [email protected]/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 ãä»ã㊠git ã«èšé²ãããŸããå£ããã¹ã¯ãªããã®åå ãæ¢ãå¿ èŠã¯ãªããªããäžè¬ã«ãã¹ã¯ãªãããå£ããŠã¿ãªããã°ãªããŸããã
ããããã¯ç¢ºãã§ã
以åã¯ããã¹ãŠã®ã¹ã¯ãªããã®ä¿å®ãæŽæ°ãæŽæ°ã«ãããã¹ãŠã®åœ±é¿ã®ä¿®æ£ã«æéãè²»ãããŠããŸããããªãªãŒã¹æã®ãšã©ãŒãããŠã³ã¿ã€ã ã®åå ãããã¡ãæ··ãã®ã·ã§ã« ã¹ã¯ãªããã®äžã§è¿œè·¡ããã®ãéåžžã«å°é£ãªåçŽãªã¿ã€ããã¹ã ã£ããšãã¯ãéåžžã«æ®å¿µã§ãããçŸåšã§ã¯ããã®ãããªãšã©ãŒã¯æå°éã«æããããŠããŸããå€æŽã¯ãã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ã«äžåºŠã«ããŒã«ã¢ãŠããããŸãããŸããæ°ããã¢ããªã±ãŒã·ã§ã³ãããã»ã¹ã«çµã¿èŸŒãã«ã¯ 15 åããããŸããCI äžã§ãã³ãã¬ãŒã ãã€ãã©ã€ã³ãã»ããã¢ããããããŒãéçºè ã®ãªããžããªã«è¿œå ããŸãã
Fastfile for Android ãšã¢ããªã±ãŒã·ã§ã³çœ²åã®ãã€ã³ãã¯ãŸã 解æãããŠããªãããã§ãããèšäºãé¢çœããã°ç¶ããæžããŸããã³ã¡ã³ããŸã㯠Telegram ã§ããã®åé¡ãã©ã®ããã«è§£æ±ºããŸããããšããã質åããææ¡ããåŸ
ã¡ããŠãããŸãã
åºæïŒ habr.com