How we integrate & deploy
Mobile Apps with Travis CI
Marcio Klepacz, iOS Engineering @ GetYourGuide
CocoaHeads Berlin 2015
Overview
  Who we are
  The Problem
  The Requirements
  The Solution
  Conclusion
Marcio Klepacz, GetYourGuide
Who we are
GetYourGuide Offers the Largest Travel
Activities Inventory Worldwide
Marcio Klepacz, GetYourGuide
800+
10,600+5,300+
800+
4,000+
2,000+
Marcio Klepacz, GetYourGuide
The Problem
  Repetitive
  Manual
  We want to automate that
  Fit our workflow
Developer Happiness
Marcio Klepacz, GetYourGuide
😄
Develop
😊	
  
Run
Tests
😐
Configure
😒	
  
Build
😠	
  
Write
release
notes
😤	
  
Upload,
notify
users,
etc.
The Requirements
Requirements
Marcio Klepacz, GetYourGuide
  Automatically build and test on push
  Fit into gitflow workflow (feature, develop and
release) branch
  Produce binaries that can be tested (downloaded)
Requirements / Gitflow
Marcio Klepacz, GetYourGuide
Requirements / Gitflow
Marcio Klepacz, GetYourGuide
Requirements / Gitflow
Marcio Klepacz, GetYourGuide
Requirements / Summary
Marcio Klepacz, GetYourGuide
  Build an Alpha App for Test Environment
  able to book with fake CC
  Build a Beta App for the Live Environment
  real content
  Build and test on every push
  Distribute app to testers from release and develop branches
  Relieve developers from repetitive manual tasks
Marcio Klepacz, GetYourGuide
Xcode	
  Server	
   Jenkins	
   Ship.io	
   Travis	
  CI	
  
iOS	
  and	
  
Android	
  
❌	
   ✅	
   ✅	
  
	
  
✅	
  
	
  
Ac,ons	
  
specific	
  to	
  
branches	
  
	
  
✅	
  
	
  
	
  
✅	
  
	
  
	
  
✅	
  
	
  
	
  
✅	
  
	
  
Build	
  on	
  
push	
  
✅	
  
	
  
✅	
  
	
  
✅	
  
	
  
✅	
  
	
  
Big	
  
community	
  
✅	
  
	
  
✅	
  
	
  
❌	
  
	
  
✅	
  
	
  
Hosted	
   ❌	
  
	
  
❌	
  
	
  
✅	
  
	
  
✅	
  
	
  
The Solution
Travis
Marcio Klepacz, GetYourGuide
  Hosted Continuous Integration service
  Configuration file in your project (.travis.yml)
  Define SDK, build env and output
  custom scripts
  Connected to Github
  Triggers in every push and pull request
  Available for many platforms
Travis Setup (.travis.yml)
Marcio Klepacz, GetYourGuide
  It’s not using the iPhone SDK
  code signing is needed
  Doesn’t differentiate between branches
  Doesn’t archive
  Doesn’t distribute
