All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hudson.plugins.jira.Updater Maven / Gradle / Ivy

package hudson.plugins.jira;

import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.AbstractBuild.DependencyChange;
import hudson.model.BuildListener;
import hudson.model.Hudson;
import hudson.model.Result;
import hudson.model.Run;
import hudson.scm.ChangeLogSet;
import hudson.scm.ChangeLogSet.Entry;

import javax.xml.rpc.ServiceException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Actual JIRA update logic.
 *
 * 
 * @author Kohsuke Kawaguchi
 */
class Updater {
    static boolean perform(AbstractBuild build, BuildListener listener) throws InterruptedException, IOException {
        PrintStream logger = listener.getLogger();

        JiraSite site = JiraSite.get(build.getProject());
        if(site==null) {
            logger.println(Messages.Updater_NoJiraSite());
            build.setResult(Result.FAILURE);
            return true;
        }

        String rootUrl = Hudson.getInstance().getRootUrl();
        if(rootUrl==null) {
            logger.println(Messages.Updater_NoHudsonUrl());
            build.setResult(Result.FAILURE);
            return true;
        }

        Set ids = findIssueIdsRecursive(build);

        if(ids.isEmpty()) {
            if(debug)
                logger.println("No JIRA issues found.");
            return true;    // nothing found here.
        }

        boolean noUpdate = build.getResult().isWorseThan(Result.UNSTABLE);

        List issues = new ArrayList();
        try {
            JiraSession session = site.createSession();
            if(session==null) {
                logger.println(Messages.Updater_NoRemoteAccess());
                build.setResult(Result.FAILURE);
                return true;
            }
            for (String id : ids) {
                if(!session.existsIssue(id)) {
                    if(debug)
                        logger.println(id+" looked like a JIRA issue but it wans't");
                    continue;   // token looked like a JIRA issue but it's actually not.
                }
                if(!noUpdate) {
                    logger.println(Messages.Updater_Updating(id));
                    String aggregateComment ="";
                    for(Entry e :(ChangeLogSet)build.getChangeSet()){
                        if(e.getMsg().contains(id)){
                            aggregateComment +=e.getMsg() + "\n";
                            aggregateComment = aggregateComment.replaceAll(id, "");

                        }
                    }


                    session.addComment(id,
                        String.format(
                            site.supportsWikiStyleComment?
                            "Integrated in !%1$snocacheImages/16x16/%3$s! [%2$s|%4$s]\n     %5$s":
                            "Integrated in %2$s (See [%4$s])\n    %5$s",
                            rootUrl, build, build.getResult().color.getImage(),
                            Util.encode(rootUrl+build.getUrl()),aggregateComment));
                }

                issues.add(new JiraIssue(session.getIssue(id)));

            }
        } catch (ServiceException e) {
            listener.getLogger().println(Messages.Updater_FailedToConnect());
            e.printStackTrace(listener.getLogger());
        }
        build.getActions().add(new JiraBuildAction(build,issues));

        if(noUpdate)
            // this build didn't work, so carry forward the issue to the next build
            build.addAction(new JiraCarryOverAction(ids));

        return true;
    }

    /**
     * Finds the strings that match JIRA issue ID patterns.
     *
     * This method returns all likely candidates and doesn't check
     * if such ID actually exists or not. We don't want to use
     * {@link JiraSite#existsIssue(String)} here so that new projects
     * in JIRA can be detected.
     */
    private static Set findIssueIdsRecursive(AbstractBuild build) {
        Set ids = new HashSet();

        // first, issues that were carried forward.
        Run prev = build.getPreviousBuild();
        if(prev!=null) {
            JiraCarryOverAction a = prev.getAction(JiraCarryOverAction.class);
            if(a!=null)
                ids.addAll(a.getIDs());
        }

        // then issues in this build
        findIssues(build,ids);

        // check for issues fixed in dependencies
        for( DependencyChange depc : build.getDependencyChanges(build.getPreviousBuild()).values())
            for(AbstractBuild b : depc.getBuilds())
                findIssues(b,ids);

        return ids;
    }

    private static void findIssues(AbstractBuild build, Set ids) {
        for (Entry change : build.getChangeSet()) {
            LOGGER.fine("Looking for JIRA ID in "+change.getMsg());
            Matcher m = ISSUE_PATTERN.matcher(change.getMsg());
            while (m.find())
                ids.add(m.group());
        }
    }

    /**
     * Regexp pattern that identifies JIRA issue token.
     *
     * 

* At least two upper alphabetic. * Numbers are also allowed as project keys (see issue #729) */ public static final Pattern ISSUE_PATTERN = Pattern.compile("\\b[A-Z]([A-Z0-9]+)-[1-9][0-9]*\\b"); private static final Logger LOGGER = Logger.getLogger(Updater.class.getName()); /** * Debug flag. */ public static boolean debug = false; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy