Skip to content

Commit

Permalink
JENKINS-30801 limit Action objects in re-trigger to CauseAction
Browse files Browse the repository at this point in the history
Passing all Action objects from previous builds results in unexpected
behavior: certain publisher and Builder rely on them to publish
information about the build, and should not be copied to the next build.

The only reason to copy Action objects is to preserve the cause of the build
in order to keep it in the pipeline and replay how the build was triggered.
  • Loading branch information
Dan Alvizu committed Oct 5, 2015
1 parent d155dca commit 8357d74
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 40 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -10,9 +10,11 @@ target
work

.checkstyle
checkstyle-cachefile

# IntelliJ
.idea/
*.iml
*.ipr
*.iws

Expand Up @@ -404,32 +404,18 @@ public int triggerManualBuild(final Integer upstreamBuildNumber, final String tr
return triggerBuild(triggerProject, upstreamBuild, buildParametersAction);
}

/**
* @param triggerProjectName
* the triggerProjectName
* @return the number of re-tried build
*/
@JavaScriptMethod
public int retryBuild(final String triggerProjectName) {
LOGGER.fine("Retrying build again: " + triggerProjectName); //$NON-NLS-1$
final AbstractProject<?, ?> triggerProject = (AbstractProject<?, ?>) super.getJob(triggerProjectName);
triggerProject.scheduleBuild(new MyUserIdCause());

return triggerProject.getNextBuildNumber();
}

/**
* @param externalizableId
* the externalizableId
* @return the number of re-run build
*/
@JavaScriptMethod
public int rerunBuild(final String externalizableId) {
LOGGER.fine("Running build again: " + externalizableId); //$NON-NLS-1$
LOGGER.info("Running build again: " + externalizableId); //$NON-NLS-1$
final AbstractBuild<?, ?> triggerBuild = (AbstractBuild<?, ?>) Run.fromExternalizableId(externalizableId);
final AbstractProject<?, ?> triggerProject = triggerBuild.getProject();
final Future<?> future = triggerProject.scheduleBuild2(triggerProject.getQuietPeriod(), new MyUserIdCause(),
removeUserIdCauseActions(triggerBuild.getActions()));
filterCauseActions(triggerBuild.getActions()));

AbstractBuild<?, ?> result = triggerBuild;
try {
Expand Down Expand Up @@ -584,43 +570,50 @@ private static ParametersAction mergeParameters(final ParametersAction base, fin
return new ParametersAction(params.values().toArray(new ParameterValue[params.size()]));
}


/**
* Checks whether the given {@link Action} contains a reference to a {@link UserIdCause} object.
* Filter out the list of actions so that it only includes CauseActions, but exclude
* CauseActions containing a UserIdCause
*
* We want to include CauseAction because that includes upstream cause actions, which
* are inherited in downstream builds.
*
* @param buildAction
* the action to check.
* @return <code>true</code> if the action has a reference to a userId cause.
* We do not want to inherit the UserId cause, because the user initiating a retry may
* be different than the user who originated the upstream build, and so should be
* re-identified.
*
* We do not want to inherit any other CauseAction because that will result in duplicating
* actions from publishers, and builders from previous builds corrupting the retriggered build.
*
* @param actions
* a collection of build actions.
* @return a collection of build actions with all UserId causes removed.
*/
private boolean isUserIdCauseAction(final Action buildAction) {
boolean retval = false;
if (buildAction instanceof CauseAction) {
for (final Cause cause : ((CauseAction) buildAction).getCauses()) {
if (cause instanceof UserIdCause) {
retval = true;
break;
private List<Action> filterCauseActions(final List<Action> actions) {
final List<Action> retval = new ArrayList<Action>();
for (final Action action : actions) {
if (action instanceof CauseAction) {
final CauseAction causeAction = (CauseAction) action;
if (!actionHasUserIdCause(causeAction)) {
retval.add(action);
}
}
}
return retval;
}

/**
* Removes any UserId cause action from the given actions collection. This is used by downstream builds that inherit upstream actions.
* The downstream build can be initiated by another user that is different from the user who initiated the upstream build, so the
* downstream build needs to remove the old user action inherited from upstream, and add its own.
*
* @param actions
* a collection of build actions.
* @return a collection of build actions with all UserId causes removed.
* @param causeAction
* the causeAction to query
* @return whether the action has a {@link UserIdCause}
*/
private List<Action> removeUserIdCauseActions(final List<Action> actions) {
final List<Action> retval = new ArrayList<Action>();
for (final Action action : actions) {
if (!isUserIdCauseAction(action)) {
retval.add(action);
private boolean actionHasUserIdCause(CauseAction causeAction) {
for (final Cause cause : causeAction.getCauses()) {
if (cause instanceof UserIdCause) {
return true;
}
}
return retval;
return false;
}

/**
Expand Down

0 comments on commit 8357d74

Please sign in to comment.