language: objective-c
xcode_project: MyNewProject.xcodeproj
xcode_scheme: MyNewProjectSharedScheme
iPhone SDK
custom build per branch
generate .ipa
distribute
Import keys (import-keys.sh)
# 1. Create keychain
security create-keychain -p travis ios-build.keychain
# 2. Make as default
security default-keychain -s ios-build.keychain
# 3. Unlock keychain
security unlock-keychain -p travis ios-build.keychain
# 4. Add certificates to keychain
security import ./ios-travis-ci/certificates/dist.cer -k ios-build.keychain -T /usr/bin/codesign
security import ./ios-travis-ci/certificates/dist.p12 -k ios-build.keychain -P $KEY_DIST_PASSWORD
-T /usr/bin/codesign
# 5. Copying provisioning profile to Travis
mkdir -p ~/Library/MobileDevice/Provisioning Profiles
cp ./ios-travis-ci/profiles/*.mobileprovision ~/Library/MobileDevice/Provisioning Profiles/
Marcio Klepacz, GetYourGuide
iPhone SDK
custom build per branch
generate .ipa
distribute
Import keys (import-keys.sh)
# 1. Create keychain
security create-keychain -p travis ios-build.keychain
# 2. Make as default
security default-keychain -s ios-build.keychain
# 3. Unlock keychain
security unlock-keychain -p travis ios-build.keychain
# 4. Add certificates to keychain
security import ./ios-travis-ci/certificates/dist.cer -k ios-build.keychain -T /usr/bin/codesign
security import ./ios-travis-ci/certificates/dist.p12 -k ios-build.keychain -P $KEY_DIST_PASSWORD
-T /usr/bin/codesign
# 5. Copying provisioning profile to Travis
mkdir -p ~/Library/MobileDevice/Provisioning Profiles
cp ./ios-travis-ci/profiles/*.mobileprovision ~/Library/MobileDevice/Provisioning Profiles/
⛔️️
Marcio Klepacz, GetYourGuide
iPhone SDK
custom build per branch
generate .ipa
distribute
Security
Marcio Klepacz, GetYourGuide
  You can encrypt environment variables using
Travis command line tool on your terminal:
~ $ travis ecrypt ‘KEY_DIST_PASSWORD=abc123’ –add
  Passing the option “--add” will automatically add the secure
key to your .travis.yml
env:
global:
- secure: Pz3cxDffsdafasf34324fdsf232fdsfdsf3fdsf
iPhone SDK
custom build per branch
generate .ipa
distribute
Travis Setup (.travis.yml)
Marcio Klepacz, GetYourGuide
  Use iPhone SDK ✅
  Doesn’t differentiate between branches
  Doesn’t archive
  Doesn’t distribute
language: objective-c
env:
global:
- secure: Pz3cxDffsdafasf34324fdsf232fdsfdsf3fdsf
before_script:
- ./scripts/import-key.sh
script:
- xctool -workspace MyNewProject.xcworkspace -scheme MySharedScheme -sdk iphoneos -configuration Beta
iPhone SDK
custom build per branch
generate .ipa
distribute
Building (build_app.sh)
# 1.
xctool -workspace ${APP_NAME}.xcworkspace 
-scheme ${APP_NAME} 
-sdk iphonesimulator test
…
# 2.
export RELEASE_SUFFIX=".release”
# Bundle Identifier:
# com.getyourguide.mobile.$(PRODUCT_NAME:rfc1034identifier)${BUNDLE_ID_SUFFIX}$
{RELEASE_SUFFIX}
…
# 3
xctool -workspace ${APP_NAME}.xcworkspace -scheme ${APP_NAME} 
-sdk iphoneos 
-configuration Debug 
OBJROOT=$PWD/build 
SYMROOT=$PWD/build
xctool -workspace ${APP_NAME}.xcworkspace -scheme ${APP_NAME} 
-sdk iphoneos 
-configuration Beta 
OBJROOT=$PWD/build 
SYMROOT=$PWD/build
Marcio Klepacz, GetYourGuide
iPhone SDK
custom build per branch
generate .ipa
distribute
Travis Setup (.travis.yml)
Marcio Klepacz, GetYourGuide
  Use iPhone SDK ✅
  Differentiate between branches ✅
  Doesn’t archive
  Doesn’t distribute
language: objective-c
env:
global:
- secure: Pz3cxDffsdafasf34324fdsf232fdsfdsf3fdsf
before_script:
- ./scripts/import-key.sh
script:
- ./scripts/build-app.sh
iPhone SDK
custom build per branch
generate .ipa
distribute
# 1.
xcrun -sdk iphoneos PackageApplication 
-v ”$BUILD_DIR/$APP_NAME.app" 
-o ”$BUILD_DIR/$APP_NAME.ipa" 
--sign "$DEVELOPER_NAME" 
--embed ”$PROVISIONING_PROFILE"
…
# 2.
release_notes=`git log --since=1.week --pretty=format:"%an - %s"`
curl 
-F status="2" 
-F notify="0" 
-F release_type="2" 
-F notes="$release_notes" 
-F notes_type="0" 
-F "ipa=@$outputdir/$APP_NAME.ipa" 
-F "mobileprovision=@$provisioning_profile" 
-H "X-HockeyAppToken: ${HOCKEY_APP_TOKEN}" 
https://rink.hockeyapp.net/api/2/apps/upload # Uploading to HockeyApp
Archiving and uploading
(archive_and_upload.sh)
Marcio Klepacz, GetYourGuide
iPhone SDK
custom build per branch
generate .ipa
distribute
Travis Setup (.travis.yml)
Marcio Klepacz, GetYourGuide
  Use iPhone SDK ✅
  Differentiate between branches ✅
  Archive ✅
  Doesn’t distribute ✅
language: objective-c
env:
global:
- secure: Pz3cxDffsdafasf34324fdsf232fdsfdsf3fdsf
before_script:
- ./scripts/import-key.sh
script:
- ./scripts/build-app.sh
after_success:
- ./scripts/archive_and_upload.sh
iPhone SDK
custom build per branch
generate .ipa
distribute
Move the scripts away from the app
repository (Optional)
Marcio Klepacz, GetYourGuide
  Maintenance 👍
  Reusable 👍
  Slower builds 👎
…
git:
submodules: false
before_install:
- git submodule init ios-travis-ci
- git submodule update --remote --merge ios-travis-ci
(Bonus) Overlaying Icons
Marcio Klepacz, GetYourGuide
  Add icon overlay script on the Build Phase of your target
IconOverlaying (by: Krzysztof Zabłocki)
…
before_install:
…
- brew install imagemagick && brew install ghostscript
Conclusion
Marcio Klepacz, GetYourGuide
  Automate tasks
  App is distributed
  No manual configuration
  Different actions between branches
  5 different apps to test concurrently
(@banaslee’s phone)
Thanks for your time
@marciok and marcio@getyourguide.com
References
Marcio Klepacz, GetYourGuide
Travis CI for iOS (Mattes Groeger)
johanneswuerbach / .travis.yml (Johannes Würbach)
The OS X Build Environment (Travis CI)

How we integrate & deploy Mobile Apps with Travis CI

  • 1.
    How we integrate& deploy Mobile Apps with Travis CI Marcio Klepacz, iOS Engineering @ GetYourGuide CocoaHeads Berlin 2015
  • 2.
    Overview   Who weare   The Problem   The Requirements   The Solution   Conclusion Marcio Klepacz, GetYourGuide
  • 3.
  • 4.
    GetYourGuide Offers theLargest Travel Activities Inventory Worldwide Marcio Klepacz, GetYourGuide 800+ 10,600+5,300+ 800+ 4,000+ 2,000+
  • 5.
  • 6.
  • 7.
      Repetitive   Manual  We want to automate that   Fit our workflow Developer Happiness Marcio Klepacz, GetYourGuide 😄 Develop 😊   Run Tests 😐 Configure 😒   Build 😠   Write release notes 😤   Upload, notify users, etc.
  • 8.
  • 9.
    Requirements Marcio Klepacz, GetYourGuide  Automatically build and test on push   Fit into gitflow workflow (feature, develop and release) branch   Produce binaries that can be tested (downloaded)
  • 10.
    Requirements / Gitflow MarcioKlepacz, GetYourGuide
  • 11.
    Requirements / Gitflow MarcioKlepacz, GetYourGuide
  • 12.
    Requirements / Gitflow MarcioKlepacz, GetYourGuide
  • 13.
    Requirements / Summary MarcioKlepacz, GetYourGuide   Build an Alpha App for Test Environment   able to book with fake CC   Build a Beta App for the Live Environment   real content   Build and test on every push   Distribute app to testers from release and develop branches   Relieve developers from repetitive manual tasks
  • 14.
    Marcio Klepacz, GetYourGuide Xcode  Server   Jenkins   Ship.io   Travis  CI   iOS  and   Android   ❌   ✅   ✅     ✅     Ac,ons   specific  to   branches     ✅       ✅       ✅       ✅     Build  on   push   ✅     ✅     ✅     ✅     Big   community   ✅     ✅     ❌     ✅     Hosted   ❌     ❌     ✅     ✅    
  • 15.
  • 16.
    Travis Marcio Klepacz, GetYourGuide  Hosted Continuous Integration service   Configuration file in your project (.travis.yml)   Define SDK, build env and output   custom scripts   Connected to Github   Triggers in every push and pull request   Available for many platforms
  • 17.
    Travis Setup (.travis.yml) MarcioKlepacz, GetYourGuide   It’s not using the iPhone SDK   code signing is needed   Doesn’t differentiate between branches   Doesn’t archive   Doesn’t distribute language: objective-c xcode_project: MyNewProject.xcodeproj xcode_scheme: MyNewProjectSharedScheme iPhone SDK custom build per branch generate .ipa distribute
  • 18.
    Import keys (import-keys.sh) #1. Create keychain security create-keychain -p travis ios-build.keychain # 2. Make as default security default-keychain -s ios-build.keychain # 3. Unlock keychain security unlock-keychain -p travis ios-build.keychain # 4. Add certificates to keychain security import ./ios-travis-ci/certificates/dist.cer -k ios-build.keychain -T /usr/bin/codesign security import ./ios-travis-ci/certificates/dist.p12 -k ios-build.keychain -P $KEY_DIST_PASSWORD -T /usr/bin/codesign # 5. Copying provisioning profile to Travis mkdir -p ~/Library/MobileDevice/Provisioning Profiles cp ./ios-travis-ci/profiles/*.mobileprovision ~/Library/MobileDevice/Provisioning Profiles/ Marcio Klepacz, GetYourGuide iPhone SDK custom build per branch generate .ipa distribute
  • 19.
    Import keys (import-keys.sh) #1. Create keychain security create-keychain -p travis ios-build.keychain # 2. Make as default security default-keychain -s ios-build.keychain # 3. Unlock keychain security unlock-keychain -p travis ios-build.keychain # 4. Add certificates to keychain security import ./ios-travis-ci/certificates/dist.cer -k ios-build.keychain -T /usr/bin/codesign security import ./ios-travis-ci/certificates/dist.p12 -k ios-build.keychain -P $KEY_DIST_PASSWORD -T /usr/bin/codesign # 5. Copying provisioning profile to Travis mkdir -p ~/Library/MobileDevice/Provisioning Profiles cp ./ios-travis-ci/profiles/*.mobileprovision ~/Library/MobileDevice/Provisioning Profiles/ ⛔️️ Marcio Klepacz, GetYourGuide iPhone SDK custom build per branch generate .ipa distribute
  • 20.
    Security Marcio Klepacz, GetYourGuide  You can encrypt environment variables using Travis command line tool on your terminal: ~ $ travis ecrypt ‘KEY_DIST_PASSWORD=abc123’ –add   Passing the option “--add” will automatically add the secure key to your .travis.yml env: global: - secure: Pz3cxDffsdafasf34324fdsf232fdsfdsf3fdsf iPhone SDK custom build per branch generate .ipa distribute
  • 21.
    Travis Setup (.travis.yml) MarcioKlepacz, GetYourGuide   Use iPhone SDK ✅   Doesn’t differentiate between branches   Doesn’t archive   Doesn’t distribute language: objective-c env: global: - secure: Pz3cxDffsdafasf34324fdsf232fdsfdsf3fdsf before_script: - ./scripts/import-key.sh script: - xctool -workspace MyNewProject.xcworkspace -scheme MySharedScheme -sdk iphoneos -configuration Beta iPhone SDK custom build per branch generate .ipa distribute
  • 22.
    Building (build_app.sh) # 1. xctool-workspace ${APP_NAME}.xcworkspace -scheme ${APP_NAME} -sdk iphonesimulator test … # 2. export RELEASE_SUFFIX=".release” # Bundle Identifier: # com.getyourguide.mobile.$(PRODUCT_NAME:rfc1034identifier)${BUNDLE_ID_SUFFIX}$ {RELEASE_SUFFIX} … # 3 xctool -workspace ${APP_NAME}.xcworkspace -scheme ${APP_NAME} -sdk iphoneos -configuration Debug OBJROOT=$PWD/build SYMROOT=$PWD/build xctool -workspace ${APP_NAME}.xcworkspace -scheme ${APP_NAME} -sdk iphoneos -configuration Beta OBJROOT=$PWD/build SYMROOT=$PWD/build Marcio Klepacz, GetYourGuide iPhone SDK custom build per branch generate .ipa distribute
  • 23.
    Travis Setup (.travis.yml) MarcioKlepacz, GetYourGuide   Use iPhone SDK ✅   Differentiate between branches ✅   Doesn’t archive   Doesn’t distribute language: objective-c env: global: - secure: Pz3cxDffsdafasf34324fdsf232fdsfdsf3fdsf before_script: - ./scripts/import-key.sh script: - ./scripts/build-app.sh iPhone SDK custom build per branch generate .ipa distribute
  • 24.
    # 1. xcrun -sdkiphoneos PackageApplication -v ”$BUILD_DIR/$APP_NAME.app" -o ”$BUILD_DIR/$APP_NAME.ipa" --sign "$DEVELOPER_NAME" --embed ”$PROVISIONING_PROFILE" … # 2. release_notes=`git log --since=1.week --pretty=format:"%an - %s"` curl -F status="2" -F notify="0" -F release_type="2" -F notes="$release_notes" -F notes_type="0" -F "ipa=@$outputdir/$APP_NAME.ipa" -F "mobileprovision=@$provisioning_profile" -H "X-HockeyAppToken: ${HOCKEY_APP_TOKEN}" https://rink.hockeyapp.net/api/2/apps/upload # Uploading to HockeyApp Archiving and uploading (archive_and_upload.sh) Marcio Klepacz, GetYourGuide iPhone SDK custom build per branch generate .ipa distribute
  • 25.
    Travis Setup (.travis.yml) MarcioKlepacz, GetYourGuide   Use iPhone SDK ✅   Differentiate between branches ✅   Archive ✅   Doesn’t distribute ✅ language: objective-c env: global: - secure: Pz3cxDffsdafasf34324fdsf232fdsfdsf3fdsf before_script: - ./scripts/import-key.sh script: - ./scripts/build-app.sh after_success: - ./scripts/archive_and_upload.sh iPhone SDK custom build per branch generate .ipa distribute
  • 26.
    Move the scriptsaway from the app repository (Optional) Marcio Klepacz, GetYourGuide   Maintenance 👍   Reusable 👍   Slower builds 👎 … git: submodules: false before_install: - git submodule init ios-travis-ci - git submodule update --remote --merge ios-travis-ci
  • 27.
    (Bonus) Overlaying Icons MarcioKlepacz, GetYourGuide   Add icon overlay script on the Build Phase of your target IconOverlaying (by: Krzysztof Zabłocki) … before_install: … - brew install imagemagick && brew install ghostscript
  • 28.
    Conclusion Marcio Klepacz, GetYourGuide  Automate tasks   App is distributed   No manual configuration   Different actions between branches   5 different apps to test concurrently (@banaslee’s phone)
  • 29.
    Thanks for yourtime @marciok and marcio@getyourguide.com
  • 30.
    References Marcio Klepacz, GetYourGuide TravisCI for iOS (Mattes Groeger) johanneswuerbach / .travis.yml (Johannes Würbach) The OS X Build Environment (Travis CI)