/* * Copyright (c) 2013, SOASTA, Inc. * All Rights Reserved. */ package com.soasta.jenkins; import hudson.AbortException; import hudson.EnvVars; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.BuildListener; import hudson.tasks.Builder; import hudson.util.ArgumentListBuilder; import hudson.util.FormValidation; import hudson.util.ListBoxModel; import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import java.io.IOException; import java.util.logging.Logger; public class iOSSimulatorLauncher extends Builder { /** * URL of {@link CloudTestServer}. */ private final String url; private final String cloudTestServerID; private final String app, sdk, family; @DataBoundConstructor public iOSSimulatorLauncher(String url, String cloudTestServerID, String app, String sdk, String family) { this.url = url; this.cloudTestServerID = cloudTestServerID; this.app = app; this.sdk = sdk; this.family = family; } public String getUrl() { return url; } public String getCloudTestServerID() { return cloudTestServerID; } public String getApp() { return app; } public String getSdk() { return sdk; } public String getFamily() { return family; } public CloudTestServer getServer() { return CloudTestServer.getByID(cloudTestServerID); } public Object readResolve() throws IOException { if (cloudTestServerID != null) return this; // We don't have a server ID. // This means the builder config is based an older version the plug-in. // Look up the server by URL instead. // We'll use the ID going forward. CloudTestServer s = CloudTestServer.getByURL(getUrl()); LOGGER.info("Matched server URL " + getUrl() + " to ID: " + s.getId() + "; re-creating."); return new iOSSimulatorLauncher(url, s.getId(), app, sdk, family); } @Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { ArgumentListBuilder args = new ArgumentListBuilder(); EnvVars envs = build.getEnvironment(listener); CloudTestServer server = getServer(); if (server == null) throw new AbortException("No TouchTest server is configured in the system configuration."); FilePath bin = new iOSAppInstallerInstaller(server).ios_sim_launcher(build.getBuiltOn(), listener); // Determine TouchTest Agent URL for this server. // The simulator will automatically open this URL // in Mobile Safari. String agentURL; String cloudTestServerUrl = server.getUrl(); if (cloudTestServerUrl.endsWith("/")) agentURL = cloudTestServerUrl + "touchtest"; else agentURL = cloudTestServerUrl + "/touchtest"; args.add(bin) .add("--app", envs.expand(app)) .add("--agenturl", agentURL); if (sdk != null && !sdk.trim().isEmpty()) args.add("--sdk", envs.expand(sdk)); if (family != null && !family.trim().isEmpty()) args.add("--family", envs.expand(family)); int r = launcher.launch().cmds(args).pwd(build.getWorkspace()).stdout(listener).join(); return r==0; } @Extension public static class DescriptorImpl extends AbstractCloudTestBuilderDescriptor { @Override public String getDisplayName() { return "Run App in iOS Simulator"; } public ListBoxModel doFillFamilyItems() { ListBoxModel items = new ListBoxModel(); items.add("iPhone", "iphone"); items.add("iPhone (Retina)", "iphone_retina"); items.add("iPad", "ipad"); items.add("iPad (Retina)", "ipad_retina"); return items; } /** * Called automatically by Jenkins whenever the "app" * field is modified by the user. * @param value the new app directory. */ public FormValidation doCheckApp(@AncestorInPath AbstractProject project, @QueryParameter String value) throws IOException { if (value == null || value.trim().isEmpty()) { return FormValidation.error("App directory is required."); } else { // Make sure the directory exists. return validateFileMask(project, value); } } } private static final Logger LOGGER = Logger.getLogger(iOSSimulatorLauncher.class.getName()); }