100

Intro to Continuous Integration at SoundCloud

Embed Size (px)

DESCRIPTION

In the past year at SoundCloud, we've improved our CI from a single machine running our limited unit test suite to several machines running a linter, unit tests, acceptance tests and building several versions of our app including the AppStore version for every commit. This enabled us to move away from pull-requests and code reviews and use trunk based development and pairing, as well as scale the team from 3 to 7 developers. We've stopped relying on Xcode Schemes for builds, we're using instead command line tools and compile-time parameters to automatically build internal versions of our app and distribute it internally. In order to make our release process more reliable, the AppStore version of the app is created by re-signing an AdHoc build. This enables us to test the exact same binary that will be submitted to the AppStore. This talk will focus on 3 areas of our continuous integration: testing, building with user defined build settings and signing apps.

Citation preview

Page 1: Intro to Continuous Integration at SoundCloud
Page 2: Intro to Continuous Integration at SoundCloud

Continuous Integration at SoundCloud

iOSDevUK september 2014 !

Vincent Garrigues @garriguv

Page 3: Intro to Continuous Integration at SoundCloud

What is CI?

Page 4: Intro to Continuous Integration at SoundCloud

“Continuous integration (CI) is the practice, in software engineering, of merging all developer working copies with a shared mainline several times a day.”

http://en.wikipedia.org/wiki/Continuous_integration

Page 5: Intro to Continuous Integration at SoundCloud

• trunk based development • lots of testing • CI pipeline

Page 6: Intro to Continuous Integration at SoundCloud
Page 7: Intro to Continuous Integration at SoundCloud
Page 8: Intro to Continuous Integration at SoundCloud
Page 9: Intro to Continuous Integration at SoundCloud
Page 10: Intro to Continuous Integration at SoundCloud
Page 11: Intro to Continuous Integration at SoundCloud
Page 12: Intro to Continuous Integration at SoundCloud
Page 13: Intro to Continuous Integration at SoundCloud
Page 14: Intro to Continuous Integration at SoundCloud
Page 15: Intro to Continuous Integration at SoundCloud

Why CI?

Page 16: Intro to Continuous Integration at SoundCloud

• move fast • keep codebase healthy • ship reliable apps

Page 17: Intro to Continuous Integration at SoundCloud

• move fast • keep codebase healthy • ship reliable apps

Page 18: Intro to Continuous Integration at SoundCloud
Page 19: Intro to Continuous Integration at SoundCloud
Page 20: Intro to Continuous Integration at SoundCloud

• started from scratch • months in development • millions of users

Page 21: Intro to Continuous Integration at SoundCloud

iOS Crash Complaints (avg per Week)

0

35

70

105

140

April May June July August

SoundCloud community team

Page 22: Intro to Continuous Integration at SoundCloud
Page 23: Intro to Continuous Integration at SoundCloud

How to get started?

Page 24: Intro to Continuous Integration at SoundCloud

Start simple and iterate

Page 25: Intro to Continuous Integration at SoundCloud

• run unit test suite • α and β versions • sign .app builds

Page 26: Intro to Continuous Integration at SoundCloud
Page 27: Intro to Continuous Integration at SoundCloud

Rake

Page 28: Intro to Continuous Integration at SoundCloud

require 'rake' !desc 'say Hello World!' task :hello do puts 'Hello World!' end

Page 29: Intro to Continuous Integration at SoundCloud

require 'rake' !desc 'say Hello World!' task :hello do puts 'Hello World!' end

Page 30: Intro to Continuous Integration at SoundCloud

require 'rake' !desc 'say Hello World!' task :hello do puts 'Hello World!' end

Page 31: Intro to Continuous Integration at SoundCloud

require 'rake' !desc 'say Hello World!' task :hello do puts 'Hello World!' end

Page 32: Intro to Continuous Integration at SoundCloud

Running the unit tests

Page 33: Intro to Continuous Integration at SoundCloud

use xcodebuild or xctool

Page 34: Intro to Continuous Integration at SoundCloud

xcodebuild -workspace ci.xcworkspace -scheme ci -configuration Debug -sdk iphonesimulator7.1 -destination "platform=iOS Simulator,name=iPhone Retina (4-inch)" test

Page 35: Intro to Continuous Integration at SoundCloud

xcodebuild -workspace ci.xcworkspace -scheme ci -configuration Debug -sdk iphonesimulator7.1 -destination "platform=iOS Simulator,name=iPhone Retina (4-inch)" test

Page 36: Intro to Continuous Integration at SoundCloud

