package hudson.plugins.emailext.plugins.recipients; import hudson.EnvVars; import hudson.Extension; import hudson.model.AbstractBuild; import hudson.model.Cause; import hudson.model.Job; import hudson.model.Run; import hudson.model.User; import hudson.plugins.emailext.ExtendedEmailPublisherContext; import hudson.plugins.emailext.ExtendedEmailPublisherDescriptor; import hudson.plugins.emailext.Messages; import hudson.plugins.emailext.plugins.RecipientProvider; import hudson.plugins.emailext.plugins.RecipientProviderDescriptor; import hudson.scm.ChangeLogSet; import java.io.PrintStream; import jenkins.model.Jenkins; import org.kohsuke.stapler.DataBoundConstructor; import javax.mail.internet.InternetAddress; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; /** * Sends emails to committers of upstream builds which triggered this build. */ public class UpstreamComitterRecipientProvider extends RecipientProvider { @DataBoundConstructor public UpstreamComitterRecipientProvider() { } @Override public void addRecipients(final ExtendedEmailPublisherContext context, EnvVars env, Set<InternetAddress> to, Set<InternetAddress> cc, Set<InternetAddress> bcc) { final class Debug implements RecipientProviderUtilities.IDebug { private final ExtendedEmailPublisherDescriptor descriptor = Jenkins.getActiveInstance().getDescriptorByType(ExtendedEmailPublisherDescriptor.class); private final PrintStream logger = context.getListener().getLogger(); public void send(final String format, final Object... args) { descriptor.debug(logger, format, args); } } final Debug debug = new Debug(); debug.send("Sending email to upstream committer(s)."); Run<?, ?> cur; Cause.UpstreamCause upc = context.getRun().getCause(Cause.UpstreamCause.class); while (upc != null) { Job<?, ?> p = (Job<?, ?>) Jenkins.getActiveInstance().getItemByFullName(upc.getUpstreamProject()); if(p == null) { context.getListener().getLogger().print("There is a break in the project linkage, could not retrieve upstream project information"); break; } cur = p.getBuildByNumber(upc.getUpstreamBuild()); upc = cur.getCause(Cause.UpstreamCause.class); addUpstreamCommittersTriggeringBuild(cur, to, cc, bcc, env, context, debug); } } /** * Adds for the given upstream build the committers to the recipient list for each commit in the upstream build. * * @param build the upstream build * @param to the to recipient list * @param cc the cc recipient list * @param bcc the bcc recipient list * @param env * @param listener */ private void addUpstreamCommittersTriggeringBuild(Run<?, ?> build, Set<InternetAddress> to, Set<InternetAddress> cc, Set<InternetAddress> bcc, EnvVars env, final ExtendedEmailPublisherContext context, RecipientProviderUtilities.IDebug debug) { debug.send("Adding upstream committer from job %s with build number %s", build.getParent().getDisplayName(), build.getNumber()); List<ChangeLogSet<?>> changeSets = new ArrayList<>(); if(build instanceof AbstractBuild<?,?>) { AbstractBuild<?,?> b = (AbstractBuild<?,?>)build; changeSets.add(b.getChangeSet()); } else { try { // check for getChangeSets which WorkflowRun has Method m = build.getClass().getMethod("getChangeSets"); changeSets = (List<ChangeLogSet<? extends ChangeLogSet.Entry>>)m.invoke(build); } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { context.getListener().getLogger().print("Could not add upstream committers, build type does not provide change set"); } } if(!changeSets.isEmpty()) { for(ChangeLogSet<? extends ChangeLogSet.Entry> changeSet : changeSets) { for(ChangeLogSet.Entry change : changeSet) { addUserFromChangeSet(change, to, cc, bcc, env, context, debug); } } } } /** * Adds a user to the recipients list based on a specific SCM change set * @param change The ChangeLogSet.Entry to get the user information from * @param to The list of to addresses to add to * @param cc The list of cc addresses to add to * @param bcc The list of bcc addresses to add to * @param env The build environment * @param listener The listener for logging */ private void addUserFromChangeSet(ChangeLogSet.Entry change, Set<InternetAddress> to, Set<InternetAddress> cc, Set<InternetAddress> bcc, EnvVars env, final ExtendedEmailPublisherContext context, RecipientProviderUtilities.IDebug debug) { User user = change.getAuthor(); RecipientProviderUtilities.addUsers(Collections.singleton(user), context, env, to, cc, bcc, debug); } @Extension public static final class DescriptorImpl extends RecipientProviderDescriptor { @Override public String getDisplayName() { return Messages.UpstreamComitterRecipientProvider_DisplayName(); } } }