package hudson.plugins.mibsr; import hudson.FilePath; import hudson.Launcher; import hudson.Extension; import hudson.matrix.MatrixConfiguration; import hudson.matrix.MatrixProject; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.Action; import hudson.model.BuildListener; import hudson.model.FreeStyleProject; import hudson.model.HealthReport; import hudson.model.Result; import hudson.plugins.mibsr.health.HealthMetric; import hudson.plugins.mibsr.parser.BuildJobs; import hudson.remoting.VirtualChannel; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Publisher; import hudson.tasks.Recorder; import hudson.util.FormValidation; import net.sf.json.JSONObject; import org.apache.commons.beanutils.ConvertUtils; import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import java.io.File; import java.io.IOException; import java.io.Serializable; /** * TODO javadoc. * * @author Stephen Connolly * @since 08-Jan-2008 21:24:06 */ public class MIBSRPublisher extends Recorder { private String reportFilenamePattern; private MIBSRHealthTarget[] targets; @DataBoundConstructor public MIBSRPublisher( String reportFilenamePattern, MIBSRHealthTarget[] targets ) { reportFilenamePattern.getClass(); this.reportFilenamePattern = reportFilenamePattern; this.targets = targets == null ? new MIBSRHealthTarget[0] : targets; } public String getReportFilenamePattern() { return reportFilenamePattern; } public MIBSRHealthTarget[] getTargets() { return targets; } /** * {@inheritDoc} */ @Override public boolean needsToRunAfterFinalized() { return false; } /** * {@inheritDoc} */ public boolean perform( final AbstractBuild<?, ?> build, Launcher launcher, final BuildListener listener ) throws InterruptedException, IOException { MIBSRBuildIndividualReport action = build.getModuleRoot().act( new Worker( build, listener, reportFilenamePattern ) ); if ( action != null ) { if ( targets != null && targets.length > 0 ) { HealthReport r = null; for ( MIBSRHealthTarget target : targets ) { r = HealthReport.min( r, target.evaluateHealth( action, PluginImpl.DISPLAY_NAME + ": " ) ); } action.setBuildHealth( r ); } build.getActions().add( action ); BuildJobs results = action.getTotals(); if ( results.getFailCount() > 0 || results.getErrorCount() > 0 ) { build.setResult( Result.UNSTABLE ); } } return true; // never stop the build } /** * {@inheritDoc} */ @Override public boolean prebuild( AbstractBuild<?, ?> build, BuildListener listener ) { return true; } /** * {@inheritDoc} */ @Override public Action getProjectAction( AbstractProject<?, ?> project ) { return new MIBSRProjectIndividualReport( project ); } public BuildStepMonitor getRequiredMonitorService() { return BuildStepMonitor.NONE; } @Extension public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> { public DescriptorImpl() { super( MIBSRPublisher.class ); } /** * {@inheritDoc} */ public String getDisplayName() { return "Publish " + PluginImpl.DISPLAY_NAME; } @Override public Publisher newInstance( StaplerRequest req, JSONObject formData ) throws FormException { ConvertUtils.register( MIBSRHealthMetrics.CONVERTER, MIBSRHealthMetrics.class ); return req.bindJSON( MIBSRPublisher.class, formData ); } public boolean isApplicable( Class<? extends AbstractProject> aClass ) { return MatrixProject.class.isAssignableFrom( aClass ) || MatrixConfiguration.class.isAssignableFrom( aClass ) || FreeStyleProject.class.isAssignableFrom( aClass ); } public HealthMetric[] getMetrics() { return MIBSRHealthMetrics.values(); } /** * Performs on-the-fly validation on the file mask wildcard. */ public FormValidation doCheck(@AncestorInPath AbstractProject project, @QueryParameter String value) throws IOException { return FilePath.validateFileMask(project.getSomeWorkspace(),value); } public String applyDefaultIncludes( String invokerResults ) { if ( invokerResults == null || invokerResults.trim().length() == 0 ) { return "**/target/invoker-reports/BUILD-*.xml"; } else { return invokerResults.trim(); } } } private static class Worker implements FilePath.FileCallable<MIBSRBuildIndividualReport>, Serializable { private final AbstractBuild<?, ?> build; private final BuildListener listener; private String reportFilenamePattern; public Worker( AbstractBuild<?, ?> build, BuildListener listener, String reportFilenamePattern ) { this.build = build; this.listener = listener; this.reportFilenamePattern = reportFilenamePattern; } public MIBSRBuildIndividualReport invoke( File file, VirtualChannel virtualChannel ) throws IOException { FilePath[] paths; try { paths = build.getModuleRoot().list( reportFilenamePattern ); } catch ( InterruptedException e ) { IOException ioe = new IOException( e.getMessage() ); ioe.initCause( e ); throw ioe; } String[] fileNames = new String[paths.length]; for ( int i = 0; i < paths.length; i++ ) { fileNames[i] = paths[i].getRemote(); } return new MIBSRBuildIndividualReport( BuildJobs.parse( fileNames ) ); } } }