Skip to content

Commit 4670c05

Browse files
committed
Cherry picked from octopus-integration branch
1 parent d6ca149 commit 4670c05

17 files changed

+655
-75
lines changed

pom.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd">
2121
<commons.io.version>2.6</commons.io.version>
2222
<screenrecorder.version>0.7.7</screenrecorder.version>
2323
<slf4jjdk14.version>1.7.28</slf4jjdk14.version>
24+
<vavr.version>0.9.2</vavr.version>
2425
</properties>
2526
<build>
2627
<plugins>
@@ -139,6 +140,16 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd">
139140
<artifactId>commons-lang3</artifactId>
140141
<version>${apache.commons.lang.version}</version>
141142
</dependency>
143+
<dependency>
144+
<groupId>io.vavr</groupId>
145+
<artifactId>vavr</artifactId>
146+
<version>${vavr.version}</version>
147+
</dependency>
148+
<dependency>
149+
<groupId>com.amazonaws</groupId>
150+
<artifactId>aws-java-sdk-s3</artifactId>
151+
<version>${aws.sdk.version}</version>
152+
</dependency>
142153
</dependencies>
143154
<repositories>
144155
<repository>

src/main/java/com/octopus/Constants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.octopus;
22

33
public class Constants {
4+
public static final String ALIAS_HEADER_PREFIX = "CucumberAlias-";
5+
46
/**
57
* The system property that can be used to enable the mouse cursor to be moved
68
* to the element being interacted with
Lines changed: 125 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,141 @@
11
package com.octopus;
22

3-
import com.amazonaws.regions.Regions;
4-
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
5-
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder;
6-
import com.amazonaws.services.simpleemail.model.*;
3+
import com.amazonaws.services.lambda.runtime.Context;
4+
import com.octopus.eventhandlers.EventHandler;
5+
import com.octopus.eventhandlers.impl.SeqLogging;
6+
import com.octopus.eventhandlers.impl.SlackWebHook;
7+
import com.octopus.eventhandlers.impl.UploadToS3;
8+
import com.octopus.utils.EnvironmentAliasesProcessor;
9+
import com.octopus.utils.ZipUtils;
10+
import com.octopus.utils.impl.AutoDeletingTempDir;
11+
import com.octopus.utils.impl.AutoDeletingTempFile;
12+
import com.octopus.utils.impl.EnvironmentAliasesProcessorImpl;
13+
import com.octopus.utils.impl.ZipUtilsImpl;
14+
import io.vavr.control.Try;
715
import org.apache.commons.io.FileUtils;
8-
import java.io.*;
16+
import org.apache.commons.lang3.math.NumberUtils;
17+
18+
import java.io.File;
19+
import java.io.IOException;
20+
import java.io.PrintWriter;
921
import java.net.MalformedURLException;
1022
import java.net.URL;
1123
import java.nio.charset.Charset;
1224
import java.nio.file.Files;
13-
import java.util.zip.ZipEntry;
14-
import java.util.zip.ZipInputStream;
25+
import java.util.Arrays;
26+
import java.util.HashMap;
27+
28+
import static com.google.common.base.Preconditions.checkNotNull;
1529

1630
public class LambdaEntry {
31+
private static final EnvironmentAliasesProcessor ENVIRONMENT_ALIASES_PROCESSOR =
32+
new EnvironmentAliasesProcessorImpl();
33+
private static final String RETRY_HEADER = "Test-Retry";
34+
private static final String RETRY_SLEEP_HEADER = "Test-Retry-Sleep";
35+
private static final ZipUtils ZIP_UTILS = new ZipUtilsImpl();
36+
private static final EventHandler[] EVENT_HANDLERS = new EventHandler[]{
37+
new UploadToS3(),
38+
new SlackWebHook(),
39+
new SeqLogging()
40+
};
1741
private static final String CHROME_HEADLESS_PACKAGE =
18-
"https://s3.amazonaws.com/webdriver-testing-resources/stable-headless-chromium-amazonlinux-2017-03.zip";
42+
"http://bamboo-support.s3.amazonaws.com/chrome-68-stable/stable-headless-chromium-amazonlinux-2017-03.zip";
1943
private static final String CHROME_DRIVER =
20-
"https://s3.amazonaws.com/webdriver-testing-resources/chromedriver_linux64.zip";
44+
"http://bamboo-support.s3.amazonaws.com/chrome-68-stable/chromedriver_linux64.zip";
2145

22-
public String runCucumber(String feature) throws Throwable {
23-
24-
File driverDirectory = null;
25-
File chromeDirectory = null;
26-
File outputFile = null;
27-
File txtOutputFile = null;
28-
File featureFile = null;
29-
30-
try {
31-
driverDirectory = downloadChromeDriver();
32-
chromeDirectory = downloadChromeHeadless();
33-
outputFile = Files.createTempFile("output", ".json").toFile();
34-
txtOutputFile = Files.createTempFile("output", ".txt").toFile();
35-
featureFile = writeFeatureToFile(feature);
46+
public String runCucumber(final LambdaInput input, final Context context) throws Throwable {
47+
checkNotNull(input);
3648

37-
io.cucumber.core.cli.Main.run(
38-
new String[]{
39-
"--monochrome",
40-
"--glue", "com.octopus.decoratorbase",
41-
"--format", "json:" + outputFile.toString(),
42-
"--format", "pretty:" + txtOutputFile.toString(),
43-
featureFile.getAbsolutePath()},
44-
Thread.currentThread().getContextClassLoader());
49+
System.out.println("STARTED Cucumber Test ID " + input.getId());
4550

46-
sendEmail("admin@matthewcasperson.com", FileUtils.readFileToString(txtOutputFile, Charset.defaultCharset()));
51+
cleanTmpFolder();
4752

48-
return FileUtils.readFileToString(outputFile, Charset.defaultCharset());
53+
File outputFile = null;
54+
File txtOutputFile = null;
55+
File htmlOutput = null;
56+
File junitOutput = null;
57+
58+
try (final AutoDeletingTempDir driverDirectory = new AutoDeletingTempDir(downloadChromeDriver())) {
59+
try (final AutoDeletingTempDir chromeDirectory = new AutoDeletingTempDir(downloadChromeHeadless())) {
60+
try (final AutoDeletingTempFile featureFile = new AutoDeletingTempFile(writeFeatureToFile(input.getFeature()))) {
61+
62+
ENVIRONMENT_ALIASES_PROCESSOR.addHeaderVarsAsAliases(input.getHeaders());
63+
64+
final int retryCount = NumberUtils.toInt(
65+
input.getHeaders().getOrDefault(RETRY_HEADER, "1"),
66+
1);
67+
68+
final int retrySleep = NumberUtils.toInt(
69+
input.getHeaders().getOrDefault(RETRY_SLEEP_HEADER, "60"),
70+
60);
71+
72+
int retValue = 0;
73+
74+
for (int x = 0; x < retryCount; ++x) {
75+
outputFile = createCleanFile(outputFile, "output", ".json");
76+
txtOutputFile = createCleanFile(txtOutputFile, "output", ".txt");
77+
junitOutput = createCleanFile(junitOutput, "junit", ".xml");
78+
htmlOutput = createCleanDirectory(htmlOutput, "htmloutput");
79+
80+
retValue = cucumber.api.cli.Main.run(
81+
new String[]{
82+
"--monochrome",
83+
"--glue", "com.octopus.decoratorbase",
84+
"--plugin", "json:" + outputFile.toString(),
85+
"--plugin", "pretty:" + txtOutputFile.toString(),
86+
"--plugin", "html:" + htmlOutput.toString(),
87+
"--plugin", "junit:" + junitOutput.toString(),
88+
featureFile.getFile().getAbsolutePath()},
89+
Thread.currentThread().getContextClassLoader());
90+
if (retValue == 0) {
91+
break;
92+
}
93+
94+
Try.run(() -> Thread.sleep(retrySleep));
95+
}
4996

97+
System.out.println((retValue == 0 ? "SUCCEEDED" : "FAILED") + " Cucumber Test ID " + input.getId());
98+
99+
final String featureFilePath = featureFile.getFile().getAbsolutePath();
100+
final String htmlOutputDir = htmlOutput.getAbsolutePath();
101+
final boolean status = retValue == 0;
102+
final String outputTextFile = FileUtils.readFileToString(txtOutputFile, Charset.defaultCharset());
103+
Arrays.stream(EVENT_HANDLERS).reduce(
104+
new HashMap<String, String>(),
105+
(results, handler) -> new HashMap<>(handler.finished(
106+
input.getId(),
107+
status,
108+
featureFilePath,
109+
outputTextFile,
110+
htmlOutputDir,
111+
input.getHeaders(),
112+
results)),
113+
(a, b) -> a
114+
);
115+
116+
return FileUtils.readFileToString(outputFile, Charset.defaultCharset());
117+
}
118+
}
50119
} finally {
51-
FileUtils.deleteQuietly(driverDirectory);
52-
FileUtils.deleteQuietly(chromeDirectory);
53120
FileUtils.deleteQuietly(outputFile);
54121
FileUtils.deleteQuietly(txtOutputFile);
55-
FileUtils.deleteQuietly(featureFile);
122+
FileUtils.deleteQuietly(htmlOutput);
123+
FileUtils.deleteQuietly(junitOutput);
124+
125+
System.out.println("FINISHED Cucumber Test ID " + input.getId());
56126
}
57127
}
58128

129+
private File createCleanFile(final File last, final String prefix, final String suffix) throws IOException {
130+
FileUtils.deleteQuietly(last);
131+
return Files.createTempFile(prefix, suffix).toFile();
132+
}
133+
134+
private File createCleanDirectory(final File last, final String name) throws IOException {
135+
FileUtils.deleteQuietly(last);
136+
return Files.createTempDirectory(name).toFile();
137+
}
138+
59139
private File downloadChromeDriver() throws IOException {
60140
final File extractedDir = downloadAndExtractFile(CHROME_DRIVER, "chrome_driver");
61141
final String driver = extractedDir.getAbsolutePath() + "/chromedriver";
@@ -78,35 +158,14 @@ private File downloadAndExtractFile(final String download, final String tempDirP
78158
downloadedFile = File.createTempFile("download", ".zip");
79159
FileUtils.copyURLToFile(new URL(download), downloadedFile);
80160
final File extractedDir = Files.createTempDirectory(tempDirPrefix).toFile();
81-
unzipFile(downloadedFile.getAbsolutePath(), extractedDir.getAbsolutePath());
161+
ZIP_UTILS.unzipFile(downloadedFile.getAbsolutePath(), extractedDir.getAbsolutePath());
82162
return extractedDir;
83163
} finally {
84164
FileUtils.deleteQuietly(downloadedFile);
85165
}
86166

87167
}
88168

89-
private void unzipFile(final String fileZip, final String outputDirectory) throws IOException {
90-
91-
final byte[] buffer = new byte[1024];
92-
93-
try (final ZipInputStream zis = new ZipInputStream(new FileInputStream(fileZip))) {
94-
ZipEntry zipEntry = zis.getNextEntry();
95-
while (zipEntry != null) {
96-
final String fileName = zipEntry.getName();
97-
final File newFile = new File(outputDirectory + "/" + fileName);
98-
try (final FileOutputStream fos = new FileOutputStream(newFile)) {
99-
int len;
100-
while ((len = zis.read(buffer)) > 0) {
101-
fos.write(buffer, 0, len);
102-
}
103-
}
104-
zipEntry = zis.getNextEntry();
105-
}
106-
zis.closeEntry();
107-
}
108-
}
109-
110169
private File writeFeatureToFile(final String feature) throws IOException {
111170
final File featureFile = File.createTempFile("cucumber", ".feature");
112171
try {
@@ -120,24 +179,15 @@ private File writeFeatureToFile(final String feature) throws IOException {
120179
return featureFile;
121180
}
122181

123-
private void sendEmail(final String to, final String results) {
182+
/**
183+
* Before we start, try cleaning the tmp directory to remove
184+
* any left over files.
185+
*/
186+
private void cleanTmpFolder() {
124187
try {
125-
final AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard()
126-
.withRegion(Regions.US_EAST_1).build();
127-
128-
final SendEmailRequest request = new SendEmailRequest()
129-
.withDestination(new Destination()
130-
.withToAddresses(to))
131-
.withMessage(new Message()
132-
.withBody(new Body()
133-
.withText(new Content()
134-
.withCharset("UTF-8").withData(results)))
135-
.withSubject(new Content()
136-
.withCharset("UTF-8").withData("WebDriver Test Results")))
137-
.withSource("admin@matthewcasperson.com");
138-
client.sendEmail(request);
139-
} catch (final Exception ex) {
140-
System.out.println("The email was not sent. Error message: " + ex.getMessage());
188+
FileUtils.cleanDirectory(new File("/tmp"));
189+
} catch (IOException e) {
190+
// silent failure
141191
}
142192
}
143193
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.octopus;
2+
3+
import java.util.Map;
4+
5+
public class LambdaInput {
6+
private String id;
7+
private String feature;
8+
private Map<String, String> headers;
9+
10+
public String getId() {
11+
return id;
12+
}
13+
14+
public void setId(final String id) {
15+
this.id = id;
16+
}
17+
18+
public String getFeature() {
19+
return feature;
20+
}
21+
22+
public void setFeature(final String feature) {
23+
this.feature = feature;
24+
}
25+
26+
public Map<String, String> getHeaders() {
27+
return headers;
28+
}
29+
30+
public void setHeaders(final Map<String, String> headers) {
31+
this.headers = headers;
32+
}
33+
}

src/main/java/com/octopus/Main.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
package com.octopus;
22

33
import com.octopus.decorators.WebDriverDecorator;
4+
import com.octopus.utils.EnvironmentAliasesProcessor;
5+
import com.octopus.utils.impl.EnvironmentAliasesProcessorImpl;
46

57
import java.io.IOException;
68
import java.util.ArrayList;
79
import java.util.Collections;
810

911
public class Main {
12+
private static final EnvironmentAliasesProcessor ENVIRONMENT_ALIASES_PROCESSOR =
13+
new EnvironmentAliasesProcessorImpl();
14+
1015
public static void main(String[] args) {
1116
try {
1217
final ArrayList<String> options = new ArrayList<String>() {{
@@ -16,6 +21,8 @@ public static void main(String[] args) {
1621

1722
Collections.addAll(options, args);
1823

24+
ENVIRONMENT_ALIASES_PROCESSOR.addSystemPropVarsAsAliases();
25+
1926
io.cucumber.core.cli.Main.run(
2027
options.toArray(new String[0]),
2128
Thread.currentThread().getContextClassLoader());

src/main/java/com/octopus/decoratorbase/AutomatedBrowserBase.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ public AutomatedBrowserBase(final AutomatedBrowser automatedBrowser) {
3131
this.automatedBrowser = automatedBrowser;
3232
}
3333

34+
public static void setExternalAliases(final Map<String, String> externalAliases) {
35+
if (externalAliases == null) return;
36+
AutomatedBrowserBase.externalAliases.putAll(externalAliases);
37+
}
38+
3439
@Before
3540
public void reuseSharedBrowser() {
3641
automatedBrowser = sharedAutomatedBrowser;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.octopus.eventhandlers;
2+
3+
import java.util.Map;
4+
5+
public interface EventHandler {
6+
Map<String, String> finished(final String id,
7+
final boolean status,
8+
final String featureFile,
9+
final String txtOutput,
10+
final String htmlOutputDir,
11+
final Map<String, String> headers,
12+
final Map<String, String> previousResults);
13+
14+
default boolean proceed(final boolean status,
15+
final Map<String, String> headers,
16+
final String failureOnlyHeader) {
17+
return !status ||
18+
!headers.containsKey(failureOnlyHeader) ||
19+
headers.get(failureOnlyHeader).equalsIgnoreCase(Boolean.FALSE.toString());
20+
}
21+
}

0 commit comments

Comments
 (0)