Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Using Continuous Integration with Xamarin Apps
Search
Greg Shackles
October 08, 2014
Technology
1
790
Using Continuous Integration with Xamarin Apps
Presented at Xamarin Evolve 2014
Greg Shackles
October 08, 2014
Tweet
Share
More Decks by Greg Shackles
See All by Greg Shackles
Building Modern Services with .NET Core 3 and gRPC
gshackles
0
170
Observability-Driven Development: What DevOps is Really About
gshackles
1
280
Monitoring Your Mobile Apps in the Wild
gshackles
1
92
Building Scalable Applications with the Actor Model
gshackles
0
610
Creating a Voice-Driven TV Remote with Azure and Alexa
gshackles
0
110
Build 2017 Recap for Xamarin Developers
gshackles
0
120
Going Serverless: Event-Driven Architecture Without The Infrastructure
gshackles
0
180
Evolve 2016 Redux
gshackles
0
140
Instrumenting Your Mobile Monitoring Strategy
gshackles
0
4.7k
Other Decks in Technology
See All in Technology
Should Our Project Join the CNCF? (Japanese Recap)
whywaita
PRO
0
340
What’s new in Android development tools
yanzm
0
320
AWS Organizations 新機能!マルチパーティ承認の紹介
yhana
1
280
関数型プログラミングで 「脳がバグる」を乗り越える
manabeai
1
190
CRE Camp #1 エンジニアリングを民主化するCREチームでありたい話
mntsq
1
130
【5分でわかる】セーフィー エンジニア向け会社紹介
safie_recruit
0
27k
NewSQLや分散データベースを支えるRaftの仕組み - 仕組みを理解して知る得意不得意
hacomono
PRO
2
170
品質と速度の両立:生成AI時代の品質保証アプローチ
odasho
1
360
生成AI開発案件におけるClineの業務活用事例とTips
shinya337
0
260
SEQUENCE object comparison - db tech showcase 2025 LT2
nori_shinoda
0
150
Reach American Airlines®️ Instantly: 19 Calling Methods for Fast Support in the USA
flyamerican
1
170
Lazy application authentication with Tailscale
bluehatbrit
0
210
Featured
See All Featured
Embracing the Ebb and Flow
colly
86
4.7k
Building Applications with DynamoDB
mza
95
6.5k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.4k
Six Lessons from altMBA
skipperchong
28
3.9k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
34
5.9k
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
How to train your dragon (web standard)
notwaldorf
95
6.1k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
60k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
Adopting Sorbet at Scale
ufuk
77
9.5k
A designer walks into a library…
pauljervisheath
207
24k
Building an army of robots
kneath
306
45k
Transcript
Using Continuous Integration with Xamarin Apps Senior Engineer, Olo @gshackles
[email protected]
Greg Shackles
Ship It A Cautionary Tale
None
None
None
None
None
None
None
The Worst by Vitruvius This app is just…the worst.
None
How can we deliver Continuous Awesomeness?
Continuous Integration Let your tools work for you on every
commit
What is Continuous Integration?
What is Continuous Integration? VCS
What is Continuous Integration? VCS CI Server
What is Continuous Integration? VCS CI Server CI Agent
What is Continuous Integration? VCS CI Server CI Agent
Options TFS Jenkins …and more
Delivery TestFlight HockeyApp …and more
CI with Xamarin Apps
Build Agent Setup
Build Agent Setup ▪ OS X machine for iOS builds
- Mac Mini works well
Build Agent Setup ▪ OS X machine for iOS builds
- Mac Mini works well ▪ OS X or Windows machine for Android
Build Agent Setup ▪ OS X machine for iOS builds
- Mac Mini works well ▪ OS X or Windows machine for Android ▪ Install platform SDKs
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
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
iOS: Build mdtool build -t:Build -c:AppStore MyAwesomeApp.sln /Applications/Xamarin Studio.app/Contents/MacOS/mdtool
iOS: Package zip -r -y MyAwesomeIosApp.zip path/to/MyAwesomeIosApp.app
Android: Build Windows: msbuild OS X: xbuild xbuild build /t:Build
/p:Configuration=Release MyAwesomeApp.sln
Android: Package (Part 1) Windows: msbuild OS X: xbuild xbuild
build /t:PackageForAndroid /p:Configuration=Release MyAwesomeAndroidApp.csproj
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>
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
Package Restore NuGet mono NuGet.exe restore path/to/App.sln
Package Restore NuGet mono NuGet.exe restore path/to/App.sln Xamarin Components mono
xamarin-component.exe restore path/to/App.sln
Xamarin.UITest Run using any NUnit runner nunit-console4 path/to/TestAssembly.dll -xml testresults.xml
Pro Tip: Allow Build to Access UI jetbrains.teamcity.BuildAgent.plist
Pro Tip: Allow Build to Access UI jetbrains.teamcity.BuildAgent.plist ▪ Set
username <key>UserName</key> <string>your_user</string>
Pro Tip: Allow Build to Access UI jetbrains.teamcity.BuildAgent.plist ▪ Set
username <key>UserName</key> <string>your_user</string> ▪ Copy to /Library/LaunchAgents
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
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()
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
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
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
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
FAKE Helpers for Xamarin “path/to/MyApp.sln“ |> RestoreComponents (fun defaults ->
{defaults with ToolPath = “...” })
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” })
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
How We Work At
None
None
None
Git / GitHub ▪ Feature branches ▪ Every app builds
on every branch ▪ Any branch can be pushed to TestFlight ▪ Pull Requests for code review
Test-Driven Core
UI Tests and Test Cloud
Deployment and Distribution
Deployment and Distribution
Deployment and Distribution
Continuous Monitoring
Demo github.com/gshackles/xamarin-ci-sample
Questions? @gshackles
[email protected]
! github.com/gshackles speakerdeck.com/u/gshackles