in src/main/java/org/jenkinsci/plugins/awsdevicefarm/AWSDeviceFarmRecorder.java [493:696]
public void perform(@Nonnull hudson.model.Run<?, ?> build, @Nonnull FilePath workspace, @Nonnull Launcher launcher, @Nonnull TaskListener listener) throws IOException, InterruptedException {
// Check if the build result set from a previous build step.
// A null build result indicates that the build is still ongoing and we're
// likely being run as a build step by the "Any Build Step Plugin".
Result buildResult = build.getResult();
if (buildResult != null && buildResult.isWorseOrEqualTo(Result.FAILURE)) {
listener.error("Still building");
}
EnvVars env = build.getEnvironment(listener);
Map<String, String> parameters = build.getEnvironment(listener);
final PrintStream log = listener.getLogger();
// Artifacts location for this build on master.
FilePath artifactsDir = new FilePath(build.getArtifactsDir());
// Validate user selection & input values.
boolean isValid = validateConfiguration(log) && validateTestConfiguration(log);
if (!isValid) {
writeToLog(log, "Invalid configuration.");
build.setResult(Result.FAILURE);
return;
}
// Create & configure the AWSDeviceFarm client.
AWSDeviceFarm adf = getAWSDeviceFarm()
.withLogger(listener.getLogger())
.withWorkspace(workspace)
.withArtifactsDir(artifactsDir)
.withEnv(env);
try {
// Accept 'ADF_PROJECT' build parameter as an overload from job configuration.
String projectNameParameter = parameters.get("AWSDEVICEFARM_PROJECT");
if (projectNameParameter != null && !projectNameParameter.isEmpty()) {
writeToLog(log, String.format("Using overloaded project '%s' from build parameters", projectNameParameter));
projectName = projectNameParameter;
}
// check for Unmetered Devices on Account
if (isRunUnmetered != null && isRunUnmetered) {
int unmeteredDeviceCount = 0;
if (ifWebApp != null && ifWebApp) {
unmeteredDeviceCount = adf.getUnmeteredDevicesForWeb();
if (unmeteredDeviceCount <= 0) {
throw new AWSDeviceFarmException(String.format(
"Your account does not have unmetered android or ios device slots. Please change "
+ "your build settings to run on metered devices."));
}
} else {
String os = adf.getOs(appArtifact);
unmeteredDeviceCount = adf.getUnmeteredDevices(os);
if (unmeteredDeviceCount <= 0) {
throw new AWSDeviceFarmException(
String.format("Your account does not have unmetered %s device slots. Please change "
+ "your build settings to run on metered devices.", os));
}
}
}
// Get AWS Device Farm project from user provided name.
writeToLog(log, String.format("Using Project '%s'", projectName));
Project project = adf.getProject(projectName);
// Accept 'ADF_DEVICE_POOL' build parameter as an overload from job configuration.
String devicePoolParameter = parameters.get("AWSDEVICEFARM_DEVICE_POOL");
if (devicePoolParameter != null) {
writeToLog(log, String.format("Using overloaded device pool '%s' from build parameters", devicePoolParameter));
devicePoolName = devicePoolParameter;
}
// Get AWS Device Farm device pool from user provided name.
writeToLog(log, String.format("Using DevicePool '%s'", devicePoolName));
DevicePool devicePool = adf.getDevicePool(project, devicePoolName);
// Upload app.
String appArn = null;
if (ifWebApp != null && ifWebApp){
writeToLog(log, "Tesing a Web App.");
}
else {
writeToLog(log, String.format("Using App '%s'", env.expand(appArtifact)));
Upload appUpload = adf.uploadApp(project, appArtifact);
appArn = appUpload.getArn();
}
String deviceFarmRunName = null;
if (StringUtils.isBlank(runName)) {
deviceFarmRunName = String.format("%s", env.get("BUILD_TAG"));
} else {
deviceFarmRunName = String.format("%s", env.expand(runName));
}
// Upload test content.
writeToLog(log, "Getting test to schedule.");
ScheduleRunTest testToSchedule = getScheduleRunTest(env, adf, project, log);
// by default videoCapture is always enabled
Boolean videoCapture = true;
if (ifVideoRecording != null && !ifVideoRecording) {
videoCapture = false;
}
if (ifAppPerformanceMonitoring != null && !ifAppPerformanceMonitoring) {
testToSchedule.addParametersEntry("app_performance_monitoring", "false");
}
Boolean skipAppResign = false;
if (ifSkipAppResigning != null && ifSkipAppResigning) {
skipAppResign = true;
}
// State the Appium Version.
if (testToRun.equalsIgnoreCase("APPIUM_JAVA_JUNIT")) writeToLog(log, String.format("Using appium version: %s", appiumVersionJunit));
else if (testToRun.equalsIgnoreCase("APPIUM_WEB_JAVA_JUNIT")) writeToLog(log, String.format("Using appium version: %s", appiumVersionJunit));
else if (testToRun.equalsIgnoreCase("APPIUM_JAVA_TESTNG")) writeToLog(log, String.format("Using appium version: %s", appiumVersionTestng));
else if (testToRun.equalsIgnoreCase("APPIUM_WEB_JAVA_TESTNG")) writeToLog(log, String.format("Using appium version: %s", appiumVersionTestng));
else if (testToRun.equalsIgnoreCase("APPIUM_PYTHON")) writeToLog(log, String.format("Using appium version: %s", appiumVersionPython));
else if (testToRun.equalsIgnoreCase("APPIUM_WEB_PYTHON")) writeToLog(log, String.format("Using appium version: %s", appiumVersionPython));
// Upload the extra data.
String extraDataArn = null;
if (extraData != null && extraData) {
writeToLog(log, String.format("Using Extra Data '%s'", env.expand(extraDataArtifact)));
Upload extraDataUpload = adf.uploadExtraData(project, extraDataArtifact);
extraDataArn = extraDataUpload.getArn();
}
// Schedule test run.
TestType testType = TestType.fromValue(testToSchedule.getType());
writeToLog(log, String.format("Scheduling '%s' run '%s'", testType, deviceFarmRunName));
ScheduleRunConfiguration configuration = getScheduleRunConfiguration(isRunUnmetered, deviceLocation, radioDetails);
configuration.setExtraDataPackageArn(extraDataArn);
// Check if VPCE option is enabled in UI and account has a VPC config
if(ifVpce != null && ifVpce && accountHasVPC()) {
// Get AWS Device Farm VPCE.
writeToLog(log, String.format("Using VPCE Configuartion '%s'", vpceServiceName));
VPCEConfiguration vpceConfiguration = adf.getVPCEConfiguration(vpceServiceName);
Collection vpceConfigurationArns = new HashSet();
vpceConfigurationArns.add(vpceConfiguration.getArn());
configuration.setVpceConfigurationArns(vpceConfigurationArns);
}
ScheduleRunResult run = adf.scheduleRun(project.getArn(), deviceFarmRunName, appArn, devicePool.getArn(), testToSchedule, jobTimeoutMinutes, configuration, videoCapture, skipAppResign);
String runArn = run.getRun().getArn();
try {
writeToLog(log, String.format("View the %s run in the AWS Device Farm Console: %s", testType, AWSDeviceFarmUtils.getRunUrlFromArn(runArn)));
} catch (ArrayIndexOutOfBoundsException e) {
writeToLog(log, String.format("Could not parse project ID and run ID from run ARN: %s", runArn));
}
// Attach AWS Device Farm action to poll periodically and update results UI.
AWSDeviceFarmTestResultAction action = new AWSDeviceFarmTestResultAction(build, null);
build.addAction(action);
// Wait for test result to complete will updating status periodically.
writeToLog(log, "Waiting for test run to complete.");
action.waitForRunCompletion(adf, run);
writeToLog(log, "Test run is complete.");
// Download results archive and store it.
if (storeResults) {
// Create results storage directory which will contain the unzip logs/screenshots pulled from AWS Device Farm.
FilePath resultsDir = new FilePath(artifactsDir, "AWS Device Farm Results");
resultsDir.mkdirs();
writeToLog(log, String.format("Storing AWS Device Farm results in directory %s", resultsDir));
Map<String, FilePath> jobs = getJobs(adf, run, resultsDir);
Map<String, FilePath> suites = getSuites(adf, run, jobs);
Map<String, FilePath> tests = getTests(adf, run, suites);
writeToLog(log, "Downloading AWS Device Farm results archive...");
// Iterating over all values in the Enum.
for (ArtifactCategory category : new ArrayList<ArtifactCategory>(Arrays.asList(ArtifactCategory.values()))) {
ListArtifactsResult result = adf.listArtifacts(run.getRun().getArn(), category);
for (Artifact artifact : result.getArtifacts()) {
String arn = artifact.getArn().split(":")[6];
String testArn = arn.substring(0, arn.lastIndexOf("/"));
String id = arn.substring(arn.lastIndexOf("/") + 1);
String extension = artifact.getExtension().replaceFirst("^\\.", "");
// Copy remote file to local path for archiving
FilePath localArtifact = new FilePath(tests.get(testArn), String.format("%s-%s.%s", artifact.getName(), id, extension));
URL artifactUrl = new URL(artifact.getUrl());
localArtifact.copyFrom(artifactUrl);
}
}
writeToLog(log, String.format("Results archive saved in %s", artifactsDir.getName()));
}
// Set Jenkins build result based on AWS Device Farm test result.
build.setResult(action.getBuildResult(ignoreRunError));
} catch (AWSDeviceFarmException e) {
writeToLog(log, e.getMessage());
return;
}
return;
}