Notifications when VCS Changes are detected
I am attempting to send a notification (specifically an email) when changes are detected on a VCS root. I am able to successfully know when there is a change on the VCS root by extending BuildServerAdapter and overriding the changeAdded method. Here is my question: Is there a way to access the notifications settings TeamCity uses and supply my own template file? I was thinking something along the lines of a SendEmail method where I pass in a template file and a list of users to send it to. Then TeamCity would use the Email Notifier settings to send an email based off the supplied template to the listed users.
Thanks for the help,
~Alex
Please sign in to leave a comment.
I have made some progress in this, but I think I'm at a stopping point. I am now able to get the Email Notificator, but the only methods it has is the existing Notify methods (Build Succeeded, Build Failed, etc.). There does not seem to be a way to use this Notificator to send a completely new message using the SMTP settings of the Email Notificator, nor does it have a way to get those SMTP settings for me to reuse.
I was able to achive my end goal using JavaMail (namely send an email when VCS Changes are detected). This requires me to get the SMTP settings in some way, which are currently hard coded so I could get it to work. However, I still think there should be a way for me to access the SMTP settings of the existing Email Notifier or better yet have a method on the Email Notifier (or any notifier) that would let me pass in a Template file and a collection of SUsers that will recieve the message (and perhaps optionally some Object that would contain dynamic values used by the Template).
~Alex
Sorry for delay, probably you could use jetbrains.buildServer.notification.MessageSender interface. For example, EmailNotifier implements it.
In general you can obtain all of the message senders from ServerExtensionHolder (available as Spring bean):
Collection<MessageSender> messageSenders = extensionHolder.getExtensions(MessageSender.class);
Then you can try to find sender you need, compose message and send it to users. In this case you won't need to duplicate SMTP settings in your plugin.
I had seen the MessageSender interface, but didn't see any classes that implemented it. I figured there would be some, and I'll look into ServerExtensionHolder.
Thanks for the info,
~Alex
Pavel,
This is excatly what I was looking for. Thank you. Does the EMailNotifier have an id so that I could use the getExtension method and grab it specifically instead of getting all of the Extensions and looping through them? I tried "email" since that is the id you would use to get the Notifier, but that did not return anything.
Thanks,
~Alex
P.S.
For anyone else who's looking to do this, here's what I did:
private MessageSender _emailNotifier = null;
private String _subject = "This is the subject";
private String _defaultBody = "This is the default body, with a parameter {0}";
public PendingChangesListener(SBuildServer sBuildServer, ServerExtensionHolder extensionHolder) {
sBuildServer.addListener(this);
Collection<MessageSender> messageSenders = extensionHolder.getExtensions(MessageSender.class);
System.out.println("Create PendingChangesListener");
for (MessageSender messageSender : messageSenders)
{
if (messageSender.describe().equals("Email notifier"))
{
_emailNotifier = messageSender;
}
}
}
@Override
public void changeAdded(@NotNull final VcsModification modification,
@NotNull final VcsRoot root,
@Nullable final Collection<SBuildType> buildTypes)
{
System.out.println("Changes Detected");
if (_emailNotifier != null)
{
String modId = String.valueOf(((SVcsModification)modification).getId());
String _body = MessageFormat.format(_defaultBody, modId);
Collection<SUser> users = ((SVcsModification)modification).getCommitters();
if (users != null)
{
HashSet<String> emails = new HashSet<String>(users.size());
for (SUser user : users)
{
emails.add(_emailNotifier.getAddress(user));
}
_emailNotifier.sendMessage(_subject, _body, emails);
}
}
}
Unfortunately there is no id at the moment. So you have to use describe() method. We'll improve this API in the future.
Since we are really getting the EmailNotifier class which implements MessageSender anyway, would it be resonable to use the NotificatorRegistry which lets me use findNotificator("email") to get the Email Notificator directly and then cast it as a MessageSender once I got it? Or do I have it wrong that these two objects are the same?
Right now looping through the Extensions isn't a big issue because the EmailNotifier is the only thing in there, but I just have a gut aversion to looping through a collection to find a specific one.
~Alex
Well, if you want to send notifications by email only, you can indeed take email notifier from the NotificatorRegistry by its id, and then work with it through MessagesSender interface. The only problem with this approach is that email notifier is a plugin and can be removed from the system (manually for example). From the other hand, probability of this is very low.
Yes, currently I am only interested in sending notifications by email. Wouldn't the issue of the email notifier not being there also occur with the ServerExtensionHolder approach of getting the MessageSender as well?
~Alex
If none of the extensions implements MessagesSender interface, you'll receive empty list.
Alright, thanks for all the information. I think I'll keep using the ServerExtensionHolder approach since I already have that working and the Email Notifier is the only thing I'm getting back anyway. It also seems to be the most direct way of getting the MessageSender, otherwise I'm relying on retreiving an object that happens to also be a MessageSender. In both approaches I would be making the assumption that the Email Notifier is there, and since no plugins we are using currently remove it (or add another MessageSender) I think this is a safe assumption.