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
データ資産をシームレスに伝達するためのイベント駆動型アーキテクチャ
kakehashi
PRO
2
230
室長と気ままに学ぶマイクロソフトのビジネスアプリケーションとビジネスプロセス
ryoheig0405
0
320
AndroidXR 開発ツールごとの できることできないこと
donabe3
0
110
モノレポ開発のエラー、誰が見る?Datadog で実現する適切なトリアージとエスカレーション
biwashi
6
770
エンジニアのためのドキュメント力基礎講座〜構造化思考から始めよう〜(2025/02/15jbug広島#15発表資料)
yasuoyasuo
15
5.5k
プロセス改善による品質向上事例
tomasagi
1
1.6k
株式会社EventHub・エンジニア採用資料
eventhub
0
4.2k
個人開発から公式機能へ: PlaywrightとRailsをつなげた3年の軌跡
yusukeiwaki
11
2.7k
トラシューアニマルになろう ~開発者だからこそできる、安定したサービス作りの秘訣~
jacopen
2
1.5k
Classmethod AI Talks(CATs) #15 司会進行スライド(2025.02.06) / classmethod-ai-talks-aka-cats_moderator-slides_vol15_2025-02-06
shinyaa31
0
170
君も受託系GISエンジニアにならないか
sudataka
2
370
All you need to know about InnoDB Primary Keys
lefred
0
120
Featured
See All Featured
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
27
1.9k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
4
400
Building Adaptive Systems
keathley
40
2.4k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
99
18k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
A designer walks into a library…
pauljervisheath
205
24k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
20
2.4k
Faster Mobile Websites
deanohume
306
31k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
Why You Should Never Use an ORM
jnunemaker
PRO
55
9.2k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
44
9.4k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.4k
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