-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Store DownstreamBuildAction
on Run
instead of FlowNode
for consistent persistence even on completed builds
#128
Changes from all commits
f5ed9d0
cd63d16
ec1d5f8
339adf5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,47 +6,87 @@ | |
import hudson.model.Item; | ||
import hudson.model.ItemGroup; | ||
import hudson.model.Run; | ||
import org.jenkinsci.plugins.workflow.actions.PersistentAction; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import org.jenkinsci.plugins.workflow.graph.FlowNode; | ||
import org.springframework.security.access.AccessDeniedException; | ||
|
||
/** | ||
* Tracks the downstream build triggered by the {@code build} step. | ||
* Tracks downstream builds triggered by the {@code build} step, as well as the {@link FlowNode#getId} of the step. | ||
* | ||
* @see BuildUpstreamCause | ||
*/ | ||
public final class DownstreamBuildAction extends InvisibleAction implements PersistentAction { | ||
private final String jobFullName; | ||
private Integer buildNumber; | ||
public final class DownstreamBuildAction extends InvisibleAction { | ||
private final List<DownstreamBuild> downstreamBuilds = new ArrayList<>(); | ||
|
||
DownstreamBuildAction(Item job) { | ||
this.jobFullName = job.getFullName(); | ||
public static @NonNull DownstreamBuild getOrCreate(@NonNull Run<?, ?> run, @NonNull String flowNodeId, @NonNull Item job) { | ||
DownstreamBuildAction downstreamBuildAction; | ||
synchronized (DownstreamBuildAction.class) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unnecessary in the normal case since the relevant part of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. May as well keep it, does not add much clutter. |
||
downstreamBuildAction = run.getAction(DownstreamBuildAction.class); | ||
if (downstreamBuildAction == null) { | ||
downstreamBuildAction = new DownstreamBuildAction(); | ||
run.addAction(downstreamBuildAction); | ||
} | ||
} | ||
return downstreamBuildAction.getOrAddDownstreamBuild(flowNodeId, job); | ||
} | ||
|
||
public @NonNull String getJobFullName() { | ||
return jobFullName; | ||
public synchronized @NonNull List<DownstreamBuild> getDownstreamBuilds() { | ||
return Collections.unmodifiableList(new ArrayList<>(downstreamBuilds)); | ||
} | ||
|
||
/** | ||
* Get the build number of the downstream build, or {@code null} if the downstream build has not yet started or the queue item was cancelled. | ||
*/ | ||
public @CheckForNull Integer getBuildNumber() { | ||
return buildNumber; | ||
private synchronized @NonNull DownstreamBuild getOrAddDownstreamBuild(@NonNull String flowNodeId, @NonNull Item job) { | ||
for (DownstreamBuild build : downstreamBuilds) { | ||
if (build.getFlowNodeId().equals(flowNodeId)) { | ||
return build; | ||
} | ||
} | ||
var build = new DownstreamBuild(flowNodeId, job); | ||
downstreamBuilds.add(build); | ||
return build; | ||
} | ||
|
||
/** | ||
* Load the downstream build, if it has started and still exists. | ||
* <p>Loading builds indiscriminately will affect controller performance, so use this carefully. If you only need | ||
* to know whether the build started at one point, use {@link #getBuildNumber}. | ||
* @throws AccessDeniedException as per {@link ItemGroup#getItem} | ||
*/ | ||
public @CheckForNull Run<?, ?> getBuild() throws AccessDeniedException { | ||
if (buildNumber == null) { | ||
return null; | ||
} | ||
return Run.fromExternalizableId(jobFullName + '#' + buildNumber); | ||
} | ||
public static final class DownstreamBuild { | ||
private final String flowNodeId; | ||
private final String jobFullName; | ||
private Integer buildNumber; | ||
|
||
DownstreamBuild(String flowNodeId, @NonNull Item job) { | ||
this.flowNodeId = flowNodeId; | ||
this.jobFullName = job.getFullName(); | ||
} | ||
|
||
public @NonNull String getFlowNodeId() { | ||
return flowNodeId; | ||
} | ||
|
||
void setBuild(Run<?, ?> build) { | ||
this.buildNumber = build.getNumber(); | ||
public @NonNull String getJobFullName() { | ||
return jobFullName; | ||
} | ||
|
||
/** | ||
* Get the build number of the downstream build, or {@code null} if the downstream build has not yet started or the queue item was cancelled. | ||
*/ | ||
public @CheckForNull Integer getBuildNumber() { | ||
return buildNumber; | ||
} | ||
|
||
/** | ||
* Load the downstream build, if it has started and still exists. | ||
* <p>Loading builds indiscriminately will affect controller performance, so use this carefully. If you only need | ||
* to know whether the build started at one point, use {@link #getBuildNumber}. | ||
* @throws AccessDeniedException as per {@link ItemGroup#getItem} | ||
*/ | ||
public @CheckForNull Run<?, ?> getBuild() throws AccessDeniedException { | ||
if (buildNumber == null) { | ||
return null; | ||
} | ||
return Run.fromExternalizableId(jobFullName + '#' + buildNumber); | ||
} | ||
|
||
void setBuild(@NonNull Run<?, ?> run) { | ||
this.buildNumber = run.getNumber(); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment this out and
downstreamBuildActionUpstreamCompletesBeforeDownstreamStarts
will fail.