Skip to content

Commit

Permalink
JENKINS-12741 Made Sauce Connect closing logic work when invoked by a…
Browse files Browse the repository at this point in the history
… slave. Added -Darguments to BrowserAxis. Extract Sauce Session Id from build log if not present in test output
  • Loading branch information
rossrowe committed Mar 4, 2012
1 parent 18855a2 commit 8333bba
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 13 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -115,7 +115,7 @@
<dependency>
<groupId>com.saucelabs</groupId>
<artifactId>ci-sauce</artifactId>
<version>1.7</version>
<version>1.8-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/hudson/plugins/sauce_ondemand/BrowserAxis.java
Expand Up @@ -82,7 +82,9 @@ public List<com.saucelabs.ci.Browser> getBrowsers() {
*/
public void addBuildVariable(String value, Map<String,String> map) {
com.saucelabs.ci.Browser b = BrowserFactory.getInstance().forKey(value);
if (b!=null) // should never be null, but let's be defensive in case of downgrade.
map.put(getName(),b.getUri());
if (b!=null) { // should never be null, but let's be defensive in case of downgrade.
map.put(getName(), "\"" + b.getUri() + "\"");
map.put("arguments", "\"-D" + getName() + "=" + b.getUri() + "\"");
}
}
}
Expand Up @@ -120,7 +120,7 @@ public void buildEnvVars(Map<String, String> env) {
config.put("browser-version", browserInstance.getVersion());
config.put("url", browserInstance.getUri());
} catch (JSONException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
logger.error("Unable to create JSON Object", e);
}
browsersJSON.put(config);

Expand Down Expand Up @@ -159,7 +159,7 @@ private String getStartingURL() {
public boolean tearDown(AbstractBuild build, BuildListener listener) throws IOException, InterruptedException {
if (tunnels != null) {
listener.getLogger().println("Shutting down Sauce OnDemand SSH tunnels");
tunnels.close(listener);
Computer.currentComputer().getChannel().call(new SauceConnectCloser(tunnels, listener));
}
return true;
}
Expand Down Expand Up @@ -258,17 +258,34 @@ public TunnelHolder(String username) {
}

public void close(TaskListener listener) {

try {
HudsonSauceManagerFactory.getInstance().createSauceConnectManager().closeTunnelsForPlan(username);
HudsonSauceManagerFactory.getInstance().createSauceConnectManager().closeTunnelsForPlan(username, listener.getLogger());
} catch (ComponentLookupException e) {
//shouldn't happen
logger.error("Unable to close tunnel", e);
}

}
}

private final class SauceConnectCloser implements Callable<ITunnelHolder, IOException> {

private ITunnelHolder tunnelHolder;
private BuildListener listener;


public SauceConnectCloser(ITunnelHolder tunnelHolder, BuildListener listener) {
this.tunnelHolder = tunnelHolder;
this.listener = listener;
}

public ITunnelHolder call() throws IOException {
tunnelHolder.close(listener);
return tunnelHolder;
}
}


private final class SauceConnectStarter implements Callable<ITunnelHolder, IOException> {
private String username;
private String key;
Expand Down Expand Up @@ -308,9 +325,7 @@ public ITunnelHolder call() throws IOException {
SauceTunnelManager sauceManager = null;
try {
sauceManager = HudsonSauceManagerFactory.getInstance().createSauceConnectManager();
Object process = sauceManager.openConnection(username, key, port, sauceConnectJar, listener.getLogger());

//tunnelHolder.tunnelManagers.add(sauceManager);
Process process = sauceManager.openConnection(username, key, port, sauceConnectJar, listener.getLogger());
return tunnelHolder;
} catch (ComponentLookupException e) {
throw new IOException(e);
Expand Down
Expand Up @@ -24,10 +24,12 @@
package hudson.plugins.sauce_ondemand;

import hudson.tasks.junit.CaseResult;
import hudson.tasks.junit.ClassResult;
import hudson.tasks.junit.TestObject;
import hudson.tasks.junit.TestResultAction.Data;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand All @@ -41,6 +43,8 @@
*/
public class SauceOnDemandReportFactory extends Data {

private static final Logger logger = Logger.getLogger(SauceOnDemandReportFactory.class);

public static final SauceOnDemandReportFactory INSTANCE = new SauceOnDemandReportFactory();

/**
Expand All @@ -53,10 +57,19 @@ public Object readResolve() {

@Override
public List<SauceOnDemandReport> getTestAction(TestObject testObject) {

if (testObject instanceof CaseResult) {
CaseResult cr = (CaseResult) testObject;
String jobName = cr.getFullName();
List<String> ids = findSessionIDs(jobName, cr.getStdout(), cr.getStderr());
if (ids.isEmpty()) {
//try parse the build output
try {
ids = SauceOnDemandReportFactory.findSessionIDs(jobName, IOUtils.readLines(testObject.getOwner().getLogReader()));
} catch (IOException e) {
logger.error("Error reading log file", e);
}
}
boolean matchingJobNames = true;
if (ids.isEmpty()) {
// fall back to old-style log parsing (when no job-name is present in output)
Expand Down Expand Up @@ -92,4 +105,20 @@ static List<String> findSessionIDs(String jobName, String... output) {

private static final Pattern SESSION_ID_PATTERN = Pattern.compile("SauceOnDemandSessionID=([0-9a-fA-F]+) job-name=(.*)");
private static final Pattern OLD_SESSION_ID_PATTERN = Pattern.compile("SauceOnDemandSessionID=([0-9a-fA-F]+)");

public static List<String> findSessionIDs(String jobName, List<String> lines) {
List<String> sessions = new ArrayList<String>();
Pattern p = jobName != null ? SESSION_ID_PATTERN : OLD_SESSION_ID_PATTERN;
for (String text : lines) {
if (text==null) continue;
Matcher m = p.matcher(text);
while (m.find()) {
String sessionId = m.group(1);
if (jobName == null || jobName.equals(m.group(2))) {
sessions.add(sessionId);
}
}
}
return sessions;
}
}
Expand Up @@ -36,6 +36,7 @@
import hudson.tasks.junit.TestDataPublisher;
import hudson.tasks.junit.TestResult;
import hudson.util.Secret;
import org.apache.commons.io.IOUtils;
import org.kohsuke.stapler.DataBoundConstructor;

import java.io.IOException;
Expand All @@ -55,14 +56,15 @@ public SauceOnDemandReportPublisher() {
@Override
public SauceOnDemandReportFactory getTestData(AbstractBuild<?,?> build, Launcher launcher, BuildListener buildListener, TestResult testResult) throws IOException, InterruptedException {
JobFactory factory = new JobFactory(new Credential(PluginImpl.get().getUsername(), Secret.toString(PluginImpl.get().getApiKey())));

buildListener.getLogger().println("Scanning for Sauce OnDemand test data...");
boolean hasResult = false;
for (SuiteResult sr : testResult.getSuites()) {
for (CaseResult cr : sr.getCases()) {
String jobName = cr.getFullName();

List<String> sessionIDs = SauceOnDemandReportFactory.findSessionIDs(jobName, cr.getStdout(), cr.getStderr());
if (sessionIDs.isEmpty()) {
sessionIDs = SauceOnDemandReportFactory.findSessionIDs(jobName, IOUtils.readLines(build.getLogReader()));
}
for (String id : sessionIDs) {
hasResult = true;
try {
Expand Down

0 comments on commit 8333bba

Please sign in to comment.