Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Delayed approval mechanism [FIXED JENKINS-11409]
This patch introduces the possibility for a delayed approval to be sent back to Gerrit. This is a relatively advanced use case, so the setting has been placed in the Advanced section for the Trigger settings. When one selects "delayed approval", the completion of the build will NOT send an approval back to Gerrit. Instead, the triggering event stays open, and needs to be closed later on. This can be done by using the new post-build action "Send a Gerrit delayed approval". At the moment, this notifier expects to read the name of the job and build number from build variables. If these point to an existing build which has a Gerrit event as a trigger, which has not been submitted due to "delayed approval", then that approval will be sent. In particular, this allows to modify the status of that build through other job (e.g., using Groovy scripts), and mark it UNSTABLE (e.g., if a subsequent build were to fail), which is a way one can change the result of the Approval in Gerrit. Amends: fixed broken style and broken unit tests
- Loading branch information
Showing
9 changed files
with
287 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
212 changes: 212 additions & 0 deletions
212
...a/com/sonyericsson/hudson/plugins/gerrit/trigger/hudsontrigger/GerritDelayedApprover.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
/* | ||
* The MIT License | ||
* | ||
* Copyright 2010 Sony Ericsson Mobile Communications. All rights reserved. | ||
* Copyright 2012 Sony Mobile Communications AB. All rights reserved. | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
package com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger; | ||
|
||
|
||
import hudson.Extension; | ||
import hudson.Util; | ||
//import org.slf4j.Logger; | ||
//import org.slf4j.LoggerFactory; | ||
import org.kohsuke.stapler.DataBoundConstructor; | ||
import hudson.tasks.BuildStepDescriptor; | ||
import hudson.tasks.BuildStepMonitor; | ||
import hudson.tasks.Notifier; | ||
import hudson.tasks.Publisher; | ||
import hudson.model.AbstractProject; | ||
import hudson.model.AbstractBuild; | ||
import hudson.model.BuildListener; | ||
import hudson.model.Hudson; | ||
import java.util.Map; | ||
import hudson.Launcher; | ||
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.ToGerritRunListener; | ||
|
||
|
||
/** | ||
* Triggers a build previously run to send its report to Gerrit, if it hadn't yet. | ||
* | ||
* @author Yannick Bréhon <yannick.brehon@smartmatic.com> | ||
*/ | ||
|
||
public class GerritDelayedApprover extends Notifier { | ||
|
||
//private static final Logger logger = LoggerFactory.getLogger(GerritDelayedApprover.class); | ||
private String delayedJob; | ||
private String delayedBuildNumber; | ||
|
||
|
||
/** | ||
* Default DataBound Constructor. | ||
* | ||
* @param delayedJob the name of the job which may need a delayed approval. buildVariables are expanded. | ||
* @param delayedBuildNumber the number of the build which may need a delayed approval. buildVariables are expanded. | ||
*/ | ||
@DataBoundConstructor | ||
public GerritDelayedApprover( | ||
String delayedJob, | ||
String delayedBuildNumber) { | ||
this.delayedJob = delayedJob; | ||
this.delayedBuildNumber = delayedBuildNumber; | ||
} | ||
/** | ||
* The delayedBuildNumber, ie number of the build which may need a delayed approval. | ||
* | ||
* @return the delayedBuildNumber | ||
*/ | ||
public String getDelayedBuildNumber() { | ||
return delayedBuildNumber; | ||
} | ||
|
||
/** | ||
* Sets the delayedBuildNumber. | ||
* | ||
* @param delayedBuildNumber | ||
* the delayedBuildNumber | ||
*/ | ||
public void setDelayedBuildNumber(String delayedBuildNumber) { | ||
this.delayedBuildNumber = delayedBuildNumber; | ||
} | ||
|
||
/** | ||
* The delayedJob, ie the name of the job which may need a delayed approval. | ||
* | ||
* @return the delayedJob | ||
*/ | ||
public String getDelayedJob() { | ||
return delayedJob; | ||
} | ||
|
||
/** | ||
* Sets the delayedJob. | ||
* | ||
* @param delayedJob | ||
* the delayedJob | ||
*/ | ||
public void setDelayedJob(String delayedJob) { | ||
this.delayedJob = delayedJob; | ||
} | ||
|
||
/** | ||
* No concurrency management is required, new style extension. | ||
* @return BuildStepMonitor.NONE | ||
* | ||
*/ | ||
public BuildStepMonitor getRequiredMonitorService() { | ||
return BuildStepMonitor.NONE; | ||
} | ||
|
||
/** | ||
* This extension needs to run after the build is completed. | ||
* @return true | ||
* | ||
*/ | ||
@Override | ||
public boolean needsToRunAfterFinalized() { | ||
return true; | ||
} | ||
|
||
/** | ||
* The actual performer method which will run in a post-build step and close a Gerrit Triggered event. | ||
* @param build current build | ||
* @param launcher launcher | ||
* @param listener the build listener | ||
* @throws InterruptedException if interrupted | ||
* @return boolean indicating whether this perform step succeeded | ||
*/ | ||
public boolean perform(final AbstractBuild<?, ?> build, final Launcher launcher, final BuildListener listener) | ||
throws InterruptedException { | ||
//logger.info("Running Gerrit Delayed Approval"); | ||
Map<String, String> buildVars = build.getBuildVariables(); | ||
String jobName = Util.replaceMacro(delayedJob, buildVars); | ||
String numberStr = Util.replaceMacro(delayedBuildNumber, buildVars); | ||
int number = Integer.parseInt(numberStr); | ||
|
||
//String jobName = (String) build.getBuildVariables().get(jobParameterName); | ||
//int number = Integer.parseInt((String)build.getBuildVariables().get(buildNumParameterName)); | ||
AbstractProject initiatingJob = Hudson.getInstance().getItemByFullName(jobName, AbstractProject.class); | ||
if (initiatingJob == null) { | ||
return false; | ||
} | ||
AbstractBuild initiatingBuild = (AbstractBuild)initiatingJob.getBuildByNumber(number); | ||
GerritCause cause = (GerritCause)initiatingBuild.getCause(GerritCause.class); | ||
if (cause == null) { | ||
return false; | ||
} | ||
ToGerritRunListener thelistener = ToGerritRunListener.getInstance(); | ||
thelistener.allBuildsCompleted(cause.getEvent(), cause, null); | ||
return true; | ||
} | ||
|
||
/*---------------------------------*/ | ||
/* ----- Descriptor stuff -------- */ | ||
/*---------------------------------*/ | ||
|
||
/** | ||
* getter for the Descriptor. | ||
* @return the associated descriptor | ||
*/ | ||
@Override | ||
public BuildStepDescriptor<Publisher> getDescriptor() { | ||
return DESCRIPTOR; | ||
} | ||
|
||
/** | ||
* The associated descriptor instance. | ||
*/ | ||
public static final GerritDelayedApproverDescriptor DESCRIPTOR = new GerritDelayedApproverDescriptor(); | ||
|
||
/** | ||
* Descriptor class. | ||
*/ | ||
@Extension | ||
public static final class GerritDelayedApproverDescriptor extends | ||
BuildStepDescriptor<Publisher> { | ||
|
||
//private static final Logger logger = LoggerFactory.getLogger(GerritDelayedApproverDescriptor.class); | ||
|
||
/** | ||
* Overridden constructor, needed to reload saved data. | ||
*/ | ||
public GerritDelayedApproverDescriptor() { | ||
super(GerritDelayedApprover.class); | ||
load(); | ||
} | ||
|
||
@Override | ||
public String getDisplayName() { | ||
return "Send a delayed Gerrit approval"; | ||
} | ||
|
||
@Override | ||
public boolean isApplicable(Class<? extends AbstractProject> jobType) { | ||
return true; | ||
} | ||
|
||
/*@Override | ||
public String getHelpFile() { | ||
return "/plugin/build-publisher/help/config/publish.html"; | ||
}*/ | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
...nyericsson/hudson/plugins/gerrit/trigger/hudsontrigger/GerritDelayedApprover/config.jelly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form"> | ||
<f:entry name="delayedJob" title="Name of the job name which may need a delayed approval" field="delayedJob"> | ||
<f:textbox name="delayedJob" value="${instance.delayedJob==null?'$JOB_TO_GERRITCOMPLETE':instance.delayedJob}"/> | ||
</f:entry> | ||
<f:entry name="delayedBuildNumber" title="Build number which may need a delayed approval" field="delayedBuildNumber"> | ||
<f:textbox name="delayedBuildNumber" value="${instance.delayedBuildNumber==null?'$BUILD_TO_GERRITCOMPLETE':instance.delayedBuildNumber}"/> | ||
</f:entry> | ||
</j:jelly> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
gerrithudsontrigger/src/main/webapp/trigger/help-DelayedApproval.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Select this option to prevent Jenkins from sending the approval at the end of this build. A post-build "delayed approval" will be necessary to have the result sent back to Gerrit. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.