xcodebuild -workspace ci.xcworkspace -scheme ci -configuration Debug -sdk iphonesimulator7.1 -destination "platform=iOS Simulator,name=iPhone Retina (4-inch)" test

Page 37: Intro to Continuous Integration at SoundCloud

xcodebuild -workspace ci.xcworkspace -scheme ci -configuration Debug -sdk iphonesimulator7.1 -destination "platform=iOS Simulator,name=iPhone Retina (4-inch)" test

Page 38: Intro to Continuous Integration at SoundCloud

xcodebuild -workspace ci.xcworkspace -scheme ci -configuration Debug -sdk iphonesimulator7.1 -destination "platform=iOS Simulator,name=iPhone Retina (4-inch)" test

Page 39: Intro to Continuous Integration at SoundCloud

xcodebuild -workspace ci.xcworkspace -scheme ci -configuration Debug -sdk iphonesimulator7.1 -destination "platform=iOS Simulator,name=iPhone Retina (4-inch)" clean

Page 40: Intro to Continuous Integration at SoundCloud

xcodebuild -workspace ci.xcworkspace -scheme ci -configuration Debug -sdk iphonesimulator7.1 -destination "platform=iOS Simulator,name=iPhone Retina (4-inch)" build

Page 41: Intro to Continuous Integration at SoundCloud

rake tasks • rake clean • rake build • rake test

Page 42: Intro to Continuous Integration at SoundCloud

α and β versions

Page 43: Intro to Continuous Integration at SoundCloud
Page 44: Intro to Continuous Integration at SoundCloud

User-defined build settings

Page 45: Intro to Continuous Integration at SoundCloud
Page 46: Intro to Continuous Integration at SoundCloud
Page 47: Intro to Continuous Integration at SoundCloud
Page 48: Intro to Continuous Integration at SoundCloud
Page 49: Intro to Continuous Integration at SoundCloud
Page 50: Intro to Continuous Integration at SoundCloud

Override user-defined build settings when

running xcodebuild

Page 51: Intro to Continuous Integration at SoundCloud

xcodebuild -workspace ci.xcworkspace -scheme ci -configuration Debug -sdk iphonesimulator7.1 -destination "platform=iOS Simulator,name=iPhone Retina (4-inch)” build

Page 52: Intro to Continuous Integration at SoundCloud

xcodebuild (…) VG_BUNDLE_ID=com.company.app-alpha build

Page 53: Intro to Continuous Integration at SoundCloud

xcodebuild (…) VG_BUNDLE_ID=com.company.app-alpha VG_DISPLAY_NAME=α build

Page 54: Intro to Continuous Integration at SoundCloud

xcodebuild (…) VG_BUNDLE_ID=com.company.app-alpha VG_DISPLAY_NAME=α VG_CODE_SIGNING="'iPhone Distribution: Vincent Garrigues'" build

Page 55: Intro to Continuous Integration at SoundCloud

Where can we store those settings?

Page 56: Intro to Continuous Integration at SoundCloud

We use a YAML file

Page 57: Intro to Continuous Integration at SoundCloud

defaults: &DEFAULTS app: &APP_DEFAULTS workspace: ci.xcworkspace scheme: ci configuration: Release display_name: ci-test bundle_identifier: com.company.ci-test codesign: &CODESIGN_DEFAULTS signing_identity: '"iPhone Distribution: Vincent Garrigues (X73EL3QFZB)"' provisioning_profile: provisioning/app_store.mobileprovision

Page 58: Intro to Continuous Integration at SoundCloud

defaults: &DEFAULTS app: &APP_DEFAULTS workspace: ci.xcworkspace scheme: ci configuration: Release display_name: ci-test bundle_identifier: com.company.ci-test codesign: &CODESIGN_DEFAULTS signing_identity: '"iPhone Distribution: Vincent Garrigues (X73EL3QFZB)"' provisioning_profile: provisioning/app_store.mobileprovision

Page 59: Intro to Continuous Integration at SoundCloud

defaults: &DEFAULTS app: &APP_DEFAULTS workspace: ci.xcworkspace scheme: ci configuration: Release display_name: ci-test bundle_identifier: com.company.ci-test codesign: &CODESIGN_DEFAULTS signing_identity: '"iPhone Distribution: Vincent Garrigues (X73EL3QFZB)"' provisioning_profile: provisioning/app_store.mobileprovision

Page 60: Intro to Continuous Integration at SoundCloud

