jenkinsci/hpe-application-automation-tools-plugin

View on GitHub
src/main/java/com/microfocus/application/automation/tools/octane/actions/CoveragePublisher.java

Summary

Maintainability
A
0 mins
Test Coverage
/*
 * Certain versions of software accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company.
 * This software was acquired by Micro Focus on September 1, 2017, and is now offered by OpenText.
 * Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.
 * __________________________________________________________________
 * MIT License
 *
 * Copyright 2012-2024 Open Text
 *
 * The only warranties for products and services of Open Text and
 * its affiliates and licensors ("Open Text") are as may be set forth
 * in the express warranty statements accompanying such products and services.
 * Nothing herein should be construed as constituting an additional warranty.
 * Open Text shall not be liable for technical or editorial errors or
 * omissions contained herein. The information contained herein is subject
 * to change without notice.
 *
 * Except as specifically indicated otherwise, this document contains
 * confidential information and a valid license is required for possession,
 * use or copying. If this work is provided to the U.S. Government,
 * consistent with FAR 12.211 and 12.212, Commercial Computer Software,
 * Computer Software Documentation, and Technical Data for Commercial Items are
 * licensed to the U.S. Government under vendor's standard commercial license.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ___________________________________________________________________
 */

package com.microfocus.application.automation.tools.octane.actions;

import com.hp.octane.integrations.OctaneSDK;
import com.hp.octane.integrations.dto.coverage.CoverageReportType;
import com.microfocus.application.automation.tools.octane.Messages;
import com.microfocus.application.automation.tools.octane.actions.coverage.CoveragePublisherAction;
import com.microfocus.application.automation.tools.octane.actions.coverage.CoverageService;
import com.microfocus.application.automation.tools.octane.tests.build.BuildHandlerUtils;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.*;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher;
import hudson.tasks.Recorder;
import hudson.util.FormValidation;
import jenkins.tasks.SimpleBuildStep;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;

import javax.annotation.Nonnull;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.List;

/**
 * Post-build action that collects the coverage reports from workspace
 * the reports that matches a specified regular expression path, are copied to
 * the build folder for future upload.
 */
public class CoveragePublisher extends Recorder implements SimpleBuildStep {
    private final String jacocoPathPattern;
    private final String lcovPathPattern;

    /**
     * this ctor is being called from configuration page.
     * the jacocoPathPattern is being injected from the web page text box
     *
     * @param jacocoPathPattern regular expression path for coverage reports
     */
    @DataBoundConstructor
    public CoveragePublisher(String jacocoPathPattern, String lcovPathPattern) {
        // Fields in config.jelly must match the parameter names in the "DataBoundConstructor"
        this.jacocoPathPattern = jacocoPathPattern == null || jacocoPathPattern.isEmpty() ? CoverageService.Jacoco.JACOCO_DEFAULT_PATH : jacocoPathPattern;
        this.lcovPathPattern = lcovPathPattern == null || lcovPathPattern.isEmpty() ? CoverageService.Lcov.LCOV_DEFAULT_PATH : lcovPathPattern;
    }

    /**
     * this method used for serialization & deserialization of path
     *
     * @return jacoco path
     */
    public String getJacocoPathPattern() {
        return jacocoPathPattern;
    }

    /**
     * this method used for serialization & deserialization of path
     *
     * @return lcov path
     */
    public String getLcovPathPattern() {
        return lcovPathPattern;
    }

    /**
     * this is where we build the project. this method is being called when we run the build
     *
     * @param run    instance
     * @param filePath instance
     * @param launcher for action attachment
     * @param taskListener for action attachment
     */
    @Override
    public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath filePath, @Nonnull Launcher launcher, @Nonnull TaskListener taskListener) throws InterruptedException, IOException {
        boolean isSuccessful = perform(run, taskListener);
        if (!isSuccessful) {
            run.setResult(Result.FAILURE);
        }
    }

    /**
     * this is where we build the project. this method is being called when we run the build
     *
     * @param build    instance
     * @param launcher instance
     * @param listener for action attachment
     * @return status
     */
    @Override
    public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) {
        return perform(build, listener);
    }

    public boolean perform(Run build, TaskListener listener) {
        CoveragePublisherAction action = new CoveragePublisherAction(build, listener);
        build.addAction(action);

        List<String> jacocoReportFileNames = action.copyCoverageReportsToBuildFolder(jacocoPathPattern, CoverageService.Jacoco.JACOCO_DEFAULT_FILE_NAME);
        List<String> lcovReportFileNames = action.copyCoverageReportsToBuildFolder(lcovPathPattern, CoverageService.Lcov.LCOV_DEFAULT_FILE_NAME);
        boolean copyReportsToBuildFolderStatus = enqueueReports(build, jacocoReportFileNames, CoverageReportType.JACOCOXML) ||
                enqueueReports(build, lcovReportFileNames, CoverageReportType.LCOV);

        return copyReportsToBuildFolderStatus;
    }

    private boolean enqueueReports(Run build, List<String> reportFileNames, CoverageReportType coverageReportType){
        if (!reportFileNames.isEmpty()) {
            String parents = BuildHandlerUtils.getRootJobCiIds(build);
            OctaneSDK.getClients().forEach(octaneClient-> {
                for (String reportFileName : reportFileNames) {
                    octaneClient.getCoverageService()
                            .enqueuePushCoverage(BuildHandlerUtils.getJobCiId(build), String.valueOf(build.getNumber()), coverageReportType, reportFileName, parents);
                }
            });
            return true;
        }
        return false;
    }

    /**
     * bound between descriptor to publisher
     *
     * @return descriptor
     */
    @Override
    public DescriptorImpl getDescriptor() {
        return (DescriptorImpl) super.getDescriptor();
    }

    /**
     * Returns BuildStepMonitor.NONE by default, as Builders normally don't depend on its previous result
     *
     * @return monitor
     */
    @Override
    public BuildStepMonitor getRequiredMonitorService() {
        return BuildStepMonitor.NONE;
    }

    /**
     * The Publisher object or Recorder is the base.
     * It needs a BuildStepDescriptor to provide certain information to Jenkins
     */
    @Symbol("publishCodeCoverage")
    @Extension
    public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {

        public DescriptorImpl() {
            load();
        }

        /**
         * Indicates that this builder can be used with all kinds of project types
         *
         * @param aClass that describe the job
         * @return always true, indicate that this post build action suitable for all jenkins jobs
         */
        public boolean isApplicable(Class<? extends AbstractProject> aClass) {
            return true; // so that it will also be available for maven & other projects
        }

        public String getDisplayName() {
            return "ALM Octane code coverage publisher";
        }

        public FormValidation doCheckJacocoPathPattern(@AncestorInPath AbstractProject project, @QueryParameter String value) throws IOException {
            if (value == null || value.isEmpty()) {
                return FormValidation.warning(Messages.CoverageResultsActionEmptyConfigurationWarning(), CoverageService.Jacoco.JACOCO_DEFAULT_PATH);
            } else if (project == null) {
                return FormValidation.ok();
            }
            return FilePath.validateFileMask(project.getSomeWorkspace(), value);
        }

        public FormValidation doCheckLcovPathPattern(@AncestorInPath AbstractProject project, @QueryParameter String value) throws IOException, ServletException {
            if (value == null || value.isEmpty()) {
                return FormValidation.warning(Messages.CoverageResultsActionEmptyConfigurationWarning(), CoverageService.Lcov.LCOV_DEFAULT_PATH);
            } else if (project == null) {
                return FormValidation.ok();
            }
            return FilePath.validateFileMask(project.getSomeWorkspace(), value);
        }
    }
}