Skip to content

Commit

Permalink
[JENKINS-37368] Improve performance in DownstreamPassCondition RunLis…
Browse files Browse the repository at this point in the history
…tener (#105)

* [JENKINS-37368] Improve performance of DownstreamPassCondition RunListener

* Fix formatting by removing spaces around operators

* Fix formatting by removing space around operators

* Set EnvVars before impersonating SYSTEM

* Check that the ItemGroup matches before checking for READ permission

* Add test to asset that the SecurityContext is reset after calling DownstreamPassCondition's RunListener

* Revert "Add test to asset that the SecurityContext is reset after calling DownstreamPassCondition's RunListener"

This reverts commit 80b4749.
  • Loading branch information
dwnusbaum authored and oleg-nenashev committed Sep 7, 2017
1 parent 66cb6f1 commit 8fdcd82
Showing 1 changed file with 59 additions and 48 deletions.
Expand Up @@ -27,13 +27,17 @@
import hudson.plugins.promoted_builds.PromotionConditionDescriptor;
import hudson.plugins.promoted_builds.PromotionProcess;
import hudson.plugins.promoted_builds.util.JenkinsHelper;
import hudson.security.ACL;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;

import java.io.IOException;
import java.security.Security;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
Expand Down Expand Up @@ -263,67 +267,74 @@ public RunListenerImpl() {
public void onCompleted(AbstractBuild<?,?> build, TaskListener listener) {
// this is not terribly efficient,
EnvVars buildEnvironment = new EnvVars(build.getBuildVariables());
for(AbstractProject<?,?> j : JenkinsHelper.getInstance().getAllItems(AbstractProject.class)) {
boolean warned = false; // used to avoid warning for the same project more than once.

JobPropertyImpl jp = j.getProperty(JobPropertyImpl.class);
if(jp!=null) {
for (PromotionProcess p : jp.getItems()) {
boolean considerPromotion = false;
for (PromotionCondition cond : p.conditions) {
if (cond instanceof DownstreamPassCondition) {
DownstreamPassCondition dpcond = (DownstreamPassCondition) cond;
if(dpcond.contains(j.getParent(), build.getParent(), buildEnvironment)) {
considerPromotion = true;
break;
SecurityContext previousCtx = ACL.impersonate(ACL.SYSTEM);
try {
for (AbstractProject<?,?> j : JenkinsHelper.getInstance().getAllItems(AbstractProject.class)) {
boolean warned = false; // used to avoid warning for the same project more than once.

JobPropertyImpl jp = j.getProperty(JobPropertyImpl.class);
if (jp!=null) {
for (PromotionProcess p : jp.getItems()) {
boolean considerPromotion = false;
for (PromotionCondition cond : p.conditions) {
if (cond instanceof DownstreamPassCondition) {
DownstreamPassCondition dpcond = (DownstreamPassCondition) cond;
if (dpcond.contains(j.getParent(), build.getParent(), buildEnvironment)
&& j.getACL().hasPermission(previousCtx.getAuthentication(), Item.READ)) {
considerPromotion = true;
break;
}
}
}
}
if(considerPromotion) {
try {
AbstractBuild<?,?> u = build.getUpstreamRelationshipBuild(j);
if (u==null) {
// if the fingerprint doesn't tell us, perhaps the cause would tell us?
final Stack<List<Cause>> stack = new Stack<List<Cause>>();
stack.push(build.getCauses());

while(!stack.isEmpty()) {
for (UpstreamCause uc : Util.filter(stack.pop(), UpstreamCause.class)) {
if (uc.getUpstreamProject().equals(j.getFullName())) {
u = j.getBuildByNumber(uc.getUpstreamBuild());
if (u!=null) {
// remember that this build is a pseudo-downstream of the discovered build.
PseudoDownstreamBuilds pdb = u.getAction(PseudoDownstreamBuilds.class);
if (pdb==null)
u.addAction(pdb=new PseudoDownstreamBuilds());
pdb.add(build);
u.save();
break;
if (considerPromotion) {
try {
AbstractBuild<?,?> u = build.getUpstreamRelationshipBuild(j);
if (u==null) {
// if the fingerprint doesn't tell us, perhaps the cause would tell us?
final Stack<List<Cause>> stack = new Stack<List<Cause>>();
stack.push(build.getCauses());

while (!stack.isEmpty()) {
for (UpstreamCause uc : Util.filter(stack.pop(), UpstreamCause.class)) {
if (uc.getUpstreamProject().equals(j.getFullName())) {
u = j.getBuildByNumber(uc.getUpstreamBuild());
if (u!=null) {
// remember that this build is a pseudo-downstream of the discovered build.
PseudoDownstreamBuilds pdb = u.getAction(PseudoDownstreamBuilds.class);
if (pdb==null)
u.addAction(pdb=new PseudoDownstreamBuilds());
pdb.add(build);
u.save();
break;
}
}
stack.push(uc.getUpstreamCauses());
}
stack.push(uc.getUpstreamCauses());
}
}
}
if (u==null) {
// no upstream build. perhaps a configuration problem?
if(build.getResult()==Result.SUCCESS && !warned) {
listener.getLogger().println("WARNING: "+j.getFullDisplayName()+" appears to use this job as a promotion criteria, " +
"but no fingerprint is recorded. Fingerprint needs to be enabled on both this job and "+j.getFullDisplayName()+". " +
"See https://wiki.jenkins-ci.org/display/JENKINS/Fingerprint for more details");
warned = true;
if (u==null) {
// no upstream build. perhaps a configuration problem?
if (build.getResult()==Result.SUCCESS && !warned) {
listener.getLogger().println("WARNING: "+j.getFullDisplayName()+" appears to use this job as a promotion criteria, " +
"but no fingerprint is recorded. Fingerprint needs to be enabled on both this job and "+j.getFullDisplayName()+". " +
"See https://wiki.jenkins-ci.org/display/JENKINS/Fingerprint for more details");
warned = true;
}
}
}

if(u!=null && p.considerPromotion2(u)!=null)
listener.getLogger().println("Promoted "+HyperlinkNote.encodeTo('/'+u.getUrl(),u.getFullDisplayName()));
} catch (IOException e) {
e.printStackTrace(listener.error("Failed to promote a build"));
if (u!=null && p.considerPromotion2(u)!=null)
listener.getLogger().println("Promoted " + HyperlinkNote.encodeTo('/'+u.getUrl(), u.getFullDisplayName()));
} catch (IOException e) {
e.printStackTrace(listener.error("Failed to promote a build"));
}
}
}
}
}
}
finally {
SecurityContextHolder.setContext(previousCtx);
}
}

/**
Expand Down

0 comments on commit 8fdcd82

Please sign in to comment.