defaults: &DEFAULTS app: &APP_DEFAULTS workspace: ci.xcworkspace scheme: ci configuration: Release display_name: ci-test bundle_identifier: com.company.ci-test codesign: &CODESIGN_DEFAULTS signing_identity: '"iPhone Distribution: Vincent Garrigues (X73EL3QFZB)"' provisioning_profile: provisioning/app_store.mobileprovision

Page 61: Intro to Continuous Integration at SoundCloud

defaults: &DEFAULTS app: &APP_DEFAULTS workspace: ci.xcworkspace scheme: ci configuration: Release display_name: ci-test bundle_identifier: com.company.ci-test codesign: &CODESIGN_DEFAULTS signing_identity: '"iPhone Distribution: Vincent Garrigues (X73EL3QFZB)"' provisioning_profile: provisioning/app_store.mobileprovision

Page 62: Intro to Continuous Integration at SoundCloud

defaults: &DEFAULTS app: &APP_DEFAULTS workspace: ci.xcworkspace scheme: ci configuration: Release display_name: ci-test bundle_identifier: com.company.ci-test codesign: &CODESIGN_DEFAULTS signing_identity: '"iPhone Distribution: Vincent Garrigues (X73EL3QFZB)"' provisioning_profile: provisioning/app_store.mobileprovision

Page 63: Intro to Continuous Integration at SoundCloud

defaults: (..) !alpha: <<: *DEFAULTS app: <<: *APP_DEFAULTS display_name: α bundle_identifier: com.company.ci-test-alpha codesign: <<: *CODESIGN_DEFAULTS provisioning_profile: provisioning/alpha.mobileprovision

Page 64: Intro to Continuous Integration at SoundCloud

defaults: (..) !alpha: <<: *DEFAULTS app: <<: *APP_DEFAULTS display_name: α bundle_identifier: com.company.ci-test-alpha codesign: <<: *CODESIGN_DEFAULTS provisioning_profile: provisioning/alpha.mobileprovision

Page 65: Intro to Continuous Integration at SoundCloud

defaults: (..) !alpha: <<: *DEFAULTS app: <<: *APP_DEFAULTS display_name: α bundle_identifier: com.company.ci-test-alpha codesign: <<: *CODESIGN_DEFAULTS provisioning_profile: provisioning/alpha.mobileprovision

Page 66: Intro to Continuous Integration at SoundCloud

rake build BUILD_ENV=alpha rake build BUILD_ENV=beta rake build BUILD_ENV=adhoc rake build BUILD_ENV=release

Page 67: Intro to Continuous Integration at SoundCloud

rake build BUILD_ENV=alpha rake build BUILD_ENV=beta rake build BUILD_ENV=adhoc rake build BUILD_ENV=release

Page 68: Intro to Continuous Integration at SoundCloud

rake build BUILD_ENV=alpha rake build BUILD_ENV=beta rake build BUILD_ENV=adhoc rake build BUILD_ENV=appstore

Page 69: Intro to Continuous Integration at SoundCloud

rake build creates a .app

Page 70: Intro to Continuous Integration at SoundCloud

We need a .ipa

Page 71: Intro to Continuous Integration at SoundCloud

xcrun

Page 72: Intro to Continuous Integration at SoundCloud

xcrun -v -sdk iphoneos PackageApplication ci-test-alpha.app -o ci-test-alpha.ipa --sign "iPhone Distribution: Vincent Garrigues" --embed provisioning/alpha.mobileprovision

Page 73: Intro to Continuous Integration at SoundCloud

xcrun -v -sdk iphoneos PackageApplication ci-test-alpha.app -o ci-test-alpha.ipa --sign "iPhone Distribution: Vincent Garrigues" --embed provisioning/alpha.mobileprovision

Page 74: Intro to Continuous Integration at SoundCloud

xcrun -v -sdk iphoneos PackageApplication ci-test-alpha.app -o ci-test-alpha.ipa --sign "iPhone Distribution: Vincent Garrigues" --embed provisioning/alpha.mobileprovision

Page 75: Intro to Continuous Integration at SoundCloud

xcrun -v -sdk iphoneos PackageApplication ci-test-alpha.app -o ci-test-alpha.ipa --sign "iPhone Distribution: Vincent Garrigues" --embed provisioning/alpha.mobileprovision

Page 76: Intro to Continuous Integration at SoundCloud

xcrun -v -sdk iphoneos PackageApplication ci-test-alpha.app -o ci-test-alpha.ipa --sign "iPhone Distribution: Vincent Garrigues" --embed provisioning/alpha.mobileprovision

