Skip to content

Commit

Permalink
Cherry picked from octopus-integration branch
Browse files Browse the repository at this point in the history
  • Loading branch information
mcasperson committed Sep 16, 2019
1 parent d6ca149 commit 4670c05
Show file tree
Hide file tree
Showing 17 changed files with 655 additions and 75 deletions.
11 changes: 11 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd">
<commons.io.version>2.6</commons.io.version>
<screenrecorder.version>0.7.7</screenrecorder.version>
<slf4jjdk14.version>1.7.28</slf4jjdk14.version>
<vavr.version>0.9.2</vavr.version>
</properties>
<build>
<plugins>
Expand Down Expand Up @@ -139,6 +140,16 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>commons-lang3</artifactId>
<version>${apache.commons.lang.version}</version>
</dependency>
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>${vavr.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>${aws.sdk.version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/octopus/Constants.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.octopus;

public class Constants {
public static final String ALIAS_HEADER_PREFIX = "CucumberAlias-";

/**
* The system property that can be used to enable the mouse cursor to be moved
* to the element being interacted with
Expand Down
200 changes: 125 additions & 75 deletions src/main/java/com/octopus/LambdaEntry.java
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";
Expand All @@ -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 {
Expand All @@ -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
}
}
}
33 changes: 33 additions & 0 deletions src/main/java/com/octopus/LambdaInput.java
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;
}
}
7 changes: 7 additions & 0 deletions src/main/java/com/octopus/Main.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package com.octopus;

import com.octopus.decorators.WebDriverDecorator;
import com.octopus.utils.EnvironmentAliasesProcessor;
import com.octopus.utils.impl.EnvironmentAliasesProcessorImpl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;

public class Main {
private static final EnvironmentAliasesProcessor ENVIRONMENT_ALIASES_PROCESSOR =
new EnvironmentAliasesProcessorImpl();

public static void main(String[] args) {
try {
final ArrayList<String> options = new ArrayList<String>() {{
Expand All @@ -16,6 +21,8 @@ public static void main(String[] args) {

Collections.addAll(options, args);

ENVIRONMENT_ALIASES_PROCESSOR.addSystemPropVarsAsAliases();

io.cucumber.core.cli.Main.run(
options.toArray(new String[0]),
Thread.currentThread().getContextClassLoader());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ public AutomatedBrowserBase(final AutomatedBrowser automatedBrowser) {
this.automatedBrowser = automatedBrowser;
}

public static void setExternalAliases(final Map<String, String> externalAliases) {
if (externalAliases == null) return;
AutomatedBrowserBase.externalAliases.putAll(externalAliases);
}

@Before
public void reuseSharedBrowser() {
automatedBrowser = sharedAutomatedBrowser;
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/com/octopus/eventhandlers/EventHandler.java
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());
}
}
Loading

0 comments on commit 4670c05

Please sign in to comment.