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
410
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
3
130
Becoming and Staying a Productive Developer with Build Scans, Build Validation Scripts and Gradle
runningcode
1
62
Keeping your Gradle builds in top shape
runningcode
1
300
Keeping your team in top shape with the Gradle Enterprise API
runningcode
3
390
What is the Android Cache Fix plugin and why do I need to solve my own cache misses.
runningcode
1
220
What is the Android Cache Fix plugin and why do I need to solve my own cache misses.
runningcode
1
490
Perspectives from a Solutions Engineer
runningcode
1
520
Beyond Modularization: Scaling your Android Build with Gradle
runningcode
9
2.6k
Secrets of the Build Scan Plugin - Virtual Android Makers 2020
runningcode
0
380
Other Decks in Technology
See All in Technology
事業貢献を考えるための技術改善の目標設計と改善実績 / Targeted design of technical improvements to consider business contribution and improvement performance
oomatomo
0
100
プロダクト開発を加速させるためのQA文化の築き方 / How to build QA culture to accelerate product development
mii3king
1
270
統計データで2024年の クラウド・インフラ動向を眺める
ysknsid25
2
850
サービスでLLMを採用したばっかりに振り回され続けたこの一年のあれやこれや
segavvy
2
500
C++26 エラー性動作
faithandbrave
2
780
10分で学ぶKubernetesコンテナセキュリティ/10min-k8s-container-sec
mochizuki875
3
360
DUSt3R, MASt3R, MASt3R-SfM にみる3D基盤モデル
spatial_ai_network
2
190
マイクロサービスにおける容易なトランザクション管理に向けて
scalar
0
140
20241214_WACATE2024冬_テスト設計技法をチョット俯瞰してみよう
kzsuzuki
3
590
サイバー攻撃を想定したセキュリティガイドライン 策定とASM及びCNAPPの活用方法
syoshie
3
1.3k
1等無人航空機操縦士一発試験 合格までの道のり ドローンミートアップ@大阪 2024/12/18
excdinc
0
170
NilAway による静的解析で「10 億ドル」を節約する #kyotogo / Kyoto Go 56th
ytaka23
3
380
Featured
See All Featured
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
810
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
The Pragmatic Product Professional
lauravandoore
32
6.3k
Practical Orchestrator
shlominoach
186
10k
Intergalactic Javascript Robots from Outer Space
tanoku
270
27k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
26
1.5k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Put a Button on it: Removing Barriers to Going Fast.
kastner
59
3.6k
Java REST API Framework Comparison - PWX 2021
mraible
28
8.3k
Optimizing for Happiness
mojombo
376
70k
KATA
mclloyd
29
14k
A Modern Web Designer's Workflow
chriscoyier
693
190k
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/