-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cherry picked from octopus-integration branch
- Loading branch information
1 parent
d6ca149
commit 4670c05
Showing
17 changed files
with
655 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,141 @@ | ||
package com.octopus; | ||
|
||
import com.amazonaws.regions.Regions; | ||
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService; | ||
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder; | ||
import com.amazonaws.services.simpleemail.model.*; | ||
import com.amazonaws.services.lambda.runtime.Context; | ||
import com.octopus.eventhandlers.EventHandler; | ||
import com.octopus.eventhandlers.impl.SeqLogging; | ||
import com.octopus.eventhandlers.impl.SlackWebHook; | ||
import com.octopus.eventhandlers.impl.UploadToS3; | ||
import com.octopus.utils.EnvironmentAliasesProcessor; | ||
import com.octopus.utils.ZipUtils; | ||
import com.octopus.utils.impl.AutoDeletingTempDir; | ||
import com.octopus.utils.impl.AutoDeletingTempFile; | ||
import com.octopus.utils.impl.EnvironmentAliasesProcessorImpl; | ||
import com.octopus.utils.impl.ZipUtilsImpl; | ||
import io.vavr.control.Try; | ||
import org.apache.commons.io.FileUtils; | ||
import java.io.*; | ||
import org.apache.commons.lang3.math.NumberUtils; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.io.PrintWriter; | ||
import java.net.MalformedURLException; | ||
import java.net.URL; | ||
import java.nio.charset.Charset; | ||
import java.nio.file.Files; | ||
import java.util.zip.ZipEntry; | ||
import java.util.zip.ZipInputStream; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
|
||
import static com.google.common.base.Preconditions.checkNotNull; | ||
|
||
public class LambdaEntry { | ||
private static final EnvironmentAliasesProcessor ENVIRONMENT_ALIASES_PROCESSOR = | ||
new EnvironmentAliasesProcessorImpl(); | ||
private static final String RETRY_HEADER = "Test-Retry"; | ||
private static final String RETRY_SLEEP_HEADER = "Test-Retry-Sleep"; | ||
private static final ZipUtils ZIP_UTILS = new ZipUtilsImpl(); | ||
private static final EventHandler[] EVENT_HANDLERS = new EventHandler[]{ | ||
new UploadToS3(), | ||
new SlackWebHook(), | ||
new SeqLogging() | ||
}; | ||
private static final String CHROME_HEADLESS_PACKAGE = | ||
"https://s3.amazonaws.com/webdriver-testing-resources/stable-headless-chromium-amazonlinux-2017-03.zip"; | ||
"http://bamboo-support.s3.amazonaws.com/chrome-68-stable/stable-headless-chromium-amazonlinux-2017-03.zip"; | ||
private static final String CHROME_DRIVER = | ||
"https://s3.amazonaws.com/webdriver-testing-resources/chromedriver_linux64.zip"; | ||
"http://bamboo-support.s3.amazonaws.com/chrome-68-stable/chromedriver_linux64.zip"; | ||
|
||
public String runCucumber(String feature) throws Throwable { | ||
|
||
File driverDirectory = null; | ||
File chromeDirectory = null; | ||
File outputFile = null; | ||
File txtOutputFile = null; | ||
File featureFile = null; | ||
|
||
try { | ||
driverDirectory = downloadChromeDriver(); | ||
chromeDirectory = downloadChromeHeadless(); | ||
outputFile = Files.createTempFile("output", ".json").toFile(); | ||
txtOutputFile = Files.createTempFile("output", ".txt").toFile(); | ||
featureFile = writeFeatureToFile(feature); | ||
public String runCucumber(final LambdaInput input, final Context context) throws Throwable { | ||
checkNotNull(input); | ||
|
||
io.cucumber.core.cli.Main.run( | ||
new String[]{ | ||
"--monochrome", | ||
"--glue", "com.octopus.decoratorbase", | ||
"--format", "json:" + outputFile.toString(), | ||
"--format", "pretty:" + txtOutputFile.toString(), | ||
featureFile.getAbsolutePath()}, | ||
Thread.currentThread().getContextClassLoader()); | ||
System.out.println("STARTED Cucumber Test ID " + input.getId()); | ||
|
||
sendEmail("[email protected]", FileUtils.readFileToString(txtOutputFile, Charset.defaultCharset())); | ||
cleanTmpFolder(); | ||
|
||
return FileUtils.readFileToString(outputFile, Charset.defaultCharset()); | ||
File outputFile = null; | ||
File txtOutputFile = null; | ||
File htmlOutput = null; | ||
File junitOutput = null; | ||
|
||
try (final AutoDeletingTempDir driverDirectory = new AutoDeletingTempDir(downloadChromeDriver())) { | ||
try (final AutoDeletingTempDir chromeDirectory = new AutoDeletingTempDir(downloadChromeHeadless())) { | ||
try (final AutoDeletingTempFile featureFile = new AutoDeletingTempFile(writeFeatureToFile(input.getFeature()))) { | ||
|
||
ENVIRONMENT_ALIASES_PROCESSOR.addHeaderVarsAsAliases(input.getHeaders()); | ||
|
||
final int retryCount = NumberUtils.toInt( | ||
input.getHeaders().getOrDefault(RETRY_HEADER, "1"), | ||
1); | ||
|
||
final int retrySleep = NumberUtils.toInt( | ||
input.getHeaders().getOrDefault(RETRY_SLEEP_HEADER, "60"), | ||
60); | ||
|
||
int retValue = 0; | ||
|
||
for (int x = 0; x < retryCount; ++x) { | ||
outputFile = createCleanFile(outputFile, "output", ".json"); | ||
txtOutputFile = createCleanFile(txtOutputFile, "output", ".txt"); | ||
junitOutput = createCleanFile(junitOutput, "junit", ".xml"); | ||
htmlOutput = createCleanDirectory(htmlOutput, "htmloutput"); | ||
|
||
retValue = cucumber.api.cli.Main.run( | ||
new String[]{ | ||
"--monochrome", | ||
"--glue", "com.octopus.decoratorbase", | ||
"--plugin", "json:" + outputFile.toString(), | ||
"--plugin", "pretty:" + txtOutputFile.toString(), | ||
"--plugin", "html:" + htmlOutput.toString(), | ||
"--plugin", "junit:" + junitOutput.toString(), | ||
featureFile.getFile().getAbsolutePath()}, | ||
Thread.currentThread().getContextClassLoader()); | ||
if (retValue == 0) { | ||
break; | ||
} | ||
|
||
Try.run(() -> Thread.sleep(retrySleep)); | ||
} | ||
|
||
System.out.println((retValue == 0 ? "SUCCEEDED" : "FAILED") + " Cucumber Test ID " + input.getId()); | ||
|
||
final String featureFilePath = featureFile.getFile().getAbsolutePath(); | ||
final String htmlOutputDir = htmlOutput.getAbsolutePath(); | ||
final boolean status = retValue == 0; | ||
final String outputTextFile = FileUtils.readFileToString(txtOutputFile, Charset.defaultCharset()); | ||
Arrays.stream(EVENT_HANDLERS).reduce( | ||
new HashMap<String, String>(), | ||
(results, handler) -> new HashMap<>(handler.finished( | ||
input.getId(), | ||
status, | ||
featureFilePath, | ||
outputTextFile, | ||
htmlOutputDir, | ||
input.getHeaders(), | ||
results)), | ||
(a, b) -> a | ||
); | ||
|
||
return FileUtils.readFileToString(outputFile, Charset.defaultCharset()); | ||
} | ||
} | ||
} finally { | ||
FileUtils.deleteQuietly(driverDirectory); | ||
FileUtils.deleteQuietly(chromeDirectory); | ||
FileUtils.deleteQuietly(outputFile); | ||
FileUtils.deleteQuietly(txtOutputFile); | ||
FileUtils.deleteQuietly(featureFile); | ||
FileUtils.deleteQuietly(htmlOutput); | ||
FileUtils.deleteQuietly(junitOutput); | ||
|
||
System.out.println("FINISHED Cucumber Test ID " + input.getId()); | ||
} | ||
} | ||
|
||
private File createCleanFile(final File last, final String prefix, final String suffix) throws IOException { | ||
FileUtils.deleteQuietly(last); | ||
return Files.createTempFile(prefix, suffix).toFile(); | ||
} | ||
|
||
private File createCleanDirectory(final File last, final String name) throws IOException { | ||
FileUtils.deleteQuietly(last); | ||
return Files.createTempDirectory(name).toFile(); | ||
} | ||
|
||
private File downloadChromeDriver() throws IOException { | ||
final File extractedDir = downloadAndExtractFile(CHROME_DRIVER, "chrome_driver"); | ||
final String driver = extractedDir.getAbsolutePath() + "/chromedriver"; | ||
|
@@ -78,35 +158,14 @@ private File downloadAndExtractFile(final String download, final String tempDirP | |
downloadedFile = File.createTempFile("download", ".zip"); | ||
FileUtils.copyURLToFile(new URL(download), downloadedFile); | ||
final File extractedDir = Files.createTempDirectory(tempDirPrefix).toFile(); | ||
unzipFile(downloadedFile.getAbsolutePath(), extractedDir.getAbsolutePath()); | ||
ZIP_UTILS.unzipFile(downloadedFile.getAbsolutePath(), extractedDir.getAbsolutePath()); | ||
return extractedDir; | ||
} finally { | ||
FileUtils.deleteQuietly(downloadedFile); | ||
} | ||
|
||
} | ||
|
||
private void unzipFile(final String fileZip, final String outputDirectory) throws IOException { | ||
|
||
final byte[] buffer = new byte[1024]; | ||
|
||
try (final ZipInputStream zis = new ZipInputStream(new FileInputStream(fileZip))) { | ||
ZipEntry zipEntry = zis.getNextEntry(); | ||
while (zipEntry != null) { | ||
final String fileName = zipEntry.getName(); | ||
final File newFile = new File(outputDirectory + "/" + fileName); | ||
try (final FileOutputStream fos = new FileOutputStream(newFile)) { | ||
int len; | ||
while ((len = zis.read(buffer)) > 0) { | ||
fos.write(buffer, 0, len); | ||
} | ||
} | ||
zipEntry = zis.getNextEntry(); | ||
} | ||
zis.closeEntry(); | ||
} | ||
} | ||
|
||
private File writeFeatureToFile(final String feature) throws IOException { | ||
final File featureFile = File.createTempFile("cucumber", ".feature"); | ||
try { | ||
|
@@ -120,24 +179,15 @@ private File writeFeatureToFile(final String feature) throws IOException { | |
return featureFile; | ||
} | ||
|
||
private void sendEmail(final String to, final String results) { | ||
/** | ||
* Before we start, try cleaning the tmp directory to remove | ||
* any left over files. | ||
*/ | ||
private void cleanTmpFolder() { | ||
try { | ||
final AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard() | ||
.withRegion(Regions.US_EAST_1).build(); | ||
|
||
final SendEmailRequest request = new SendEmailRequest() | ||
.withDestination(new Destination() | ||
.withToAddresses(to)) | ||
.withMessage(new Message() | ||
.withBody(new Body() | ||
.withText(new Content() | ||
.withCharset("UTF-8").withData(results))) | ||
.withSubject(new Content() | ||
.withCharset("UTF-8").withData("WebDriver Test Results"))) | ||
.withSource("[email protected]"); | ||
client.sendEmail(request); | ||
} catch (final Exception ex) { | ||
System.out.println("The email was not sent. Error message: " + ex.getMessage()); | ||
FileUtils.cleanDirectory(new File("/tmp")); | ||
} catch (IOException e) { | ||
// silent failure | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.octopus; | ||
|
||
import java.util.Map; | ||
|
||
public class LambdaInput { | ||
private String id; | ||
private String feature; | ||
private Map<String, String> headers; | ||
|
||
public String getId() { | ||
return id; | ||
} | ||
|
||
public void setId(final String id) { | ||
this.id = id; | ||
} | ||
|
||
public String getFeature() { | ||
return feature; | ||
} | ||
|
||
public void setFeature(final String feature) { | ||
this.feature = feature; | ||
} | ||
|
||
public Map<String, String> getHeaders() { | ||
return headers; | ||
} | ||
|
||
public void setHeaders(final Map<String, String> headers) { | ||
this.headers = headers; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.octopus.eventhandlers; | ||
|
||
import java.util.Map; | ||
|
||
public interface EventHandler { | ||
Map<String, String> finished(final String id, | ||
final boolean status, | ||
final String featureFile, | ||
final String txtOutput, | ||
final String htmlOutputDir, | ||
final Map<String, String> headers, | ||
final Map<String, String> previousResults); | ||
|
||
default boolean proceed(final boolean status, | ||
final Map<String, String> headers, | ||
final String failureOnlyHeader) { | ||
return !status || | ||
!headers.containsKey(failureOnlyHeader) || | ||
headers.get(failureOnlyHeader).equalsIgnoreCase(Boolean.FALSE.toString()); | ||
} | ||
} |
Oops, something went wrong.