Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
fr.mmarie.core.jira.JiraService Maven / Gradle / Ivy
package fr.mmarie.core.jira;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.inject.Inject;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import fr.mmarie.api.jira.Comment;
import fr.mmarie.api.jira.Transition;
import fr.mmarie.api.jira.input.TransitionInput;
import fr.mmarie.api.jira.response.CommentResponse;
import fr.mmarie.api.jira.response.TransitionResponse;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import retrofit.Callback;
import retrofit.JacksonConverterFactory;
import retrofit.Response;
import retrofit.Retrofit;
import retrofit.RxJavaCallAdapterFactory;
import java.io.IOException;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static fr.mmarie.utils.Common.sanitizeURL;
@Slf4j
public class JiraService {
public static final String TRANSITION_HOLDER = "{transition}";
/**
* Matches issues with name like : #TEST-1, does not support special characters in
* project name, #TEST-TEST-1 won't match.
*/
public static final Pattern ISSUE_PATTERN = Pattern.compile("#\\s*(\\w+-\\d+)");
private final JiraConfiguration jiraConfiguration;
private final JiraEndPoints jiraEndPoints;
@Inject
public JiraService(@NonNull JiraConfiguration jiraConfiguration) {
this.jiraConfiguration = jiraConfiguration;
OkHttpClient httpClient = new OkHttpClient();
httpClient.interceptors().add(chain -> {
String credentials = jiraConfiguration.getUsername() + ":" + jiraConfiguration.getPassword();
String encodedHeader = "Basic " + new String(Base64.getEncoder().encode(credentials.getBytes()));
Request requestWithAuthorization = chain.request().newBuilder().addHeader("Authorization", encodedHeader).build();
return chain.proceed(requestWithAuthorization);
});
this.jiraEndPoints = new Retrofit.Builder()
.baseUrl(sanitizeURL(jiraConfiguration.getUrl()))
.addConverterFactory(JacksonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(httpClient)
.build()
.create(JiraEndPoints.class);
}
public Response getIssue(String issue) throws IOException {
return jiraEndPoints.getIssue(issue).execute();
}
public Response getCommentsOfIssue(String issue) throws IOException {
return jiraEndPoints.getCommentsOfIssue(issue).execute();
}
public Response commentIssue(String issue, Comment comment) throws IOException {
return jiraEndPoints.commentIssue(issue, comment).execute();
}
public TransitionResponse getTransitionsOfIssue(String issue) {
return jiraEndPoints.getTransitionsOfIssue(issue).toBlocking().firstOrDefault(null);
}
public boolean transitionOnIssue(String issue, TransitionInput transitionInput) {
try {
Response response = jiraEndPoints.transitionsOnIssue(issue, transitionInput).execute();
if(response.isSuccess()) {
log.info("Transition {} has been made on {}", transitionInput, issue);
return true;
} else {
log.error("Bad response received <" + response.code() + ">, "
+ "unable to make the transition <{}> on <{}>, received message : " + response.message(),
issue,
transitionInput);
try {
log.error("Response body received : {}",
response.errorBody().string());
} catch (IOException e) {
log.error("Unable to read response body", e);
}
}
} catch (IOException e) {
log.error("Unable to perform transition <{}> on <{}>", transitionInput, issue);
}
return false;
}
public Response> serverInfo() throws IOException {
return jiraEndPoints.serverInfo().execute();
}
/**
* Extracts issues names from given {@code message}.
*
* @param message Commit message
* @return Matching issues name
*/
public List extractIssuesFromMessage(String message) {
List issues = Lists.newArrayList();
Matcher matcher = ISSUE_PATTERN.matcher(message);
while (matcher.find()) {
issues.add(matcher.group(1));
}
return issues;
}
/**
* Extracts all transitions from given {@code message}.
*
* @param message Commit message
* @return Matching [ISSUE, TRANSITION]
*/
public Map extractMatchingTransitionsFromMessage(String message) {
Map matchingTransition = Maps.newHashMap();
List issues = extractIssuesFromMessage(message);
issues.forEach(issue -> {
Optional optionalTransition = extractMatchingTransitionsFromMessage(message, issue);
if(optionalTransition.isPresent()) {
matchingTransition.put(issue, optionalTransition.get());
}
});
return matchingTransition;
}
/**
* Extracts first matching transition from given {@code message} related to the given issue.
*
* @param message Commit message
* @return Matching transition if it exists
*/
public Optional extractMatchingTransitionsFromMessage(String message, String issue) {
List transitions = jiraConfiguration.getTransitions();
for (TransitionConfiguration transition : transitions) {
for (String keyword : transition.getKeywords()) {
String regex = keyword.toLowerCase() + " #" + issue.toLowerCase();
Matcher matcher = Pattern.compile(regex).matcher(message.toLowerCase());
if(matcher.find()) {
return Optional.of(transition.getName());
}
}
}
return Optional.empty();
}
public boolean performTransition(String message, String issue, String comment) {
Optional optionalTransitionName = extractMatchingTransitionsFromMessage(message, issue);
if(optionalTransitionName.isPresent()) {
String transitionName = optionalTransitionName.get();
Optional optionalTransition = getTransition(issue, transitionName);
if(optionalTransition.isPresent()) {
log.info("Performing transition <{}> for issue <{}>", transitionName, issue);
TransitionInput.CommentWrapper commentWrapper =
new TransitionInput.CommentWrapper(new Comment(comment.replace(TRANSITION_HOLDER, transitionName)));
final TransitionInput transitionInput = new TransitionInput(
new TransitionInput.Update(ImmutableList.of(commentWrapper)),
optionalTransition.get()
);
return transitionOnIssue(issue, transitionInput);
} else {
log.warn("Transaction <{}> does not exists, issue <{}> can not be edited",
transitionName,
issue);
}
}
return false;
}
public boolean isExistingIssue(String issue) {
try {
return (getIssue(issue).code() == 200);
} catch (Exception e) {
log.error("Unable to get issue <{}>", issue, e);
return false;
}
}
public Optional getTransition(String issue, String name) {
return getTransitionsOfIssue(issue)
.getTransitions()
.stream()
.filter(transition -> transition.getName().equalsIgnoreCase(name))
.findFirst();
}
public boolean isExistingTransition(String issue, String name) {
return getTransition(issue, name).isPresent();
}
public boolean isIssueAlreadyCommented(String issue, String commitId) {
try {
List comments = getCommentsOfIssue(issue).body().getComments();
return comments.stream().anyMatch(comment -> comment.getBody().contains(commitId));
} catch (IOException e) {
return true;
}
}
}