package hudson.plugins.jira; import java.io.IOException; import java.io.PrintStream; import java.util.List; import org.kohsuke.stapler.DataBoundConstructor; import com.google.common.collect.Lists; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.matrix.MatrixAggregatable; import hudson.matrix.MatrixAggregator; import hudson.matrix.MatrixBuild; import hudson.matrix.MatrixRun; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.BuildListener; import hudson.model.Run; import hudson.model.TaskListener; import hudson.plugins.jira.selector.AbstractIssueSelector; import hudson.plugins.jira.selector.DefaultIssueSelector; import hudson.scm.SCM; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Publisher; import hudson.tasks.Recorder; import jenkins.model.Jenkins; import jenkins.tasks.SimpleBuildStep; /** * Parses build changelog for JIRA issue IDs and then * updates JIRA issues accordingly. * * @author Kohsuke Kawaguchi */ public class JiraIssueUpdater extends Recorder implements MatrixAggregatable, SimpleBuildStep { private AbstractIssueSelector issueSelector; private SCM scm; private List<String> labels; @DataBoundConstructor public JiraIssueUpdater(AbstractIssueSelector issueSelector, SCM scm, List<String> labels) { super(); this.issueSelector = issueSelector; this.scm = scm; if(labels != null) this.labels = labels; else this.labels = Lists.newArrayList(); } @Override public void perform(Run<?, ?> run, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException { // Don't do anything for individual matrix runs. if (run instanceof MatrixRun) { return; } else if(run instanceof AbstractBuild) { AbstractBuild<?,?> abstractBuild = (AbstractBuild<?,?>) run; Updater updater = new Updater(abstractBuild.getParent().getScm(), labels); updater.perform(run, listener, getIssueSelector()); } else if(scm != null) { Updater updater = new Updater(scm, labels); updater.perform(run, listener, getIssueSelector()); } else { throw new IllegalArgumentException("Unsupported run type "+run.getClass().getName()); } } public BuildStepMonitor getRequiredMonitorService() { return BuildStepMonitor.BUILD; } @Override public DescriptorImpl getDescriptor() { return DESCRIPTOR; } public AbstractIssueSelector getIssueSelector() { AbstractIssueSelector uis = this.issueSelector; if (uis == null) uis = new DefaultIssueSelector(); return (this.issueSelector = uis); } @Extension public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); public MatrixAggregator createAggregator(MatrixBuild build, Launcher launcher, BuildListener listener) { return new MatrixAggregator(build, launcher, listener) { @Override public boolean endBuild() throws InterruptedException, IOException { PrintStream logger = listener.getLogger(); logger.println("End of Matrix Build. Updating JIRA."); Updater updater = new Updater(this.build.getParent().getScm(), labels); return updater.perform(this.build, this.listener, getIssueSelector()); } }; } public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> { private DescriptorImpl() { super(JiraIssueUpdater.class); } @Override public String getDisplayName() { // Displayed in the publisher section return Messages.JiraIssueUpdater_DisplayName(); } @Override public String getHelpFile() { return "/plugin/jira/help.html"; } @Override @SuppressWarnings("unchecked") public boolean isApplicable(Class<? extends AbstractProject> jobType) { return true; } public boolean hasIssueSelectors() { return Jenkins.getActiveInstance().getDescriptorList(AbstractIssueSelector.class).size() > 1; } } }