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
780
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
150
Observability-Driven Development: What DevOps is Really About
gshackles
1
270
Monitoring Your Mobile Apps in the Wild
gshackles
1
82
Building Scalable Applications with the Actor Model
gshackles
0
580
Creating a Voice-Driven TV Remote with Azure and Alexa
gshackles
0
97
Build 2017 Recap for Xamarin Developers
gshackles
0
95
Going Serverless: Event-Driven Architecture Without The Infrastructure
gshackles
0
160
Evolve 2016 Redux
gshackles
0
130
Instrumenting Your Mobile Monitoring Strategy
gshackles
0
4.6k
Other Decks in Technology
See All in Technology
急成長する企業で作った、エンジニアが輝ける制度/ 20250214 Rinto Ikenoue
shift_evolve
2
880
Moved to https://speakerdeck.com/toshihue/presales-engineer-career-bridging-tech-biz-ja
toshihue
2
550
室長と気ままに学ぶマイクロソフトのビジネスアプリケーションとビジネスプロセス
ryoheig0405
0
320
20250208_OpenAIDeepResearchがやばいという話
doradora09
PRO
0
170
10分で紹介するAmazon Bedrock利用時のセキュリティ対策 / 10-minutes introduction to security measures when using Amazon Bedrock
hideakiaoyagi
0
170
バックエンドエンジニアのためのフロントエンド入門 #devsumiC
panda_program
16
6.5k
【Developers Summit 2025】プロダクトエンジニアから学ぶ、 ユーザーにより高い価値を届ける技術
niwatakeru
2
890
マルチモーダル理解と生成の統合 DeepSeek Janus, etc... / Multimodal Understanding and Generation Integration
hiroga
0
360
地方拠点で エンジニアリングマネージャーってできるの? 〜地方という制約を楽しむオーナーシップとコミュニティ作り〜
1coin
1
130
まだ間に合う! エンジニアのための生成AIアプリ開発入門 on AWS
minorun365
PRO
4
580
現場の種を事業の芽にする - エンジニア主導のイノベーションを事業戦略に装着する方法 -
kzkmaeda
2
1.5k
開発者が自律的に AWS Security Hub findings に 対応する仕組みと AWS re:Invent 2024 登壇体験談 / Developers autonomously report AWS Security Hub findings Corresponding mechanism and AWS re:Invent 2024 presentation experience
kaminashi
0
190
Featured
See All Featured
4 Signs Your Business is Dying
shpigford
182
22k
Fashionably flexible responsive web design (full day workshop)
malarkey
406
66k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Being A Developer After 40
akosma
89
590k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
27
1.5k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
27
1.9k
How GitHub (no longer) Works
holman
313
140k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Typedesign – Prime Four
hannesfritz
40
2.5k
Facilitating Awesome Meetings
lara
51
6.2k
Gamification - CAS2011
davidbonilla
80
5.1k
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