Page 77: Intro to Continuous Integration at SoundCloud

xcrun -v -sdk iphoneos PackageApplication ci-test-alpha.app -o ci-test-alpha.ipa --sign "iPhone Distribution: Vincent Garrigues" --embed provisioning/alpha.mobileprovision

Page 78: Intro to Continuous Integration at SoundCloud

xcrun -v -sdk iphoneos PackageApplication ci-test-alpha.app -o ci-test-alpha.ipa --sign "iPhone Distribution: Vincent Garrigues" --embed provisioning/alpha.mobileprovision

Page 79: Intro to Continuous Integration at SoundCloud

xcrun -v -sdk iphoneos PackageApplication ci-test-alpha.app -o ci-test-alpha.ipa --sign "iPhone Distribution: Vincent Garrigues" --embed provisioning/alpha.mobileprovision

Page 80: Intro to Continuous Integration at SoundCloud

rake sign

Page 81: Intro to Continuous Integration at SoundCloud

• rake clean • rake test • rake build • rake sign

Page 82: Intro to Continuous Integration at SoundCloud

How can we use those rake tasks?

Page 83: Intro to Continuous Integration at SoundCloud
Page 84: Intro to Continuous Integration at SoundCloud

• rake build sign BUILD_ENV=alpha • rake build sign BUILD_ENV=beta • rake build sign BUILD_ENV=adhoc

Page 85: Intro to Continuous Integration at SoundCloud

• rake build sign BUILD_ENV=alpha • rake build sign BUILD_ENV=beta • rake build sign BUILD_ENV=adhoc

Page 86: Intro to Continuous Integration at SoundCloud

• rake build sign BUILD_ENV=alpha • rake build sign BUILD_ENV=beta • rake build sign BUILD_ENV=adhoc

Page 87: Intro to Continuous Integration at SoundCloud

• rake build sign BUILD_ENV=alpha • rake build sign BUILD_ENV=beta • rake build sign BUILD_ENV=adhoc • rake build sign BUILD_ENV=appstore

Page 88: Intro to Continuous Integration at SoundCloud

Ad-Hoc and AppStore builds have the same

bundle id

Page 89: Intro to Continuous Integration at SoundCloud

rake build BUILD_ENV=appstore

ci-test-appstore.app ci-test-appstore.dSYM ci-test-appstore.dSYM.zip

Page 90: Intro to Continuous Integration at SoundCloud

rake build BUILD_ENV=appstore rake ipa BUILD_ENV=appstore

ci-test-appstore.app ci-test-appstore.dSYM ci-test-appstore.dSYM.zip ci-test-appstore.ipa

Page 91: Intro to Continuous Integration at SoundCloud

rake build BUILD_ENV=appstore rake ipa BUILD_ENV=appstore rake ipa BUILD_ENV=adhoc

ci-test-appstore.app ci-test-appstore.dSYM ci-test-appstore.dSYM.zip ci-test-appstore.ipa ci-test-adhoc.ipa

Page 92: Intro to Continuous Integration at SoundCloud

rake build BUILD_ENV=appstore rake ipa BUILD_ENV=appstore rake ipa BUILD_ENV=adhoc

ci-test-appstore.app ci-test-appstore.dSYM ci-test-appstore.dSYM.zip ci-test-appstore.ipa ci-test-adhoc.ipa

Page 93: Intro to Continuous Integration at SoundCloud

ci-test-appstore.app ci-test-appstore.dSYM ci-test-appstore.dSYM.zip ci-test-appstore.ipa ci-test-adhoc.ipa

rake build BUILD_ENV=appstore rake ipa BUILD_ENV=appstore rake ipa BUILD_ENV=adhoc

Page 94: Intro to Continuous Integration at SoundCloud

The same binary, signed twice

Page 95: Intro to Continuous Integration at SoundCloud

Sample project !

github.com/garriguv/ci-test

Page 96: Intro to Continuous Integration at SoundCloud
Page 97: Intro to Continuous Integration at SoundCloud

• linter (Xcode project, data model, acceptance tests, ruby, ObjC)

• static analysis • unit tests (ruby and ObjC) • acceptance tests • custom app icon • deploy to HockeyApp • …

Page 98: Intro to Continuous Integration at SoundCloud
Page 99: Intro to Continuous Integration at SoundCloud
Page 100: Intro to Continuous Integration at SoundCloud

Thank you!http://github.com/garriguv/ci-talk

!

!

Vincent Garrigues @garriguv