Skip to content
This repository has been archived by the owner on Oct 30, 2023. It is now read-only.

Commit

Permalink
feat!: Bamboo Server 9 Support (#69)
Browse files Browse the repository at this point in the history
* feat!: Bamboo Server 9 support

* Don't init client a million times

* Avoid processing duplicate lines
  • Loading branch information
alexplischke authored Sep 20, 2023
1 parent 2f1b481 commit 6c79191
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 107 deletions.
58 changes: 33 additions & 25 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.saucelabs.bamboo</groupId>
<artifactId>bamboo-sauceondemand-plugin</artifactId>
<version>1.6.98-SNAPSHOT</version>
<version>2.0.0-RC.1</version>
<name>Bamboo Sauce OnDemand Plugin</name>
<packaging>atlassian-plugin</packaging>
<description>This is the Sauce OnDemand plugin for Bamboo</description>
Expand Down Expand Up @@ -51,20 +51,20 @@
<properties>
<ci-sauce.version>1.149</ci-sauce.version>
<saucerest.version>1.0.42</saucerest.version>
<bamboo.version>8.0.2</bamboo.version>
<bamboo.data.version>8.0.2</bamboo.data.version>
<amps.version>8.0.2</amps.version>
<plugin.testrunner.version>1.2.3</plugin.testrunner.version>
<atlassian.spring.scanner.version>1.2.6</atlassian.spring.scanner.version>
<bamboo.version>9.3.3</bamboo.version>
<bamboo.data.version>${bamboo.version}</bamboo.data.version>
<amps.version>8.11.1</amps.version>
<plugin.testrunner.version>2.0.2</plugin.testrunner.version>
<atlassian.spring.scanner.version>1.2.13</atlassian.spring.scanner.version>
<!-- This key is used to keep the consistency between the key in atlassian-plugin.xml and the key to generate bundle. -->
<atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
<java.version>8</java.version>
<java.version>1.8</java.version>
</properties>
<scm>
<connection>scm:git:git://github.com/saucelabs/bamboo_sauce.git</connection>
<developerConnection>scm:git:git@github.com:saucelabs/bamboo_sauce.git</developerConnection>
<url>git@github.com:saucelabs/bamboo_sauce.git</url>
<tag>bamboo-sauceondemand-plugin-1.6.90</tag>
<tag>bamboo-sauceondemand-plugin-1.6.97</tag>
</scm>
<dependencies>
<!-- <dependency>
Expand Down Expand Up @@ -114,6 +114,14 @@
<groupId>com.saucelabs</groupId>
<artifactId>saucerest</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
Expand Down Expand Up @@ -292,30 +300,30 @@
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<version>3.8.1</version>
<configuration>
<source>1.${java.version}</source>
<target>1.${java.version}</target>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5.201505241946</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
<!-- <executions>-->
<!-- <execution>-->
<!-- <goals>-->
<!-- <goal>prepare-agent</goal>-->
<!-- </goals>-->
<!-- </execution>-->
<!-- <execution>-->
<!-- <id>report</id>-->
<!-- <phase>test</phase>-->
<!-- <goals>-->
<!-- <goal>report</goal>-->
<!-- </goals>-->
<!-- </execution>-->
<!-- </executions>-->
</plugin>
</plugins>
<extensions>
Expand Down
99 changes: 41 additions & 58 deletions src/main/java/com/saucelabs/bamboo/sod/action/PostBuildAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,13 @@
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.json.JSONException;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -67,6 +65,8 @@ public class PostBuildAction extends AbstractSauceBuildPlugin implements CustomB

private CustomVariableContext customVariableContext;

private SauceREST sauceClient;

protected SODMappedBuildConfiguration getBuildConfiguration(BuildContext buildContext) {
return new SODMappedBuildConfiguration(buildContext.getBuildDefinition().getCustomConfiguration());
}
Expand All @@ -76,7 +76,8 @@ public BuildContext call() {
final SODMappedBuildConfiguration config = getBuildConfiguration(buildContext);
if (config.isEnabled()) {
try {
recordSauceJobResult(config);
this.sauceClient = getSauceREST(config);
recordSauceJobResult();
} catch (IOException e) {
logger.error(e);
}
Expand Down Expand Up @@ -124,56 +125,46 @@ public void setPlanManager(PlanManager planManager) {
* store the session id from the line in the custom build data of the build, and invoke the Sauce REST API
* to store the Bamboo build number
*
* @param config sauceondemand configuration
* @throws IOException when it has trouble reading from log file
*/
protected void recordSauceJobResult(SODMappedBuildConfiguration config) throws IOException {
protected void recordSauceJobResult() throws IOException {
//iterate over the entries of the build logger to see if one starts with 'SauceOnDemandSessionID'
boolean foundLogEntry = false;
Set<String> lines = new HashSet<>();

logger.info("Checking log interceptor entries");
CurrentBuildResult buildResult = buildContext.getBuildResult();
for (Map.Entry<String, String> entry : buildResult.getCustomBuildData().entrySet()) {
if (entry.getKey().contains("SAUCE_JOB_ID")) {
if (processLine(config, entry.getValue())) {
foundLogEntry = true;
}

lines.add(entry.getValue());
}
}

logger.info("Reading from log file");
// try reading from the log file directly
final StorageLocationService storageLocationService = getStorageLocationService();
File logFile = storageLocationService.getLogFile(buildContext.getPlanResultKey());
List lines = FileUtils.readLines(logFile);
for (Object object : lines) {
String line = (String) object;
if (logger.isDebugEnabled()) {
logger.debug("Processing line: " + line);
}
if (processLine(config, line)) {
foundLogEntry = true;
}
}
List<String> logLines = FileUtils.readLines(logFile, Charset.defaultCharset());
lines.addAll(logLines);

logger.info("Reading from build logger output");
BuildLogger buildLogger = buildLoggerManager.getLogger(buildContext.getResultKey());
for (LogEntry logEntry : buildLogger.getLastNLogEntries(100)) {
if (processLine(config, logEntry.getLog())) {
lines.add(logEntry.getLog());
}

for (String line : lines) {
if (processLine(line)) {
foundLogEntry = true;
}
}


if (!foundLogEntry) {
logger.warn("No Sauce Session ids found in build output");
}

}

protected boolean processLine(SODMappedBuildConfiguration config, String line) {


protected boolean processLine(String line) {
//extract session id
String sessionId = null;
String jobName = null;
Expand All @@ -192,67 +183,59 @@ protected boolean processLine(SODMappedBuildConfiguration config, String line) {
//we might not have a space separating the session id and job-name, so retrieve the text up to the end of the string
sessionId = StringUtils.substringAfter(line, SAUCE_ON_DEMAND_SESSION_ID + "=");
}
if (sessionId != null && !sessionId.equalsIgnoreCase("null")) {
if (sessionId.trim().equals("")) {
logger.error("Session id for line" + line + " was blank");
if (!sessionId.equalsIgnoreCase("null")) {
if (sessionId.trim().isEmpty()) {
return false;
} else {
//TODO extract Sauce Job name (included on log line as 'job-name=')?
storeBambooBuildNumberInSauce(config, sessionId, jobName);
storeBuildMetadata(sessionId, jobName);
return true;
}
}
return false;
}

/**
* Invokes the Sauce REST API to store the build number and pass/fail status against the Sauce Job.
* Store build metadata in the Sauce job with the given session ID (aka job ID).
*
* @param config bamboo/sauce configuration
* @param sessionId the Sauce Job Id
* @param sessionId the Sauce job ID
* @param jobName newly parsed job name
*/

protected void storeBambooBuildNumberInSauce(SODMappedBuildConfiguration config, String sessionId, String jobName) {
SauceREST sauceREST = getSauceREST(config);

protected void storeBuildMetadata(String sessionId, String jobName) {
try {
logger.debug("Invoking Sauce REST API for " + sessionId);
String json = sauceREST.getJobInfo(sessionId);
logger.debug("Results: " + json);
logger.info("Fetching Sauce job " + sessionId);
String json = this.sauceClient.getJobInfo(sessionId);
if (logger.isDebugEnabled()) {
logger.debug("Results: " + json);
}

JobInformation jobInformation = new JobInformation(sessionId, "");
jobInformation.populateFromJson(new org.json.JSONObject(json));
if (jobInformation.getStatus() == null) {
Boolean testPassed = hasTestPassed(jobInformation.getName());
if (testPassed != null) {
//set the status to passed if the test was successful
jobInformation.setStatus(testPassed.booleanValue() ? "passed" : "failed");
}
boolean testPassed = hasTestPassed(jobInformation.getName());
jobInformation.setStatus(testPassed ? "passed" : "failed");
}
if (!jobInformation.hasJobName()) {
if (!jobInformation.hasJobName() && !jobName.isEmpty()) {
logger.info("Setting job name to " + jobName);
jobInformation.setName(jobName);
}
if (!jobInformation.hasBuild()) {
jobInformation.setBuild(getBuildNumber());
}
if (jobInformation.hasChanges()) {
logger.debug("Performing Sauce REST update for " + jobInformation.getJobId());
sauceREST.updateJobInfo(jobInformation.getJobId(), jobInformation.getChanges());
logger.info("Updating Sauce job " + jobInformation.getJobId());
this.sauceClient.updateJobInfo(jobInformation.getJobId(), jobInformation.getChanges());
logger.info("Changes: " + jobInformation.getChanges());
}
} catch (JSONException e) {
logger.error("Unable to set build number for " + sessionId, e);
} /*catch (Exception e) {
logger.error("Unexpected error processing " + sessionId, e);
}*/

} catch (Exception e) {
logger.error("Unable to set build metadata for " + sessionId, e);
}
}

protected SauceREST getSauceREST(SODMappedBuildConfiguration config) {
return new SauceREST(config.getTempUsername(), config.getTempApikey(), config.getTempDatacenter());
}

private Boolean hasTestPassed(String name) {
private boolean hasTestPassed(String name) {
//do we have a test which matches the job name?
TestResults testResults = findTestResult(name);
if (testResults != null) {
Expand Down Expand Up @@ -288,7 +271,7 @@ private TestResults findTestResult(String name, Collection<TestResults> testResu
}

protected String getBuildNumber() {
return getBuildContextToUse().getBuildResultKey();
return getBuildContextToUse().getPlanResultKey().getKey();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ private ArrayList<JobInformation> retrieveJobIdsFromSauce(String username, Strin
String buildName = PlanKeys.getPlanResultKey(resultsSummary.getPlanKey(), getResultsSummary().getBuildNumber()).getKey();
SauceREST sauceREST = new SauceREST(username, accessKey, dataCenter);
//invoke Sauce Rest API to find plan results with those values
logger.info("Fetching jobs for build " + buildName);
String jsonResponse = sauceREST.getBuildFullJobs(buildName);
logger.info("REST response " + jsonResponse);
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,14 @@ public class SauceLogInterceptor implements LogInterceptor {


public SauceLogInterceptor(BuildContext buildContext) {

this.buildContext = buildContext;
}

public void intercept(@NotNull LogEntry logEntry) {
if (StringUtils.containsIgnoreCase(logEntry.getLog(), PostBuildAction.SAUCE_ON_DEMAND_SESSION_ID)) {
if (logger.isDebugEnabled()) {
logger.debug("Adding log entry: " + logEntry.getLog());
}
logger.info("Adding log entry: " + logEntry.getLog());
CurrentBuildResult buildResult = buildContext.getBuildResult();
buildResult.getCustomBuildData().put("SAUCE_JOB_ID_" + System.currentTimeMillis(), logEntry.getLog());

} else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping line " + logEntry.getLog());
Expand All @@ -39,19 +35,7 @@ public void intercept(@NotNull LogEntry logEntry) {
}

public void interceptError(@NotNull LogEntry logEntry) {
if (StringUtils.containsIgnoreCase(logEntry.getLog(), PostBuildAction.SAUCE_ON_DEMAND_SESSION_ID)) {
if (logger.isDebugEnabled()) {
logger.debug("Adding log entry: " + logEntry.getLog());
}
CurrentBuildResult buildResult = buildContext.getBuildResult();
buildResult.getCustomBuildData().put("SAUCE_JOB_ID_" + System.currentTimeMillis(), logEntry.getLog());


} else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping line " + logEntry.getLog());
}
}
intercept(logEntry);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.Before;
import org.junit.Ignore;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
Expand All @@ -18,6 +19,7 @@
/**
* @author Ross Rowe
*/
@Ignore
public abstract class AbstractTestHelper extends HttpServlet {

public static final int PORT = 5000;
Expand All @@ -33,7 +35,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se

@Before
public void loadProperties() throws Exception {

File sauceSettings = new File(new File(System.getProperty("user.home")), ".sauce-ondemand");
if (!sauceSettings.exists()) {
String userName = System.getProperty("sauce.user");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import com.saucelabs.ci.sauceconnect.SauceConnectFourManager;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import java.io.File;

/**
* @author Ross Rowe
*/
@Ignore
public class ExtractSauceConnectTest {

private SauceConnectFourManager manager = new SauceConnectFourManager();
Expand Down
Loading

0 comments on commit 6c79191

Please sign in to comment.