package com.hubspot.blazar.visitor.repositorybuild;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.hubspot.blazar.base.RepositoryBuild;
import com.hubspot.blazar.base.notifications.InstantMessageConfiguration;
import com.hubspot.blazar.base.visitor.RepositoryBuildVisitor;
import com.hubspot.blazar.data.service.InstantMessageConfigurationService;
import com.hubspot.blazar.data.service.RepositoryBuildService;
import com.hubspot.blazar.util.BlazarSlackClient;
import com.hubspot.blazar.util.SlackMessageBuildingUtils;
@Singleton
public class SlackRoomNotificationVisitor implements RepositoryBuildVisitor {
private static final Logger LOG = LoggerFactory.getLogger(SlackRoomNotificationVisitor.class);
private InstantMessageConfigurationService instantMessageConfigurationService;
private BlazarSlackClient blazarSlackClient;
private final SlackMessageBuildingUtils slackMessageBuildingUtils;
private final RepositoryBuildService repositoryBuildService;
@Inject
public SlackRoomNotificationVisitor(
InstantMessageConfigurationService instantMessageConfigurationService,
BlazarSlackClient blazarSlackClient,
SlackMessageBuildingUtils slackMessageBuildingUtils,
RepositoryBuildService repositoryBuildService) {
this.instantMessageConfigurationService = instantMessageConfigurationService;
this.blazarSlackClient = blazarSlackClient;
this.slackMessageBuildingUtils = slackMessageBuildingUtils;
this.repositoryBuildService = repositoryBuildService;
}
@Override
public void visit(RepositoryBuild build) throws Exception {
if (!(build.getState().isComplete())) {
return;
}
Set<InstantMessageConfiguration> configurationSet = instantMessageConfigurationService.getAllWithBranchId(build.getBranchId());
Optional<RepositoryBuild> previous = repositoryBuildService.getPreviousBuild(build);
for (InstantMessageConfiguration instantMessageConfiguration : configurationSet) {
if (shouldSendMessage(instantMessageConfiguration, build.getState(), previous, build)) {
blazarSlackClient.sendMessageToChannel(instantMessageConfiguration.getChannelName(), "", slackMessageBuildingUtils.buildSlackAttachment(build));
}
}
}
private boolean shouldSendMessage(
InstantMessageConfiguration instantMessageConfiguration,
RepositoryBuild.State state,
Optional<RepositoryBuild> previous,
RepositoryBuild build) {
boolean shouldSend = false;
final String logBase = String.format("Will send slack notification: RepoBuild %s,", String.valueOf(build.getId()));
// OnChange
boolean isChanged = previous.isPresent() && previous.get().getState() != state;
boolean builtNewCode = build.getCommitInfo().isPresent() && !build.getCommitInfo().get().getNewCommits().isEmpty();
if (instantMessageConfiguration.getOnChange() && isChanged) {
LOG.info("{} OnChange {}, State has changed from {} to {}", logBase, instantMessageConfiguration.getOnChange(), previous.get().getState(), state);
shouldSend = true;
}
// OnSuccess
// We don't notify OnSuccess if we didn't build new code because developers care
// more about changes _they_ made than upstream changes being propagated etc.
if (instantMessageConfiguration.getOnFinish() && state.equals(RepositoryBuild.State.SUCCEEDED) && builtNewCode) {
LOG.info("{} OnSuccess {}", logBase, instantMessageConfiguration.getOnFinish());
shouldSend = true;
}
// OnFailure
if (instantMessageConfiguration.getOnFail() && state.isFailed()) {
LOG.info("{} OnFail {}, thisFailed {}", logBase, instantMessageConfiguration.getOnFail(), state.isFailed());
shouldSend = true;
}
if (!shouldSend) {
LOG.debug("Not sending slack message for RepoBuild {}", build.getId());
}
return shouldSend;
}
}