Skip to content

Commit

Permalink
Merge pull request #468 from ckreisl/feature-add-vote-patches-same-topic
Browse files Browse the repository at this point in the history
[JENKINS-65349] Feature voting patchsets with the same topic
  • Loading branch information
rsandell committed Nov 11, 2022
2 parents 17c5aed + 9f8f222 commit 2b1f287
Show file tree
Hide file tree
Showing 22 changed files with 968 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,45 @@ public static GerritServer getServer_(String name) {
return plugin.getServer(name);
}

/**
* Returns the Gerrit Server based on the GerritTriggerEvent.
*
* @param event The GerritTriggerEvent.
* @return GerritServer or null if no server could be found.
*/
public GerritServer getServer(GerritTriggeredEvent event) {
Provider provider = event.getProvider();
if (provider == null) {
logger.warn("The event {} has no provider specified. BUG!", event);
return null;
}
GerritServer gerritServer = getServer_(provider.getName());
if (gerritServer == null) {
logger.warn("Could not find server config for {} - no such server.", provider.getName());
return null;
}
return gerritServer;
}

/**
* Returns a GerritServer object based on a GerritTriggerEvent.
*
* Static short for {@link #getServer(GerritTriggeredEvent)}.
*
* @param event The GerritTriggerEvent.
* @return GerritServer or null if no server could be found.
*/
@CheckForNull
//CS IGNORE MethodName FOR NEXT 1 LINES. REASON: Static equivalent marker.
public static GerritServer getServer_(GerritTriggeredEvent event) {
PluginImpl plugin = getInstance();
if (plugin == null) {
logger.debug("Error, plugin instance could not be found!");
return null;
}
return plugin.getServer(event);
}

/**
* Gets the first server in the server list. Or null if there are no servers.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ public class Config implements IGerritHudsonTriggerConfig {
private WatchTimeExceptionData watchTimeExceptionData;
private Notify notificationLevel;
private BuildCancellationPolicy buildCurrentPatchesOnly;
private boolean voteSameTopic;

/**
* Constructor.
Expand Down Expand Up @@ -314,6 +315,8 @@ public void setValues(JSONObject formData) {
buildCurrentPatchesOnly = new BuildCancellationPolicy();
}

voteSameTopic = formData.optBoolean("voteSameTopic", false);

numberOfWorkerThreads = formData.optInt(
"numberOfReceivingWorkerThreads",
DEFAULT_NR_OF_RECEIVING_WORKER_THREADS);
Expand Down Expand Up @@ -859,6 +862,32 @@ public void setBuildCurrentPatchesOnly(BuildCancellationPolicy buildCurrentPatch
this.buildCurrentPatchesOnly = buildCurrentPatchesOnly;
}

@Override
public boolean isVoteSameTopic() {
return voteSameTopic;
}

/**
* Standard setter for the voteSameTopic value.
*
* @param voteSameTopic true if patchsets with same topic should be voted together.
*/
public void setVoteSameTopic(boolean voteSameTopic) {
this.voteSameTopic = voteSameTopic;
}

/**
* Returns the description message for the jelly entry.
*
* @return descriptionMsg for jelly.
*/
public String getVoteSameTopicDescription() {
return "<b>Warning:</b>"
+ " The current implementation takes into account that 'Build Current Patches Only'"
+ " with 'Abort new patch sets' and 'Abort patch sets with same topic' are <b>enabled</b>"
+ " (see help for more).";
}

