riga dev day - automated android continuous integration

48
AUTOMATED ANDROID CONTINUOUS INTEGRATION: HOW HARD CAN IT BE? @NICOLAS_FRANKEL

Upload: nicolas-frankel

Post on 07-Apr-2017

12.562 views

Category:

Software


3 download

TRANSCRIPT

Page 1: Riga Dev Day - Automated Android Continuous Integration

AUTOMATED ANDROID CONTINUOUS INTEGRATION: HOW HARD CAN IT BE?@NICOLAS_FRANKEL

Page 2: Riga Dev Day - Automated Android Continuous Integration

@nicolas_frankel #springboot 2

ME, MYSELF AND I Backend Java Developer• As consultant

Page 3: Riga Dev Day - Automated Android Continuous Integration

@nicolas_frankel #springboot 3

HYBRIS, AN SAP COMPANY

Page 4: Riga Dev Day - Automated Android Continuous Integration

THE EXISTING ORGANIZATION

Software Factory

Mobile Dev Team

Page 5: Riga Dev Day - Automated Android Continuous Integration

THE REAL ORGANIZATION

Software Factory

Mobile Dev Team

Page 6: Riga Dev Day - Automated Android Continuous Integration

THE EXISTING SITUATION

Page 7: Riga Dev Day - Automated Android Continuous Integration

SOFTWARE INSTALL AUTOMATION

Page 8: Riga Dev Day - Automated Android Continuous Integration

SOFTWARE INSTALL AUTOMATION

Page 9: Riga Dev Day - Automated Android Continuous Integration

JENKINS JOB CONFIGURATIONNo central registry• Stored in XML• In each job’s folder

Page 10: Riga Dev Day - Automated Android Continuous Integration

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

WHAT WE DIDCreation of a Jenkins DSL in Puppet

fail!

Page 12: Riga Dev Day - Automated Android Continuous Integration

WHY FAIL?Time-consumingError-proneFragile• Implementation details

Reinventing the wheel

Page 13: Riga Dev Day - Automated Android Continuous Integration

ALTERNATIVESJenkins Job Builder• Part of OpenStack•DSL that calls Jenkins API

• YAML configuration

Page 14: Riga Dev Day - Automated Android Continuous Integration

SOFTWARE INSTALL AUTOMATION

DONE!

Page 15: Riga Dev Day - Automated Android Continuous Integration

DEPENDENCIES

Page 16: Riga Dev Day - Automated Android Continuous Integration

THE CHALLENGE

Page 17: Riga Dev Day - Automated Android Continuous Integration

ISSUES

1. Gradle Wrapper2. Robolectric3. Android

platforms/extra/add-ons

Page 18: Riga Dev Day - Automated Android Continuous Integration

JENKINS GRADLE PLUGIN

Page 19: Riga Dev Day - Automated Android Continuous Integration

GRADLE ISSUE./gradlew xxx

Page 20: Riga Dev Day - Automated Android Continuous Integration

GRADLE WRAPPERMade of:•A JAR•A property

Downloads the required version from the Internet

Page 21: Riga Dev Day - Automated Android Continuous Integration

GRADLE-WRAPPER.PROPERTIESdistributionUrl=https\://services.gradle.org/distributions/gradle-2.3-bin.zip

Page 22: Riga Dev Day - Automated Android Continuous Integration

THE ROOT ISSUEThe proxy…

Page 23: Riga Dev Day - Automated Android Continuous Integration

REQUIREMENTArtifactoryNexusSimple Web Server?

Page 24: Riga Dev Day - Automated Android Continuous Integration

UPDATED GRADLE-WRAPPER.PROPERTIESdistributionUrl=https\://intranet.mydomain.org/org/gradle/gradle-2.3-bin.zip

Page 25: Riga Dev Day - Automated Android Continuous Integration

GRADLE ISSUE./gradlew xxx

DONE!

Page 26: Riga Dev Day - Automated Android Continuous Integration

ROBOLECTRIC ISSUE./gradlew test

Page 27: Riga Dev Day - Automated Android Continuous Integration

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

GRADLE.PROPERTIESsystemProp.http.proxyHost=mydomain.orgsystemProp.http.proxyPort=8080systemProp.http.proxyUser=usersystemProp.http.proxyPassword=password

Page 29: Riga Dev Day - Automated Android Continuous Integration

WTF!?... SAME ERROR

Page 30: Riga Dev Day - Automated Android Continuous Integration

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

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

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

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

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

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

ROBOLECTRIC ISSUE./gradlew test

DONE!

Page 37: Riga Dev Day - Automated Android Continuous Integration

ANDROID SDK ISSUEandroid update sdk

Page 38: Riga Dev Day - Automated Android Continuous Integration

ANDROID SDK ISSUEandroid update sdk -u

Non interactive mode

Page 39: Riga Dev Day - Automated Android Continuous Integration

2 ISSUESSet the proxyAccept license agreements

Page 40: Riga Dev Day - Automated Android Continuous Integration

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

WTF?!!?Accepts proxy parametersBut no authentication…

Page 42: Riga Dev Day - Automated Android Continuous Integration

SOLUTIONS (THANKS GOOGLE FOR NOTHING)

Environments variablesSpecific credential fileLocal proxy

Page 43: Riga Dev Day - Automated Android Continuous Integration

A WORKING SOLUTION: EXPECTLinux binaryOriginally for testing purposeScript input in regard to output

Page 44: Riga Dev Day - Automated Android Continuous Integration

(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

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

ANDROID SDK ISSUEandroid update sdk -u

DONE!

Page 47: Riga Dev Day - Automated Android Continuous Integration

ANDROID CONTINUOUS INTEGRATION?Not mature• Lags behind “standard” Java

So time-consuming…• But possible!

Page 48: Riga Dev Day - Automated Android Continuous Integration

48

Q&A

@nicolas_frankel

http://blog.frankel.ch/@nicolas_frankel http://frankel.in/