Riga Dev Day - Automated Android Continuous Integration
-
Upload
nicolas-frankel -
Category
Software
-
view
12.565 -
download
3
Transcript of Riga Dev Day - Automated Android Continuous Integration
![Page 1: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/1.jpg)
AUTOMATED ANDROID CONTINUOUS INTEGRATION: HOW HARD CAN IT BE?@NICOLAS_FRANKEL
![Page 2: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/2.jpg)
@nicolas_frankel #springboot 2
ME, MYSELF AND I Backend Java Developer• As consultant
![Page 3: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/3.jpg)
@nicolas_frankel #springboot 3
HYBRIS, AN SAP COMPANY
![Page 4: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/4.jpg)
THE EXISTING ORGANIZATION
Software Factory
Mobile Dev Team
![Page 5: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/5.jpg)
THE REAL ORGANIZATION
Software Factory
Mobile Dev Team
![Page 6: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/6.jpg)
THE EXISTING SITUATION
![Page 7: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/7.jpg)
SOFTWARE INSTALL AUTOMATION
![Page 8: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/8.jpg)
SOFTWARE INSTALL AUTOMATION
![Page 9: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/9.jpg)
JENKINS JOB CONFIGURATIONNo central registry• Stored in XML• In each job’s folder
![Page 10: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/10.jpg)
WHAT WE DIDAnalyzed the config of an existing jobDivided it into snippetsCreated Puppet template for eachAssembled and filled in snippets through classes
![Page 11: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/11.jpg)
WHAT WE DIDCreation of a Jenkins DSL in Puppet
fail!
![Page 12: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/12.jpg)
WHY FAIL?Time-consumingError-proneFragile• Implementation details
Reinventing the wheel
![Page 13: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/13.jpg)
ALTERNATIVESJenkins Job Builder• Part of OpenStack•DSL that calls Jenkins API
• YAML configuration
![Page 14: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/14.jpg)
SOFTWARE INSTALL AUTOMATION
DONE!
![Page 15: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/15.jpg)
DEPENDENCIES
![Page 16: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/16.jpg)
THE CHALLENGE
![Page 17: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/17.jpg)
ISSUES
1. Gradle Wrapper2. Robolectric3. Android
platforms/extra/add-ons
![Page 18: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/18.jpg)
JENKINS GRADLE PLUGIN
![Page 19: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/19.jpg)
GRADLE ISSUE./gradlew xxx
![Page 20: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/20.jpg)
GRADLE WRAPPERMade of:•A JAR•A property
Downloads the required version from the Internet
![Page 21: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/21.jpg)
GRADLE-WRAPPER.PROPERTIESdistributionUrl=https\://services.gradle.org/distributions/gradle-2.3-bin.zip
![Page 22: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/22.jpg)
THE ROOT ISSUEThe proxy…
![Page 23: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/23.jpg)
REQUIREMENTArtifactoryNexusSimple Web Server?
![Page 24: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/24.jpg)
UPDATED GRADLE-WRAPPER.PROPERTIESdistributionUrl=https\://intranet.mydomain.org/org/gradle/gradle-2.3-bin.zip
![Page 25: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/25.jpg)
GRADLE ISSUE./gradlew xxx
DONE!
![Page 26: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/26.jpg)
ROBOLECTRIC ISSUE./gradlew test
![Page 27: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/27.jpg)
AN ERROR!?Error:Could not HEAD 'http://repo1.maven.org/maven2/org/robolectric/robolectric-gradle-plugin/0.12.0/robolectric-gradle-plugin-0.12.0.jar'. Received status code 407 from server: AuthorizedOnly
![Page 28: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/28.jpg)
GRADLE.PROPERTIESsystemProp.http.proxyHost=mydomain.orgsystemProp.http.proxyPort=8080systemProp.http.proxyUser=usersystemProp.http.proxyPassword=password
![Page 29: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/29.jpg)
WTF!?... SAME ERROR
![Page 30: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/30.jpg)
Y U ROBOLECTRIC?public class RobolectricTestRunner {
protected DependencyResolver getJarResolver() { if (dependencyResolver == null) { if (Boolean.getBoolean("robolectric.offline")) { String dependencyDir = System.getProperty( "robolectric.dependency.dir", "."); dependencyResolver = new LocalDependencyResolver( new File(dependencyDir)); } else { File cacheDir = new File(new File( System.getProperty("java.io.tmpdir")), "robolectric");
if (cacheDir.exists() || cacheDir.mkdir()) { Logger.info( "Dependency cache location: %s", cacheDir.getAbsolutePath()); dependencyResolver = new CachedDependencyResolver( new MavenDependencyResolver(), cacheDir, 60 * 60 * 24 * 1000); } else { dependencyResolver = new MavenDependencyResolver(); } } } }
![Page 31: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/31.jpg)
Y U ROBOLECTRIC?<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.robolectric</groupId> <artifactId>robolectric-parent</artifactId> <version>3.1-SNAPSHOT</version> </parent> <artifactId>robolectric</artifactId> <dependencies>... <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-ant-tasks</artifactId> <version>2.1.3</version> <exclusions> <exclusion> <groupId>*</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> </dependencies></project>
![Page 32: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/32.jpg)
Y U ROBOLECTRIC?“Robolectric downloads a version of Android at runtime that's built specifically for running tests. Each API level is ~40mb, so producing a single jar file that includes everything would be prohibitive. All of the artifacts are available on maven central under the coordinates:org.robolectric:android-all. You can grab the API levels from maven central and use them with offline mode.”
https://groups.google.com/forum/#!topic/robolectric/nJgHtdbkpi8
![Page 33: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/33.jpg)
Y U ROBOLECTRIC?Uses a custom class loaderEither:•Download dependencies
beforehand•Override method• Pass through proxy
![Page 34: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/34.jpg)
YOUR OWN TEST RUNNER@Overrideprotected DependencyResolver getJarResolver() { if (this.dependencyResolver == null) { if (Boolean.getBoolean("robolectric.offline")) { String cacheDir = System.getProperty( "robolectric.dependency.dir", "."); this.dependencyResolver = new LocalDependencyResolver( new File(cacheDir)); } else { this.dependencyResolver = new MyResolver(); } } return this.dependencyResolver;}
![Page 35: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/35.jpg)
YOUR OWN RESOLVERpublic class MyResolver extends MavenDependencyResolver { @Override protected void configureMaven( DependenciesTask task) { RemoteRepository remoteRepository = new RemoteRepository(); remoteRepository.setId("My Maven repo"); remoteRepository.setUrl(BuildConfig.NEXUS_URL); task.addConfiguredRemoteRepository( remoteRepository); }}
![Page 36: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/36.jpg)
ROBOLECTRIC ISSUE./gradlew test
DONE!
![Page 37: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/37.jpg)
ANDROID SDK ISSUEandroid update sdk
![Page 38: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/38.jpg)
ANDROID SDK ISSUEandroid update sdk -u
Non interactive mode
![Page 39: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/39.jpg)
2 ISSUESSet the proxyAccept license agreements
![Page 40: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/40.jpg)
ANDROID SDK --HELPAction "update sdk": Updates the SDK by suggesting new platforms to install if available.Options: -f --force : Forces replacement of a package or its parts, even if something has been modified. -n --dry-mode : Simulates the update but does not download or install anything. --proxy-host: HTTP/HTTPS proxy host (overrides settings if defined) -s --no-https : Uses HTTP instead of HTTPS (the default) for downloads. -t --filter : A filter that limits the update to the specified types of packages in the form of a comma-separated list of [platform, system-image, tool, platform-tool, doc, sample, source]. This also accepts the identifiers returned by 'list sdk --extended'. -u --no-ui : Updates from command-line (does not display the GUI) --proxy-port: HTTP/HTTPS proxy port (overrides settings if defined) -p --obsolete : Deprecated. Please use --all instead. -a --all : Includes all packages (such as obsolete and non-dependent ones.)
![Page 41: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/41.jpg)
WTF?!!?Accepts proxy parametersBut no authentication…
![Page 42: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/42.jpg)
SOLUTIONS (THANKS GOOGLE FOR NOTHING)
Environments variablesSpecific credential fileLocal proxy
![Page 43: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/43.jpg)
A WORKING SOLUTION: EXPECTLinux binaryOriginally for testing purposeScript input in regard to output
![Page 44: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/44.jpg)
(VERY) SIMPLE EXPECT SCRIPT#!/usr/bin/expecteval spawn jot -r 1 0 1expect { "0" { puts "zero" } "1" { puts "one" }}
![Page 45: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/45.jpg)
THE “REAL” SCRIPT#!/bin/bashexpect -d -c 'log_file /var/log/update-android.logset timeout -1spawn <%= @android_sdk_dir %>/tools/android -v update sdk -a -u -f --proxy-host\ <%= @proxy_host %> --proxy-port <%= @proxy_port %> -t <%= @joined_packages %>while {1} { expect { "Login:" { send "<%= @proxy_user %>\r" } "Password:" { send "<%= @proxy_password %>\r" } "Workstation:" { send "\r" } "Domain:" { send "\r" } -re ".*\[y\/n\]:" { send "y\r" } }}'
Handles the proxy
Handles license agreements
![Page 46: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/46.jpg)
ANDROID SDK ISSUEandroid update sdk -u
DONE!
![Page 47: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/47.jpg)
ANDROID CONTINUOUS INTEGRATION?Not mature• Lags behind “standard” Java
So time-consuming…• But possible!
![Page 48: Riga Dev Day - Automated Android Continuous Integration](https://reader035.fdocuments.net/reader035/viewer/2022062900/58e791eb1a28ab0d288b5333/html5/thumbnails/48.jpg)
48
Q&A
@nicolas_frankel
http://blog.frankel.ch/@nicolas_frankel http://frankel.in/