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
Pro builds in your small startup (Berlindroid 2...
Search
Nelson Osacky
November 29, 2017
Technology
2
450
Pro builds in your small startup (Berlindroid 29-Nov-2017)
How we scaled our build system at Zenjob.
Nelson Osacky
November 29, 2017
Tweet
Share
More Decks by Nelson Osacky
See All by Nelson Osacky
Develocity Reporting and Visualization
runningcode
4
180
Becoming and Staying a Productive Developer with Build Scans, Build Validation Scripts and Gradle
runningcode
1
80
Keeping your Gradle builds in top shape
runningcode
1
330
Keeping your team in top shape with the Gradle Enterprise API
runningcode
3
410
What is the Android Cache Fix plugin and why do I need to solve my own cache misses.
runningcode
1
250
What is the Android Cache Fix plugin and why do I need to solve my own cache misses.
runningcode
1
520
Perspectives from a Solutions Engineer
runningcode
1
550
Beyond Modularization: Scaling your Android Build with Gradle
runningcode
9
2.8k
Secrets of the Build Scan Plugin - Virtual Android Makers 2020
runningcode
0
420
Other Decks in Technology
See All in Technology
Bill One 開発エンジニア 紹介資料
sansan33
PRO
4
12k
JSX - 歴史を振り返り、⾯⽩がって、エモくなろう
pal4de
3
910
比起獨自升級 我更喜歡 DevOps 文化 <3
line_developers_tw
PRO
0
220
Definition of Done
kawaguti
PRO
4
190
上長や社内ステークホルダーに対する解像度を上げて、より良い補完関係を築く方法 / How-to-increase-resolution-and-build-better-complementary-relationships-with-your-bosses-and-internal-stakeholders
madoxten
13
7.7k
Cloud Native Scalability for Internal Developer Platforms
hhiroshell
2
460
CIでのgolangci-lintの実行を約90%削減した話
kazukihayase
0
290
RubyOnRailsOnDevin+α / DevinMeetupJapan#2
ginkouno
0
450
Perk アプリの技術選定とリリースから1年弱経ってのふりかえり
stomk
0
100
What's new in OpenShift 4.19
redhatlivestreaming
1
260
Javalinの紹介
notoh
0
110
DB 醬,嗨!哪泥嘎斯基?
line_developers_tw
PRO
0
220
Featured
See All Featured
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.8k
Testing 201, or: Great Expectations
jmmastey
42
7.5k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
16
920
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
48
5.4k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
50k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
The Cost Of JavaScript in 2023
addyosmani
50
8.4k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.5k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Agile that works and the tools we love
rasmusluckow
329
21k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
281
13k
Transcript
Pro builds in your small startup Nelson Osacky
About me • Android developer since before Uni • New
to Berlin - Started working in September • Formerly at Square in San Francisco • Worked on Reader Experience, Square Register and build systems: Buck
Every build is a special snowflake
In the beginning there were no tests, no CI…
None
None
Why Travis? • Other engineering teams at Zenjob teams were
already using it • Integrates easily with GitHub • Good Android examples and documentation • There’s a million options, this isn’t really the point.
How to add Travis? language: android jdk: - oraclejdk8 android:
components: - tools - platform-tools - tools - build-tools-25.0.0 - android-26 script: ./gradlew assemble check notifications: email: false cache: directories: - $HOME/.gradle
Only ran checkstyle and unit tests
Next step: Boot emulator before_install: - start emulator install:
./gradlew assemble before_script: android-wait-for-emulator script: ./gradlew check connectedCheck
before_install: # Install the system image. - sdkmanager “system-images;android-19;default;armeabi-v7a" #
Create and start emulator for the script. # Meant to race the install task. - echo no | avdmanager create avd --force -n test -k "system- images;android-19;default;armeabi-v7a" - $ANDROID_HOME/emulator/emulator -avd test -no-audio -no-window &
Travis takes: 15 min 13 sec
Next: Run UI tests
Hard to debug • Button isn’t visible? Why? • No
screenshots • Spoon doesn’t support AGP 3.0 (yet) • Screenshot on failure is tricky • Unsolved problem
After enabling our first UI test
None
2 tests later
None
Soon we had a problem
None
Make the tests faster • Replace SystemClock.sleep() in tests with
Espresso idling resources • Replace real API calls with mock API calls • Make mock API calls return instantly
Success…?
None
Time to try something else
AWS Device Farm
• AWS Device Lab failed with cryptic error and no
support • AWS Device Lab $10/hr • Firebase Test Lab $1/hr virtual and $5/hr real devices
Easy Decision
So much faster!
Why faster? • Do not have to download or install
emulator • Emulator doesn’t slow down the rest of the build • Tests are now run on faster emulator
None
111 secs = 1m 51 secs
None
Can we go faster?
if [ "$COMPONENT" == "checkstyle" ]; then ./gradlew checkstyle elif
[ "$COMPONENT" == "unit" ]; then ./gradlew test elif [ "$COMPONENT" == "lint" ]; then ./gradlew lint elif [ "$COMPONENT" == "release" ]; then ./gradlew assembleRelease elif [ "$COMPONENT" == "instrumentation" ]; then ./gradlew assembleDebug assembleAndroidTest .travis/run-ui-tests.sh else echo "This module doesn't exist" exit 1 fi
None
Yes, but…
Faster individual builds but slower with multiple builds.
if [ "$COMPONENT" == "build" ]; then ./gradlew checkstyle check
assembleRelease elif [ "$COMPONENT" == "instrumentation" ]; then ./gradlew assembleDebug assembleAndroidTest .travis/run-ui-tests.sh else echo "This module doesn't exist" exit 1 fi
None
Less is more!
Problems solved!
…but then we wrote more UI tests
None
60+ Tests, 11 mins
Sharding?
Flank!
• https://github.com/TestArmada/flank • Splits up UI tests amongst Firebase Test
Lab devices • Splits up tests to minimize costs
Test time stays constant
None
Prints out cost
Still one problem; manual uploads
Automation
before_deploy: # Verify that the apk was signed. - apksigner
verify -v app/build/outputs/apk/release/app-release.apk # Publish to GitHub releases only on tagged commits. deploy: provider: releases api_key: secure: blah-blah-blah file: - "app/build/outputs/apk/debug/app-debug.apk" - "app/build/outputs/mapping/release/mapping.txt" - "app/build/outputs/apk/release/app-release.apk" skip_cleanup: true on: tags: true condition: $COMPONENT = build # Publish to Google Play after successful deployment to GitHub releases. after_deploy: - ./gradlew publishApkRelease
before_deploy: # Verify that the apk was signed. - apksigner
verify -v app/build/outputs/apk/release/ app-release.apk
before_deploy: # Verify that the apk was signed. - apksigner
verify -v app/build/outputs/apk/release/app-release.apk # Publish to GitHub releases only on tagged commits. deploy: provider: releases api_key: secure: blah-blah-blah file: - "app/build/outputs/apk/debug/app-debug.apk" - "app/build/outputs/mapping/release/mapping.txt" - "app/build/outputs/apk/release/app-release.apk" skip_cleanup: true on: tags: true condition: $COMPONENT = build # Publish to Google Play after successful deployment to GitHub releases. after_deploy: - ./gradlew publishApkRelease
# Publish to GitHub releases only on tagged commits. deploy:
provider: releases api_key: secure: blah-blah-blah file: - "app/build/outputs/apk/debug/app-debug.apk" - "app/build/outputs/mapping/release/mapping.txt" - "app/build/outputs/apk/release/app-release.apk" skip_cleanup: true on: tags: true condition: $COMPONENT = build
before_deploy: # Verify that the apk was signed. - apksigner
verify -v app/build/outputs/apk/release/app-release.apk # Publish to GitHub releases only on tagged commits. deploy: provider: releases api_key: secure: blah-blah-blah file: - "app/build/outputs/apk/debug/app-debug.apk" - "app/build/outputs/mapping/release/mapping.txt" - "app/build/outputs/apk/release/app-release.apk" skip_cleanup: true on: tags: true condition: $COMPONENT = build # Publish to Google Play after successful deployment to GitHub releases. after_deploy: - ./gradlew publishApkRelease
None
None
Automatic upload to the play store
apply plugin: 'com.github.triplet.play' android { playAccountConfigs { defaultAccountConfig { jsonFile
= file('keys.json') } } defaultConfig { playAccountConfig = playAccountConfigs.defaultAccountConfig } }
before_deploy: # Verify that the apk was signed. - apksigner
verify -v app/build/outputs/apk/release/app-release.apk # Publish to GitHub releases only on tagged commits. deploy: provider: releases api_key: secure: blah-blah-blah file: - "app/build/outputs/apk/debug/app-debug.apk" - "app/build/outputs/mapping/release/mapping.txt" - "app/build/outputs/apk/release/app-release.apk" skip_cleanup: true on: tags: true condition: $COMPONENT = build # Publish to Google Play after successful deployment to GitHub releases. after_deploy: - ./gradlew publishApkRelease
# Publish to Google Play after successful deployment to GitHub
releases. after_deploy: - ./gradlew publishApkRelease
None
TODOs • Automate bumping version numbers • Run UI tests
on more real devices with different APIs before release • Move to AWS or another service with faster machines
TODOs • Screenshots on failure ( should be built in)
• Gradle plugin for Firebase tests • Gradle plugin for Flank (for running locally)
TODOs • Merge on green button • Automate release branch
cutting • Speed up local builds (Buck?)
Thank you
[email protected]
https://www.zenjob.de/careers/