@Override
public String getGerritCmdBuildSuccessful() {
return gerritVerifiedCmdBuildSuccessful;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,18 @@ public interface IGerritHudsonTriggerConfig extends GerritConnectionConfig2 {

/**
* If enabled, then old patch revision builds will be canceled.
*
* @return true if so.
*/
boolean isGerritBuildCurrentPatchesOnly();

/**
* If enabled, build notifications and votes will be sent to patchsets with the same topic.
*
* @return true if so.
*/
boolean isVoteSameTopic();

/**
* The object containing information regarding if old builds should
* be cancelled when new builds are triggered.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
*/
package com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier;

import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.notification.INotification;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.notification.Notification;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.notification.NotificationCommands;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.notification.NotificationBuildCompleted;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.notification.NotificationBuildStarted;
import com.sonymobile.tools.gerrit.gerritevents.GerritCmdRunner;
import com.sonymobile.tools.gerrit.gerritevents.dto.events.ChangeBasedEvent;
import com.sonymobile.tools.gerrit.gerritevents.dto.events.GerritTriggeredEvent;
Expand All @@ -44,8 +49,8 @@
public class GerritNotifier {

private static final Logger logger = LoggerFactory.getLogger(GerritNotifier.class);
private GerritCmdRunner cmdRunner;
private ParameterExpander parameterExpander;
private final GerritCmdRunner cmdRunner;
private final ParameterExpander parameterExpander;

/**
* Constructor.
Expand All @@ -68,6 +73,34 @@ public GerritNotifier(IGerritHudsonTriggerConfig config, GerritCmdRunner cmdRunn
this.parameterExpander = new ParameterExpander(config, jenkins);
}

/**
* Send Notification to gerrit.
*
* @param notification The notifications.
*/
private void send(INotification notification) {

if (notification == null) {
logger.error("NotificationObject is null not sending command!");
return;
}

if (!notification.isValid()) {
logger.error("Something wrong during parameter extraction. "
+ "Gerrit will not be notified of BuildStarted!");
return;
}

NotificationCommands notifyCommands = notification.getCommands();
cmdRunner.sendCommand(notifyCommands.getCommand());

if (notification.isVoteSameTopic()) {
for (String command : notifyCommands.getCommandsTopicChanges()) {
cmdRunner.sendCommand(command);
}
}
}

/**
* Generates the build-started command based on configured templates and build-values and sends it to Gerrit.
* @param build the build.
Expand All @@ -80,18 +113,15 @@ public void buildStarted(Run build, TaskListener taskListener,
try {
/* Without a change, it doesn't make sense to notify gerrit */
if (event instanceof ChangeBasedEvent) {
String command =
parameterExpander.getBuildStartedCommand(build, taskListener, (ChangeBasedEvent)event, stats);
if (command != null) {
if (!command.isEmpty()) {
logger.debug("Notifying BuildStarted to gerrit: {}", command);
cmdRunner.sendCommand(command);
GerritTriggeredBuildListener.fireOnStarted(event, command);
} else {
logger.debug("BuildStarted command is empty. Gerrit will not be notified of BuildStarted");
}
Notification notification = new NotificationBuildStarted(
build, taskListener, event, stats, parameterExpander);
if (notification.isValid()) {
send(notification);
String command = notification.getCommands().getCommand();
GerritTriggeredBuildListener.fireOnStarted(event, command);
} else {
logger.error("Something wrong during parameter extraction. "
logger.error("Notification commands object is not valid. "
+ "Something went wrong during parameter extraction. "
+ "Gerrit will not be notified of BuildStarted");
}
}
Expand All @@ -106,23 +136,19 @@ public void buildStarted(Run build, TaskListener taskListener,
* @param listener the taskListener.
*/
public void buildCompleted(MemoryImprint memoryImprint, TaskListener listener) {

try {
/* Without a change, it doesn't make sense to notify gerrit */
if (memoryImprint.getEvent() instanceof ChangeBasedEvent) {
String command = parameterExpander.getBuildCompletedCommand(memoryImprint, listener);

if (command != null) {
if (!command.isEmpty()) {
logger.debug("Notifying BuildCompleted to gerrit: {}", command);
cmdRunner.sendCommand(command);
GerritTriggeredBuildListener.fireOnCompleted(memoryImprint, command);
} else {
logger.debug("BuildCompleted command is empty. Gerrit will not be notified of BuildCompleted");
}
Notification notification = new NotificationBuildCompleted(
memoryImprint, listener, parameterExpander);
if (notification.isValid()) {
send(notification);
String command = notification.getCommands().getCommand();
GerritTriggeredBuildListener.fireOnCompleted(memoryImprint, command);
} else {
logger.error("Something wrong during parameter extraction. "
+ "Gerrit will not be notified of BuildCompleted");
logger.error("Notification commands object is not valid. "
+ "Something went wrong during parameter extraction. "
+ "Gerrit will not be notified of BuildCompleted.");
}
}
} catch (Exception ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,18 @@
*
* @author Robert Sandell &lt;robert.sandell@sonyericsson.com&gt;
*/
public class NotificationFactory {
private static final Logger logger = LoggerFactory.getLogger(NotificationFactory.class);
private static NotificationFactory instance;
public class GerritNotifierFactory {
private static final Logger logger = LoggerFactory.getLogger(GerritNotifierFactory.class);
private static GerritNotifierFactory instance;

/**
* Gets the singleton instance of the NotificationFactory.
*
* @return the NotificationFactory.
*/
public static NotificationFactory getInstance() {
public static GerritNotifierFactory getInstance() {
if (instance == null) {
instance = new NotificationFactory();
instance = new GerritNotifierFactory();
}
return instance;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -513,9 +513,19 @@ public Notify getNotificationLevel(GerritTrigger trigger) {
*
* @param memoryImprint the memory with all the information
* @param listener the taskListener
* @param gerritEvent the event.
* @return the command.
*/
public String getBuildCompletedCommand(MemoryImprint memoryImprint, TaskListener listener) {
public String getBuildCompletedCommand(MemoryImprint memoryImprint, TaskListener listener,
GerritTriggeredEvent gerritEvent) {

GerritTriggeredEvent event;
if (gerritEvent == null) {
event = memoryImprint.getEvent();
} else {
event = gerritEvent;
}

String command;
// We only count builds without NOT_BUILT status normally. If *no*
// builds were successful, unstable or failed, we find the minimum
Expand Down Expand Up @@ -546,13 +556,13 @@ public String getBuildCompletedCommand(MemoryImprint memoryImprint, TaskListener
notifyLevel = getHighestNotificationLevel(memoryImprint, onlyCountBuilt);
}

Map<String, String> parameters = createStandardParameters(null, memoryImprint.getEvent(),
Map<String, String> parameters = createStandardParameters(null, event,
codeReview, verified, notifyLevel.name());

// escapes ' as '"'"' in order to avoid breaking command line param
// Details: http://stackoverflow.com/a/26165123/99834
parameters.put("BUILDS_STATS", createBuildsStats(memoryImprint,
listener,
parameters).replaceAll("'", "'\"'\"'"));
listener, parameters).replaceAll("'", "'\"'\"'"));

Run build = null;
Entry[] entries = memoryImprint.getEntries();
Expand Down Expand Up @@ -679,7 +689,7 @@ private String createBuildsStats(MemoryImprint memoryImprint, TaskListener liste
* @return the message for the build completed command.
*/
public String getBuildCompletedMessage(MemoryImprint memoryImprint, TaskListener listener) {
String completedCommand = getBuildCompletedCommand(memoryImprint, listener);
String completedCommand = getBuildCompletedCommand(memoryImprint, listener, null);
return findMessage(completedCommand);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public synchronized void allBuildsCompleted(GerritTriggeredEvent event, GerritCa
if (event instanceof GerritEventLifecycle) {
((GerritEventLifecycle)event).fireAllBuildsCompleted();
}
NotificationFactory.getInstance().queueBuildCompleted(memory.getMemoryImprint(event), listener);
GerritNotifierFactory.getInstance().queueBuildCompleted(memory.getMemoryImprint(event), listener);
} finally {
memory.forget(event);
}
Expand Down Expand Up @@ -241,7 +241,7 @@ public synchronized void onStarted(Run r, TaskListener listener) {
}
if (!silentStartMode) {
BuildsStartedStats stats = memory.getBuildsStartedStats(cause.getEvent());
NotificationFactory.getInstance().queueBuildStarted(r, listener, cause.getEvent(), stats);
GerritNotifierFactory.getInstance().queueBuildStarted(r, listener, cause.getEvent(), stats);
}
}
logger.info("Gerrit build [{}] Started for cause: [{}].", r, cause);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import com.sonymobile.tools.gerrit.gerritevents.workers.cmd.AbstractSendCommandJob;
import com.sonyericsson.hudson.plugins.gerrit.trigger.config.IGerritHudsonTriggerConfig;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.GerritNotifier;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.NotificationFactory;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.GerritNotifierFactory;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.model.BuildMemory;

import hudson.model.TaskListener;
Expand Down Expand Up @@ -63,7 +63,7 @@ public BuildCompletedCommandJob(IGerritHudsonTriggerConfig config,
@Override
public void run() {
try (ACLContext ctx = ACL.as(ACL.SYSTEM)) {
GerritNotifier notifier = NotificationFactory.getInstance()
GerritNotifier notifier = GerritNotifierFactory.getInstance()
.createGerritNotifier((IGerritHudsonTriggerConfig)getConfig(), this);
notifier.buildCompleted(memoryImprint, listener);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import com.sonymobile.tools.gerrit.gerritevents.workers.cmd.AbstractSendCommandJob;
import com.sonyericsson.hudson.plugins.gerrit.trigger.config.IGerritHudsonTriggerConfig;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.GerritNotifier;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.NotificationFactory;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.GerritNotifierFactory;
import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.model.BuildsStartedStats;

import hudson.model.TaskListener;
Expand Down Expand Up @@ -73,7 +73,7 @@ public BuildStartedCommandJob(IGerritHudsonTriggerConfig config, Run build,
@Override
public void run() {
try (ACLContext ctx = ACL.as(ACL.SYSTEM)) {
GerritNotifier notifier = NotificationFactory.getInstance()
GerritNotifier notifier = GerritNotifierFactory.getInstance()
.createGerritNotifier((IGerritHudsonTriggerConfig)getConfig(), this);
notifier.buildStarted(build, taskListener, event, stats);
}
Expand Down

0 comments on commit 2b1f287

Please sign in to comment.