Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Using Continuous Integration with Xamarin Apps

Using Continuous Integration with Xamarin Apps

Presented at Xamarin Evolve 2014

Greg Shackles

October 08, 2014
Tweet

More Decks by Greg Shackles

Other Decks in Technology

Transcript

  1. Build Agent Setup ▪ OS X machine for iOS builds

    - Mac Mini works well ▪ OS X or Windows machine for Android
  2. Build Agent Setup ▪ OS X machine for iOS builds

    - Mac Mini works well ▪ OS X or Windows machine for Android ▪ Install platform SDKs
  3. Build Agent Setup ▪ OS X machine for iOS builds

    - Mac Mini works well ▪ OS X or Windows machine for Android ▪ Install platform SDKs ▪ Install Xamarin
  4. Build Agent Setup ▪ OS X machine for iOS builds

    - Mac Mini works well ▪ OS X or Windows machine for Android ▪ Install platform SDKs ▪ Install Xamarin ▪ Install agent software for chosen CI server
  5. Android: Build Windows: msbuild OS X: xbuild xbuild build /t:Build

    /p:Configuration=Release MyAwesomeApp.sln
  6. Android: Package (Part 1) Windows: msbuild OS X: xbuild xbuild

    build /t:PackageForAndroid /p:Configuration=Release MyAwesomeAndroidApp.csproj
  7. Android: Package (Part 2) jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore

    <keystore file> -storepass <keystore password> -signedjar path/to/MyAwesomeAndroidApp-Signed.apk path/to/MyAwesomeAndroidApp.apk <keystore alias>
  8. Android: Package (Part 2) jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore

    <keystore file> -storepass <keystore password> -signedjar path/to/MyAwesomeAndroidApp-Signed.apk path/to/MyAwesomeAndroidApp.apk <keystore alias> zipalign -f -v 4 path/to/MyAwesomeAndroidApp-Signed.apk path/to/MyAwesomeAndroidApp-Aligned.apk
  9. Pro Tip: Allow Build to Access UI jetbrains.teamcity.BuildAgent.plist ▪ Set

    username <key>UserName</key> <string>your_user</string>
  10. Pro Tip: Allow Build to Access UI jetbrains.teamcity.BuildAgent.plist ▪ Set

    username <key>UserName</key> <string>your_user</string> ▪ Copy to /Library/LaunchAgents
  11. TestCloud Run your UI tests on hundreds of devices test-cloud.exe

    submit path/to/myapp.[ipa|apk] <TestCloud token> --devices <Device Set ID> --series "master" --locale "en_US" --assembly-dir “path/to/bin“ --nunit-xml testresults.xml
  12. FAKE #r @"FAKE/tools/FakeLib.dll"
 #load "build-helpers/iOS.fsx"
 
 open Fake
 
 Target

    "ios-build" (fun () ->
 iOS.build "Debug|iPhoneSimulator"
 )
 
 Target "ios-adhoc" (fun () ->
 iOS.build "AdHoc|iPhone"
 )
 
 Target "ios-testflight" (fun () ->
 iOS.publishToTestFlight()
 )
 
 "ios-adhoc"
 ==> "ios-testflight"
 
 RunTarget()

  13. FAKE #r @"FAKE/tools/FakeLib.dll"
 #load "build-helpers/iOS.fsx"
 
 open Fake
 
 Target

    "ios-build" (fun () ->
 iOS.build "Debug|iPhoneSimulator"
 )
 
 Target "ios-adhoc" (fun () ->
 iOS.build "AdHoc|iPhone"
 )
 
 Target "ios-testflight" (fun () ->
 iOS.publishToTestFlight()
 )
 
 "ios-adhoc"
 ==> "ios-testflight"
 
 RunTarget()
 TeamCityHelper.PublishArtifact "path/to/App.zip"
 Helpers
  14. FAKE #r @"FAKE/tools/FakeLib.dll"
 #load "build-helpers/iOS.fsx"
 
 open Fake
 
 Target

    "ios-build" (fun () ->
 iOS.build "Debug|iPhoneSimulator"
 )
 
 Target "ios-adhoc" (fun () ->
 iOS.build "AdHoc|iPhone"
 )
 
 Target "ios-testflight" (fun () ->
 iOS.publishToTestFlight()
 )
 
 "ios-adhoc"
 ==> "ios-testflight"
 
 RunTarget()
 TeamCityHelper.PublishArtifact "path/to/App.zip"
 TeamCityHelper.sendTeamCityNUnitImport "results.xml"
 Helpers
  15. FAKE #r @"FAKE/tools/FakeLib.dll"
 #load "build-helpers/iOS.fsx"
 
 open Fake
 
 Target

    "ios-build" (fun () ->
 iOS.build "Debug|iPhoneSimulator"
 )
 
 Target "ios-adhoc" (fun () ->
 iOS.build "AdHoc|iPhone"
 )
 
 Target "ios-testflight" (fun () ->
 iOS.publishToTestFlight()
 )
 
 "ios-adhoc"
 ==> "ios-testflight"
 
 RunTarget()
 TeamCityHelper.PublishArtifact "path/to/App.zip"
 TeamCityHelper.sendTeamCityNUnitImport "results.xml"
 TestFlight(fun p ->
 {p with
 File: "path/to/App.app"
 Notes: "Now with 42% more awesome!"
 })
 Helpers
  16. FAKE #r @"FAKE/tools/FakeLib.dll"
 #load "build-helpers/iOS.fsx"
 
 open Fake
 
 Target

    "ios-build" (fun () ->
 iOS.build "Debug|iPhoneSimulator"
 )
 
 Target "ios-adhoc" (fun () ->
 iOS.build "AdHoc|iPhone"
 )
 
 Target "ios-testflight" (fun () ->
 iOS.publishToTestFlight()
 )
 
 "ios-adhoc"
 ==> "ios-testflight"
 
 RunTarget()
 TeamCityHelper.PublishArtifact "path/to/App.zip"
 TeamCityHelper.sendTeamCityNUnitImport "results.xml"
 HipChatNotification(fun p ->
 {p with 
 From = "App BuildBot"
 Message = "Published to TestFlight"
 Color = "green"
 })
 TestFlight(fun p ->
 {p with
 File: "path/to/App.app"
 Notes: "Now with 42% more awesome!"
 })
 Helpers
  17. FAKE Helpers for Xamarin “path/to/MyApp.sln“ |> RestoreComponents (fun defaults ->

    {defaults with ToolPath = “...” })
 iOSBuild (fun defaults ->
 {defaults with
 ProjectPath = “path/to/MyApp.sln”
 Configuration = “AppStore”
 Target = “Build”
 })

  18. FAKE Helpers for Xamarin iOSBuild (fun defaults ->
 {defaults with


    ProjectPath = “path/to/MyApp.sln”
 Configuration = “AppStore”
 Target = “Build”
 })
 “path/to/MyApp.sln“ |> RestoreComponents (fun defaults -> {defaults with ToolPath = “...” })
 AndroidPackage (fun defaults ->
 {defaults with
 ProjectPath = “path/to/MyApp.csproj”
 })
 |> AndroidSignAndAlign (fun defaults ->
 {defaults with
 KeystorePath = “...”
 KeystorePassword = “...”
 KeystoreAlias = “...”
 })
 |> fun file -> TeamCityHelper.PublishArtifact file.FullName

  19. Git / GitHub ▪ Feature branches ▪ Every app builds

    on every branch ▪ Any branch can be pushed to TestFlight ▪ Pull Requests for code review