public void perform()

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;
    }