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
460
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
200
Becoming and Staying a Productive Developer with Build Scans, Build Validation Scripts and Gradle
runningcode
1
87
Keeping your Gradle builds in top shape
runningcode
1
340
Keeping your team in top shape with the Gradle Enterprise API
runningcode
3
420
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
530
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
430
Other Decks in Technology
See All in Technology
5分でカオスエンジニアリングを分かった気になろう
pandayumi
0
260
RSCの時代にReactとフレームワークの境界を探る
uhyo
11
3.5k
「全員プロダクトマネージャー」を実現する、Cursorによる仕様検討の自動運転
applism118
22
12k
バイブスに「型」を!Kent Beckに学ぶ、AI時代のテスト駆動開発
amixedcolor
3
590
テストを軸にした生き残り術
kworkdev
PRO
0
220
Modern Linux
oracle4engineer
PRO
0
160
下手な強制、ダメ!絶対! 「ガードレール」を「檻」にさせない"ガバナンス"の取り方とは?
tsukaman
2
460
slog.Handlerのよくある実装ミス
sakiengineer
4
480
AIエージェント開発用SDKとローカルLLMをLINE Botと組み合わせてみた / LINEを使ったLT大会 #14
you
PRO
0
130
AWSを利用する上で知っておきたい名前解決のはなし(10分版)
nagisa53
10
3.2k
react-callを使ってダイヤログをいろんなとこで再利用しよう!
shinaps
2
270
Android Audio: Beyond Winning On It
atsushieno
0
3.4k
Featured
See All Featured
How GitHub (no longer) Works
holman
315
140k
Building an army of robots
kneath
306
46k
Docker and Python
trallard
46
3.6k
Site-Speed That Sticks
csswizardry
10
820
Visualization
eitanlees
148
16k
Rebuilding a faster, lazier Slack
samanthasiow
83
9.2k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
930
The Invisible Side of Design
smashingmag
301
51k
Imperfection Machines: The Place of Print at Facebook
scottboms
268
13k
Automating Front-end Workflow
addyosmani
1370
200k
Gamification - CAS2011
davidbonilla
81
5.4k
Bash Introduction
62gerente
615
210k
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/