Skip to content
Permalink
Browse files
added builder properties to directly override envirnoment variables f…
…or ANDROID_HOME and ANDROID_ZIPALIGN so that can be set from a pipeline or dsl script irrespective of JENKINS-35671
  • Loading branch information
restjohn committed Feb 14, 2017
1 parent ae0db0f commit 2a67d3b2fccd83d73e6a6180caf65a9e11c61ebb
@@ -122,7 +122,7 @@ public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath workspace, @Nonnul
env = new EnvVars();
}

ZipalignTool zipalign = new ZipalignTool(env, workspace, listener.getLogger(), zipalignPath);
ZipalignTool zipalign = new ZipalignTool(env, workspace, listener.getLogger(), androidHome, zipalignPath);
Map<String,String> apksToArchive = new LinkedHashMap<>();
int apkCounter = 1;
for (Apk entry : entries) {
@@ -19,22 +19,32 @@

class ZipalignTool {

static final String ENV_ANDROID_HOME = "ANDROID_HOME";
static final String ENV_ZIPALIGN_PATH = "ANDROID_ZIPALIGN";

private static FilePath findFromEnv(EnvVars env, FilePath workspace, PrintStream logger) throws AbortException {

String zipalignPath = env.get("ANDROID_ZIPALIGN");
String zipalignPath = env.get(ENV_ZIPALIGN_PATH);
if (!StringUtils.isEmpty(zipalignPath)) {
zipalignPath = env.expand(zipalignPath);
logger.printf("[SignApksBuilder] found zipalign path in env ANDROID_ZIPALIGN=%s%n", zipalignPath);
logger.printf("[SignApksBuilder] found zipalign path in env %s=%s%n", ENV_ZIPALIGN_PATH, zipalignPath);
return new FilePath(workspace.getChannel(), zipalignPath);
}

String androidHome = env.get("ANDROID_HOME");
String androidHome = env.get(ENV_ANDROID_HOME);
if (StringUtils.isEmpty(androidHome)) {
throw new AbortException("failed to find zipalign: no environment variable ANDROID_ZIPALIGN or ANDROID_HOME");
throw new AbortException("failed to find zipalign: no environment variable " + ENV_ZIPALIGN_PATH + " or " + ENV_ANDROID_HOME);
}

androidHome = env.expand(androidHome);
FilePath buildTools = new FilePath(workspace.getChannel(), androidHome).child("build-tools");

logger.printf("[SignApksBuilder] searching environment variable %s=%s for zipalign...", ENV_ANDROID_HOME, androidHome);

return findInAndroidHome(androidHome, workspace, logger);
}

private static FilePath findInAndroidHome(String androidHome, FilePath workspace, PrintStream logger) throws AbortException {

FilePath buildTools = workspace.child(androidHome).child("build-tools");
List<FilePath> versionDirs;
try {
versionDirs = buildTools.listDirectories();
@@ -47,7 +57,7 @@ private static FilePath findFromEnv(EnvVars env, FilePath workspace, PrintStream
}

if (versionDirs == null || versionDirs.isEmpty()) {
throw new AbortException("failed to find zipalign: no build-tools directory in ANDROID_HOME path " + androidHome);
throw new AbortException("failed to find zipalign: no build-tools directory in Android home path " + androidHome);
}

SortedMap<VersionNumber, FilePath> versions = new TreeMap<>();
@@ -59,51 +69,74 @@ private static FilePath findFromEnv(EnvVars env, FilePath workspace, PrintStream

if (versions.isEmpty()) {
throw new AbortException(
"failed to find zipalign: no build-tools versions in ANDROID_HOME path " + buildTools);
"failed to find zipalign: no build-tools versions in Android home path " + buildTools);
}

VersionNumber latest = versions.lastKey();
buildTools = versions.get(latest);
FilePath zipalign = buildTools.child("zipalign");

logger.printf("[SignApksBuilder] found zipalign in Android SDK's latest build tools: %s%n", zipalign.getRemote());

return zipalign;
}

private static FilePath ensureZipalignExists(FilePath zipalign, PrintStream logger) throws AbortException {
try {
if (!zipalign.exists()) {
zipalign = buildTools.child("zipalign.exe");
if (zipalign.exists()) {
return zipalign;
}
if (!zipalign.exists()) {
throw new AbortException("failed to find zipalign: no zipalign/zipalign.exe in latest build-tools path " +
zipalign.getParent().getRemote());
}
catch (Exception e) {
e.printStackTrace(logger);
throw new AbortException(e.getMessage());
}
try {
zipalign = zipalign.getParent().child("zipalign.exe");
if (zipalign.exists()) {
return zipalign;
}
}
catch (Exception e) {
e.printStackTrace(logger);
throw new AbortException(
String.format("failed to find zipalign: error listing build-tools versions in %s: %s",
buildTools.getRemote(), e.getLocalizedMessage()));
throw new AbortException(e.getMessage());
}

logger.printf("[SignApksBuilder] found zipalign in Android SDK's latest build tools: %s%n", zipalign.getRemote());
return zipalign;
throw new AbortException("failed to find zipalign: no zipalign/zipalign.exe in latest build-tools path " +
zipalign.getParent().getRemote());
}

private final EnvVars env;
private final FilePath workspace;
private final PrintStream logger;
private final String overrideAndroidHome;
private final String overrideZipalignPath;
private FilePath zipalign;

ZipalignTool(@Nonnull EnvVars env, @Nonnull FilePath workspace, @Nonnull PrintStream logger, @Nullable String overrideZipalignPath) {
ZipalignTool(@Nonnull EnvVars env, @Nonnull FilePath workspace, @Nonnull PrintStream logger, @Nullable String overrideAndroidHome, @Nullable String overrideZipalignPath) {
this.env = env;
this.workspace = workspace;
this.logger = logger;

if (StringUtils.isNotEmpty(overrideZipalignPath)) {
overrideZipalignPath = env.expand(overrideZipalignPath);
zipalign = new FilePath(workspace.getChannel(), overrideZipalignPath);
}
this.overrideAndroidHome = overrideAndroidHome;
this.overrideZipalignPath = overrideZipalignPath;
}

ArgumentListBuilder commandFor(String unsignedApk, String outputApk) throws AbortException {
if (zipalign == null) {
zipalign = findFromEnv(env, workspace, logger);
if (!StringUtils.isEmpty(overrideZipalignPath)) {
logger.printf("[SignApksBuilder] zipalign path explicitly set to %s", overrideZipalignPath);
zipalign = workspace.child(env.expand(overrideZipalignPath));
}
else if (!StringUtils.isEmpty(overrideAndroidHome)) {
logger.printf("[SignApksBuilder] zipalign %s explicitly set to %s", ENV_ANDROID_HOME, overrideAndroidHome);
String expandedAndroidHome = env.expand(overrideAndroidHome);
zipalign = findInAndroidHome(expandedAndroidHome, workspace, this.logger);
}
else {
zipalign = findFromEnv(env, workspace, logger);
}

zipalign = ensureZipalignExists(zipalign, logger);
}

return new ArgumentListBuilder()
@@ -57,6 +57,7 @@
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.collection.IsEmptyCollection.empty;
import static org.junit.Assert.assertThat;
@@ -95,8 +96,12 @@ public String getDisplayName() {
}

private static class FakeZipalign implements FakeLauncher {

private Launcher.ProcStarter lastProc;

@Override
public Proc onLaunch(Launcher.ProcStarter p) throws IOException {
lastProc = p;
List<String> cmd = p.cmds();
String inPath = cmd.get(cmd.size() - 2);
String outPath = cmd.get(cmd.size() - 1);
@@ -188,6 +193,8 @@ private static ApkArtifactIsSignedMatcher isSignedWith(Apk signingEntry) throws

private StandardCertificateCredentials credentials = null;
private FilePath sourceWorkspace = null;
private FilePath androidHome = null;
private FakeZipalign zipalignLauncer = null;

@Before
public void addCredentials() {
@@ -215,12 +222,13 @@ public void setupEnvironment() throws Exception {
String androidHomePath = androidHomeUrl.getPath();
envVars.put("ANDROID_HOME", androidHomePath);
testJenkins.jenkins.getGlobalNodeProperties().add(prop);
androidHome = new FilePath(new File(androidHomeUrl.toURI()));

URL workspaceUrl = getClass().getResource("/workspace");
sourceWorkspace = new FilePath(new File(workspaceUrl.toURI()));

FakeZipalign zipalign = new FakeZipalign();
PretendSlave slave = testJenkins.createPretendSlave(zipalign);
zipalignLauncer = new FakeZipalign();
PretendSlave slave = testJenkins.createPretendSlave(zipalignLauncer);
slave.setLabelString(slave.getLabelString() + " " + getClass().getSimpleName());
}

@@ -416,6 +424,36 @@ public void signsMultipleApksThatWillHaveConflictingSignedFileNames() throws Exc
});
}

@Test
public void usesAndroidHomeOverride() throws Exception {
List<Apk> entries = new ArrayList<>();
entries.add(new Apk(KEY_STORE_ID, getClass().getSimpleName(), "*-unsigned.apk", false, true));
SignApksBuilder builder = new SignApksBuilder(entries);
FilePath androidHomeOverride = testJenkins.jenkins.getRootPath().createTempDir("android-home-override", null);
androidHome.copyRecursiveTo(androidHomeOverride);
builder.setAndroidHome(androidHomeOverride.getRemote());
FreeStyleProject job = createSignApkJob();
job.getBuildersList().add(builder);
testJenkins.buildAndAssertSuccess(job);

assertThat(zipalignLauncer.lastProc.cmds().get(0), startsWith(androidHomeOverride.getRemote()));
}

@Test
public void usesZipalignPathOverride() throws Exception {
List<Apk> entries = new ArrayList<>();
entries.add(new Apk(KEY_STORE_ID, getClass().getSimpleName(), "*-unsigned.apk", false, true));
SignApksBuilder builder = new SignApksBuilder(entries);
FilePath zipalignOverride = testJenkins.jenkins.getRootPath().createTempDir("zipalign-override", null);
zipalignOverride = zipalignOverride.createTextTempFile("zipalign-override", ".sh", "echo \"zipalign $@\"");
builder.setZipalignPath(zipalignOverride.getRemote());
FreeStyleProject job = createSignApkJob();
job.getBuildersList().add(builder);
testJenkins.buildAndAssertSuccess(job);

assertThat(zipalignLauncer.lastProc.cmds().get(0), startsWith(zipalignOverride.getRemote()));
}

@Test
public void supportsMultipleApkGlobs() throws Exception {

0 comments on commit 2a67d3b

Please sign in to comment.