public void perform()

in src/main/java/CodeBuilder.java [268:590]


    public void perform(@Nonnull Run<?, ?> build, @Nonnull FilePath ws, @Nonnull Launcher launcher, @Nonnull TaskListener listener) throws InterruptedException, IOException {
        descriptor = getDescriptor();
        envVars = build.getEnvironment(listener);

        AWSClientFactory awsClientFactory;
        try {
            awsClientFactory = new AWSClientFactory(
                    getParameterized(this.credentialsType),
                    getParameterized(this.credentialsId),
                    getParameterized(this.proxyHost),
                    getParameterized(this.proxyPort),
                    getParameterized(this.awsAccessKey),
                    this.awsSecretKey,
                    getParameterized(this.awsSessionToken),
                    getParameterized(this.region),
                    build,
                    this.stepContext);
        } catch (Exception e) {
            failBuild(build, listener, authorizationError, e.getMessage());
            return;
        }

        String projectConfigError = CodeBuilderValidation.checkEssentialConfig(this);
        if(!projectConfigError.isEmpty()) {
            failBuild(build, listener, configuredImproperlyError, projectConfigError);
            return;
        }

        String overridesErrorMessage = CodeBuilderValidation.checkStartBuildOverridesConfig(this);
        if(!overridesErrorMessage.isEmpty()) {
            failBuild(build, listener, configuredImproperlyError, overridesErrorMessage);
            return;
        }

        Collection<EnvironmentVariable> codeBuildEnvVars = null;
        try {
            codeBuildEnvVars = mapEnvVariables(getParameterized(envVariables), EnvironmentVariableType.PLAINTEXT);
            codeBuildEnvVars.addAll(mapEnvVariables(getParameterized(envParameters), EnvironmentVariableType.PARAMETER_STORE));
        } catch(InvalidInputException e) {
            failBuild(build, listener, configuredImproperlyError, e.getMessage());
            return;
        }
        if(CodeBuilderValidation.envVariablesHaveRestrictedPrefix(codeBuildEnvVars)) {
            failBuild(build, listener, configuredImproperlyError, envVariableNameSpaceError);
            return;
        }

        LoggingHelper.log(listener, awsClientFactory.getCredentialsDescriptor());

        final AWSCodeBuildClient cbClient;
        try {
            cbClient = awsClientFactory.getCodeBuildClient();
        } catch (Exception e) {
            failBuild(build, listener, "Error when constructing CodeBuild client: ", e.getMessage());
            return;
        }

        StartBuildRequest startBuildRequest = new StartBuildRequest().withProjectName(getParameterized(projectName)).
                withEnvironmentVariablesOverride(codeBuildEnvVars).withBuildspecOverride(getParameterized(buildSpecFile)).
                withTimeoutInMinutesOverride(parseInt(getParameterized(buildTimeoutOverride)));

        ProjectArtifacts artifactsOverride = generateStartBuildArtifactOverride();
        if(artifactsOverride != null) {
            startBuildRequest.setArtifactsOverride(artifactsOverride);
        }

        ProjectCache cacheOverride = generateStartBuildCacheOverride();
        if(cacheOverride != null) {
            startBuildRequest.setCacheOverride(cacheOverride);
        }

        LogsConfig logsConfigOverride = generateStartBuildLogsConfigOverride();
        if(logsConfigOverride != null) {
            startBuildRequest.setLogsConfigOverride(logsConfigOverride);
        }

        if(!getParameterized(environmentTypeOverride).isEmpty()) {
            startBuildRequest.setEnvironmentTypeOverride(getParameterized(environmentTypeOverride));
        }

        if(!getParameterized(imageOverride).isEmpty()) {
            startBuildRequest.setImageOverride(getParameterized(imageOverride));
        }

        if(!getParameterized(computeTypeOverride).isEmpty()) {
            startBuildRequest.setComputeTypeOverride(getParameterized(computeTypeOverride));
        }

        if(!getParameterized(certificateOverride).isEmpty()) {
            startBuildRequest.setCertificateOverride(getParameterized(certificateOverride));
        }

        if(!getParameterized(serviceRoleOverride).isEmpty()) {
            startBuildRequest.setServiceRoleOverride(getParameterized(serviceRoleOverride));
        }

        if(!getParameterized(insecureSslOverride).isEmpty()) {
            startBuildRequest.setInsecureSslOverride(Boolean.parseBoolean(getParameterized(insecureSslOverride)));
        }

        if(!getParameterized(privilegedModeOverride).isEmpty()) {
            startBuildRequest.setPrivilegedModeOverride(Boolean.parseBoolean(getParameterized(privilegedModeOverride)));
        }

        List<ProjectSource> secondarySources;
        List<ProjectSourceVersion> secondarySourceVersions;
        List<ProjectArtifacts> secondaryArtifacts;

        try {
            secondarySources = Utils.parseDataList(getParameterized(secondarySourcesOverride), ProjectSource.class);
            secondarySourceVersions = Utils.parseDataList(getParameterized(secondarySourcesVersionOverride), ProjectSourceVersion.class);
            secondaryArtifacts = Utils.parseDataList(getParameterized(secondaryArtifactsOverride), ProjectArtifacts.class);
        } catch (InvalidInputException e) {
            failBuild(build, listener, invalidSecondarySourceArtifacts, e.getMessage());
            return;
        }

        if(secondarySources != null && !secondarySources.isEmpty()) {
            startBuildRequest.setSecondarySourcesOverride(secondarySources);
        }

        if(secondarySourceVersions != null && !secondarySourceVersions.isEmpty()) {
            startBuildRequest.setSecondarySourcesVersionOverride(secondarySourceVersions);
        }

        if(secondaryArtifacts != null && !secondaryArtifacts.isEmpty()) {
            startBuildRequest.setSecondaryArtifactsOverride(secondaryArtifacts);
        }

        if(SourceControlType.JenkinsSource.toString().equals(getParameterized(sourceControlType))) {
            String buildSourceLocation = "";
            if(!getParameterized(sourceTypeOverride).isEmpty() || !getParameterized(sourceLocationOverride).isEmpty()) {
                if(!CodeBuilderValidation.checkJenkinsSourceOverrides(getParameterized(sourceTypeOverride), getParameterized(sourceLocationOverride))) {
                    failBuild(build, listener, configuredImproperlyError, jenkinsSourceOverrideError);
                    return;
                }

                buildSourceLocation = getParameterized(sourceLocationOverride);
            } else {
                try {
                    buildSourceLocation = retrieveProjectSourceInfo(cbClient);
                } catch(Exception e) {
                    failBuild(build, listener, configuredImproperlyError, e.getMessage());
                    return;
                }
            }

            String sourceS3Bucket = Utils.getS3BucketFromObjectArn(buildSourceLocation);
            String sourceS3Key = Utils.getS3KeyFromObjectArn(buildSourceLocation);
            if(!CodeBuilderValidation.checkBucketIsVersioned(sourceS3Bucket, awsClientFactory)) {
                failBuild(build, listener, notVersionsedS3BucketError, "");
                return;
            }

            S3DataManager s3DataManager = new S3DataManager(awsClientFactory.getS3Client(), sourceS3Bucket, sourceS3Key, getParameterized(sseAlgorithm), getParameterized(localSourcePath), getParameterized(workspaceSubdir));
            String uploadedSourceVersion = "";

            try {
                UploadToS3Output uploadToS3Output = s3DataManager.uploadSourceToS3(listener, ws);
                // Override source version to object version id returned by S3
                if(uploadToS3Output.getObjectVersionId() != null) {
                    uploadedSourceVersion = uploadToS3Output.getObjectVersionId();
                } else {
                    failBuild(build, listener, notVersionsedS3BucketError, "");
                    return;
                }
                LoggingHelper.log(listener, "S3 object version id for uploaded source is " + uploadedSourceVersion);
            } catch (Exception e) {
                failBuild(build, listener, "Error when uploading source to S3: ", e.getMessage());
                return;
            }

            startBuildRequest.setSourceVersion(uploadedSourceVersion);
            logStartBuildMessage(listener, uploadedSourceVersion);

        } else {
            startBuildRequest.setSourceVersion(getParameterized(sourceVersion));
            startBuildRequest.setGitCloneDepthOverride(generateStartBuildGitCloneDepthOverride());
            if(!getParameterized(reportBuildStatusOverride).isEmpty()) {
                startBuildRequest.setReportBuildStatusOverride(Boolean.parseBoolean(getParameterized(reportBuildStatusOverride)));
            }

            logStartBuildMessage(listener, getParameterized(sourceVersion));
        }

        if(!getParameterized(sourceTypeOverride).isEmpty()) {
            startBuildRequest.setSourceTypeOverride(getParameterized(sourceTypeOverride));
            SourceAuth auth = generateStartBuildSourceAuthOverride(getParameterized(sourceTypeOverride));
            if(auth != null) {
                startBuildRequest.setSourceAuthOverride(auth);
            }
        }
        if(!getParameterized(sourceLocationOverride).isEmpty()) {
            startBuildRequest.setSourceLocationOverride(getParameterized(sourceLocationOverride));
        }

        final StartBuildResult sbResult;
        try {
            sbResult = cbClient.startBuild(startBuildRequest);
        } catch (Exception e) {
            failBuild(build, listener, "Error when calling CodeBuild StartBuild: ", e.getMessage());
            return;
        }

        Build currentBuild = new Build().withBuildStatus(StatusType.IN_PROGRESS);
        String buildId = sbResult.getBuild().getId();
        LoggingHelper.log(listener, "Build id: " + buildId);
        LoggingHelper.log(listener, "CodeBuild dashboard: " + generateDashboardURL(buildId));

        boolean haveInitializedAction = false;
        CodeBuildAction action = null;
        CloudWatchMonitor logMonitor = null;

        //poll buildResult for build status until it's complete.
        do {
            try {
                List<Build> buildsForId = cbClient.batchGetBuilds(new BatchGetBuildsRequest().withIds(buildId)).getBuilds();

                if(buildsForId.size() != 1) {
                    throw new Exception("Multiple builds mapped to this build id.");
                }

                currentBuild = buildsForId.get(0);
                if(!haveInitializedAction) {
                    logMonitor = new CloudWatchMonitor(awsClientFactory.getCloudWatchLogsClient(), Boolean.parseBoolean(getParameterized(cwlStreamingDisabled)));
                    action = new CodeBuildAction(build);

                    //only need to set these once, the others will need to be updated below as the build progresses.
                    String buildARN = currentBuild.getArn();
                    codeBuildResult.setBuildInformation(currentBuild.getId(), buildARN);

                    action.setBuildId(buildId);
                    action.setBuildARN(buildARN);
                    action.setStartTime(currentBuild.getStartTime().toString());

                    ProjectSource source = currentBuild.getSource();
                    if(source != null) {
                        action.setSourceType(source.getType());
                        action.setSourceLocation(source.getLocation());

                        if(currentBuild.getSourceVersion() == null) {
                            action.setSourceVersion("");
                        } else {
                            action.setSourceVersion(currentBuild.getSourceVersion());
                        }

                        Integer depth = source.getGitCloneDepth();
                        if(depth == null || depth == 0) {
                            action.setGitCloneDepth("Full");
                        } else {
                            action.setGitCloneDepth(String.valueOf(depth));
                        }

                        Boolean status = source.getReportBuildStatus();
                        if(status != null) {
                            action.setReportBuildStatus(String.valueOf(status));
                        }
                    }

                    action.setArtifactTypeOverride(getParameterized(artifactTypeOverride));
                    action.setCodeBuildDashboardURL(generateDashboardURL(buildId));
                    action.setLogs(new ArrayList());
                    action.setCloudWatchLogsURL("");
                    action.setS3LogsURL("");

                    build.addAction(action);
                    haveInitializedAction = true;
                }

                updateDashboard(currentBuild, action, logMonitor, listener);
                Thread.sleep(getSleepTime(descriptor));
            } catch(Exception e) {
                if(e.getClass().equals(InterruptedException.class)) {
                    //Request to stop Jenkins build has been made. First make sure the build is stoppable
                    List<Build> buildsForId = cbClient.batchGetBuilds(new BatchGetBuildsRequest().withIds(buildId)).getBuilds();
                    currentBuild = buildsForId.get(0);
                    if(!currentBuild.getCurrentPhase().equals(BuildPhaseType.COMPLETED.toString())) {
                        cbClient.stopBuild(new StopBuildRequest().withId(buildId));
                        //Wait for the build to actually stop
                        do {
                            buildsForId = cbClient.batchGetBuilds(new BatchGetBuildsRequest().withIds(buildId)).getBuilds();
                            currentBuild = buildsForId.get(0);
                            Thread.sleep(5000L);
                            logMonitor.pollForLogs(listener);
                            updateDashboard(currentBuild, action, logMonitor, listener);
                        } while (!currentBuild.getCurrentPhase().equals(BuildPhaseType.COMPLETED.toString()));
                    }
                    if (action != null) {
                        action.setJenkinsBuildSucceeds(false);
                    }
                    this.codeBuildResult.setStopped();
                    build.setResult(Result.ABORTED);
                    return;
                } else if(e.getMessage().contains(CodeBuildClientRetryCondition.HTTP_ERROR_MESSAGE)) {
                    Thread.sleep(getSleepTime(descriptor));
                    continue;
                } else {
                    if (action != null) {
                        action.setJenkinsBuildSucceeds(false);
                    }
                    failBuild(build, listener, "Error while polling build: ", e.getMessage());
                    return;
                }
            }
        } while(currentBuild.getBuildStatus().equals(StatusType.IN_PROGRESS.toString()));

        // Read artifacts location once the build is complete and artifact name finalized
        codeBuildResult.setArtifactsLocation(currentBuild.getArtifacts() != null ? currentBuild.getArtifacts().getLocation() : null);

        // Download build artifacts
        if(downloadArtifacts.equalsIgnoreCase(Boolean.TRUE.toString())) {
            downloadArtifactsFromS3(listener, awsClientFactory.getS3Client(), currentBuild, this.getArtifactRoot(ws));
        }
        if(currentBuild.getBuildStatus().equals(StatusType.SUCCEEDED.toString().toUpperCase(Locale.ENGLISH))) {
            action.setJenkinsBuildSucceeds(true);
            this.codeBuildResult.setSuccess();
            build.setResult(Result.SUCCESS);
        } else {
            action.setJenkinsBuildSucceeds(false);
            failBuild(build, listener, "Build " + currentBuild.getId() + " failed", action.getPhaseErrorMessage());
        }
        return;
    }