Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
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
470
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
Android Dev to Backend Polyglot
runningcode
1
17
Develocity Reporting and Visualization
runningcode
4
210
Becoming and Staying a Productive Developer with Build Scans, Build Validation Scripts and Gradle
runningcode
1
90
Keeping your Gradle builds in top shape
runningcode
1
350
Keeping your team in top shape with the Gradle Enterprise API
runningcode
3
440
What is the Android Cache Fix plugin and why do I need to solve my own cache misses.
runningcode
1
260
What is the Android Cache Fix plugin and why do I need to solve my own cache misses.
runningcode
1
540
Perspectives from a Solutions Engineer
runningcode
1
570
Beyond Modularization: Scaling your Android Build with Gradle
runningcode
9
2.9k
Other Decks in Technology
See All in Technology
eBPFとwaruiBPF
sat
PRO
2
930
形式手法特論:CEGAR を用いたモデル検査の状態空間削減 #kernelvm / Kernel VM Study Hokuriku Part 8
ytaka23
1
140
シンプルを極める。アンチパターンなDB設計の本質
facilo_inc
1
1k
著者と読み解くAIエージェント現場導入の勘所 Lancers TechBook#2
smiyawaki0820
7
2.8k
モバイルゲーム開発におけるエージェント技術活用への試行錯誤 ~開発効率化へのアプローチの紹介と未来に向けた展望~
qualiarts
0
280
GitLab Duo Agent Platformで実現する“AI駆動・継続的サービス開発”と最新情報のアップデート
jeffi7
0
150
手動から自動へ、そしてその先へ
moritamasami
0
180
なぜ使われないのか?──定量×定性で見極める本当のボトルネック
kakehashi
PRO
1
760
Claude Code はじめてガイド -1時間で学べるAI駆動開発の基本と実践-
oikon48
42
25k
MCP・A2A概要 〜Google Cloudで構築するなら〜
shukob
0
160
事業部のプロジェクト進行と開発チームの改善の “時間軸" のすり合わせ
konifar
9
2.8k
.NET 10 のパフォーマンス改善
nenonaninu
2
4.7k
Featured
See All Featured
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.2k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Side Projects
sachag
455
43k
How to train your dragon (web standard)
notwaldorf
97
6.4k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.3k
Product Roadmaps are Hard
iamctodd
PRO
55
12k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.3k
Practical Orchestrator
shlominoach
190
11k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
54k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
8.3k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
37
2.6k
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
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/