diff --git a/README.md b/README.md
index 8a2064f1..22aa5568 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ The changelog can:
- Be stored to file, like `CHANGELOG.md`. There are some templates used for testing available [here](/src/test/resources/templatetest).
- Or, just rendered to a `String`.
-It can integrate with Jira and/or GitHub to retrieve the title of issues.
+It can integrate with Jira, Redmine, GitLab and/or GitHub to retrieve the title of issues.
## Usage
diff --git a/src/main/java/se/bjurr/gitchangelog/api/GitChangelogApi.java b/src/main/java/se/bjurr/gitchangelog/api/GitChangelogApi.java
index 15fe578d..f01a8eb2 100644
--- a/src/main/java/se/bjurr/gitchangelog/api/GitChangelogApi.java
+++ b/src/main/java/se/bjurr/gitchangelog/api/GitChangelogApi.java
@@ -465,6 +465,42 @@ public GitChangelogApi withJiraUsername(final String string) {
return this;
}
+ /**
+ * Pattern to recognize Redmine:s. #([0-9]+)
+ */
+ public GitChangelogApi withRedmineIssuePattern(final String redmineIssuePattern) {
+ this.settings.setRedmineIssuePattern(redmineIssuePattern);
+ return this;
+ }
+
+ /** Authenticate to Redmine. */
+ public GitChangelogApi withRedminePassword(final String string) {
+ this.settings.setRedminePassword(string);
+ return this;
+ }
+
+ /** Authenticate to Redmine with API_KEY */
+ public GitChangelogApi withRedmineToken(final String string) {
+ this.settings.setRedmineToken(string);
+ return this;
+ }
+
+ /**
+ * URL pointing at your Redmine server. When configured, the {@link Issue#getTitle()} will be
+ * populated with title from Redmine.
+ * https://redmineserver/
+ */
+ public GitChangelogApi withRedmineServer(final String redmineServer) {
+ this.settings.setRedmineServer(redmineServer);
+ return this;
+ }
+
+ /** Authenticate to Redmine. */
+ public GitChangelogApi withRedmineUsername(final String string) {
+ this.settings.setRedmineUsername(string);
+ return this;
+ }
+
/**
* This is a "virtual issue" that is added to {@link Changelog#getIssues()}. It contains all
* commits that has no issue in the commit comment. This could be used as a "wall of shame"
diff --git a/src/main/java/se/bjurr/gitchangelog/api/GitChangelogApiConstants.java b/src/main/java/se/bjurr/gitchangelog/api/GitChangelogApiConstants.java
index 58e0a9fe..5adc8cf0 100644
--- a/src/main/java/se/bjurr/gitchangelog/api/GitChangelogApiConstants.java
+++ b/src/main/java/se/bjurr/gitchangelog/api/GitChangelogApiConstants.java
@@ -14,6 +14,7 @@ public final class GitChangelogApiConstants {
public static final String DEFAULT_GITHUB_ISSUE_PATTERN = "#([0-9]+)";
public static final String DEFAULT_GITLAB_ISSUE_PATTERN = "#([0-9]+)";
public static final String DEFAULT_JIRA_ISSUE_PATTEN = "\\b[a-zA-Z]([a-zA-Z]+)-([0-9]+)\\b";
+ public static final String DEFAULT_REDMINE_ISSUE_PATTEN = "#([0-9]+)";
public static final String DEFAULT_MINOR_PATTERN = "^[Ff]eat.*";
public static final String DEFAULT_PATCH_PATTERN = null;
diff --git a/src/main/java/se/bjurr/gitchangelog/api/model/Issue.java b/src/main/java/se/bjurr/gitchangelog/api/model/Issue.java
index 9b5d1eaa..22555459 100644
--- a/src/main/java/se/bjurr/gitchangelog/api/model/Issue.java
+++ b/src/main/java/se/bjurr/gitchangelog/api/model/Issue.java
@@ -4,6 +4,7 @@
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.GITHUB;
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.GITLAB;
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.JIRA;
+import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.REDMINE;
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.NOISSUE;
import static se.bjurr.gitchangelog.internal.util.Preconditions.checkNotNull;
import static se.bjurr.gitchangelog.internal.util.Preconditions.checkState;
@@ -95,6 +96,10 @@ public boolean isJira() {
return this.issueType == JIRA;
}
+ public boolean isRedmine() {
+ return this.issueType == REDMINE;
+ }
+
public boolean isGitHub() {
return this.issueType == GITHUB;
}
diff --git a/src/main/java/se/bjurr/gitchangelog/api/model/IssueType.java b/src/main/java/se/bjurr/gitchangelog/api/model/IssueType.java
index cfe5ca8e..42668182 100644
--- a/src/main/java/se/bjurr/gitchangelog/api/model/IssueType.java
+++ b/src/main/java/se/bjurr/gitchangelog/api/model/IssueType.java
@@ -4,6 +4,7 @@
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.GITHUB;
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.GITLAB;
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.JIRA;
+import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.REDMINE;
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.NOISSUE;
import static se.bjurr.gitchangelog.internal.util.Preconditions.checkNotNull;
import static se.bjurr.gitchangelog.internal.util.Preconditions.checkState;
@@ -34,6 +35,10 @@ public boolean isJira() {
return this.type == JIRA;
}
+ public boolean isRedmine() {
+ return this.type == REDMINE;
+ }
+
public boolean isGitHub() {
return this.type == GITHUB;
}
diff --git a/src/main/java/se/bjurr/gitchangelog/internal/integrations/redmine/DefaultRedmineClient.java b/src/main/java/se/bjurr/gitchangelog/internal/integrations/redmine/DefaultRedmineClient.java
new file mode 100644
index 00000000..97e79a61
--- /dev/null
+++ b/src/main/java/se/bjurr/gitchangelog/internal/integrations/redmine/DefaultRedmineClient.java
@@ -0,0 +1,59 @@
+package se.bjurr.gitchangelog.internal.integrations.redmine;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Base64;
+import java.util.Map;
+import java.util.Optional;
+import se.bjurr.gitchangelog.api.exceptions.GitChangelogIntegrationException;
+import se.bjurr.gitchangelog.internal.integrations.rest.RestClient;
+
+public class DefaultRedmineClient extends RedmineClient {
+
+ private RestClient client;
+
+ public DefaultRedmineClient(final String api) {
+ super(api);
+ this.client = new RestClient();
+ }
+
+ @Override
+ public RedmineClient withBasicCredentials(final String username, final String password) {
+ this.client = this.client.withBasicAuthCredentials(username, password);
+ return this;
+ }
+
+ @Override
+ public RedmineClient withTokenCredentials(final String token) {
+ String authToken;
+ try {
+ authToken = Base64.getEncoder().encodeToString((token + ":changelog" ).getBytes("UTF-8"));
+ } catch (final UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ this.client = this.client.withTokenAuthCredentials(authToken);
+ return this;
+ }
+
+ @Override
+ public RedmineClient withHeaders(final Map headers) {
+ this.client = this.client.withHeaders(headers);
+ return this;
+ }
+
+ @Override
+ public Optional getIssue(final String issue) throws GitChangelogIntegrationException {
+ final String endpoint = this.getEndpoint(issue);
+ final Optional json = this.client.get(endpoint);
+ if (json.isPresent()) {
+ final String jsonString = json.get();
+ try {
+ final RedmineIssue redmineIssue = this.toRedmineIssue(issue, jsonString);
+ return Optional.of(redmineIssue);
+ } catch (final Exception e) {
+ throw new GitChangelogIntegrationException("Unable to parse:\n" + jsonString, e);
+ }
+ }
+ return Optional.empty();
+ }
+
+}
diff --git a/src/main/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineClient.java b/src/main/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineClient.java
new file mode 100644
index 00000000..ee773440
--- /dev/null
+++ b/src/main/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineClient.java
@@ -0,0 +1,53 @@
+package se.bjurr.gitchangelog.internal.integrations.redmine;
+
+import static com.jayway.jsonpath.JsonPath.read;
+
+import java.util.Map;
+import java.util.Optional;
+
+import se.bjurr.gitchangelog.api.exceptions.GitChangelogIntegrationException;
+
+public abstract class RedmineClient {
+ private final String api;
+
+ public RedmineClient(final String api) {
+ if (api.endsWith("/")) {
+ this.api = api.substring(0, api.length() - 1);
+ } else {
+ this.api = api;
+ }
+ }
+
+ public String getApi() {
+ return this.api;
+ }
+
+ protected String getEndpoint(final String issue) {
+ final String issueNo = getIssueNumber(issue);
+ final String endpoint = this.api + "/issues/" + issueNo + ".json";
+ return endpoint;
+ }
+
+ protected RedmineIssue toRedmineIssue(final String issue, final String json) {
+ final String issueNo = getIssueNumber(issue);
+ final String title = read(json, "$.issue.subject");
+ final String description = read(json, "$.issue.description");
+ final String type = read(json, "$.issue.tracker.name");
+ final String link = this.api + "/issues/" + issueNo;
+
+ final RedmineIssue redmineIssue = new RedmineIssue(title, description, link, issue, type);
+ return redmineIssue;
+ }
+
+ protected String getIssueNumber( String issue ){
+ return issue.startsWith("#") ? issue.substring(1) : issue;
+ }
+
+ public abstract RedmineClient withBasicCredentials(String username, String password);
+
+ public abstract RedmineClient withTokenCredentials(String token);
+
+ public abstract RedmineClient withHeaders(Map headers);
+
+ public abstract Optional getIssue(String matched) throws GitChangelogIntegrationException;
+}
diff --git a/src/main/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineClientFactory.java b/src/main/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineClientFactory.java
new file mode 100644
index 00000000..b81014cf
--- /dev/null
+++ b/src/main/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineClientFactory.java
@@ -0,0 +1,25 @@
+package se.bjurr.gitchangelog.internal.integrations.redmine;
+
+public class RedmineClientFactory {
+
+ private static RedmineClient redmineClient;
+
+ public static void reset() {
+ redmineClient = null;
+ }
+
+ /**
+ * The Bitbucket Server plugin uses this method to inject the Atlassian Client.
+ */
+ public static void setRedmineClient(final RedmineClient redmineClient) {
+ RedmineClientFactory.redmineClient = redmineClient;
+ }
+
+ public static RedmineClient createRedmineClient(final String apiUrl) {
+ if (redmineClient != null) {
+ return redmineClient;
+ }
+ return new DefaultRedmineClient(apiUrl);
+ }
+
+}
diff --git a/src/main/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineIssue.java b/src/main/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineIssue.java
new file mode 100644
index 00000000..ce3d5f2f
--- /dev/null
+++ b/src/main/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineIssue.java
@@ -0,0 +1,44 @@
+package se.bjurr.gitchangelog.internal.integrations.redmine;
+
+public class RedmineIssue {
+ private final String title;
+ private final String link;
+ private final String issue;
+ private final String issueType;
+ private final String description;
+
+
+ public RedmineIssue(String title, String description, String link, String issue, String issueType ) {
+ this.title = title;
+ this.link = link;
+ this.issue = issue;
+ this.issueType = issueType;
+ this.description = description;
+ }
+
+ public String getIssue() {
+ return issue;
+ }
+
+ public String getLink() {
+ return link;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getIssueType() {
+ return issueType;
+ }
+
+ public String getDescription() {
+
+ return description;
+ }
+
+ @Override
+ public String toString() {
+ return "RedmineIssue [title=" + title + ", link=" + link + ", issue=" + issue + ", issueType=" + issueType + "]";
+ }
+}
diff --git a/src/main/java/se/bjurr/gitchangelog/internal/issues/IssueParser.java b/src/main/java/se/bjurr/gitchangelog/internal/issues/IssueParser.java
index 423c5430..af1bd3c2 100644
--- a/src/main/java/se/bjurr/gitchangelog/internal/issues/IssueParser.java
+++ b/src/main/java/se/bjurr/gitchangelog/internal/issues/IssueParser.java
@@ -8,6 +8,7 @@
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.GITHUB;
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.GITLAB;
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.JIRA;
+import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.REDMINE;
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.NOISSUE;
import java.util.ArrayList;
@@ -26,6 +27,9 @@
import se.bjurr.gitchangelog.internal.integrations.jira.JiraClient;
import se.bjurr.gitchangelog.internal.integrations.jira.JiraClientFactory;
import se.bjurr.gitchangelog.internal.integrations.jira.JiraIssue;
+import se.bjurr.gitchangelog.internal.integrations.redmine.RedmineClient;
+import se.bjurr.gitchangelog.internal.integrations.redmine.RedmineClientFactory;
+import se.bjurr.gitchangelog.internal.integrations.redmine.RedmineIssue;
import se.bjurr.gitchangelog.internal.model.ParsedIssue;
import se.bjurr.gitchangelog.internal.settings.IssuesUtil;
import se.bjurr.gitchangelog.internal.settings.Settings;
@@ -56,8 +60,9 @@ public List parseForIssues(final boolean useIntegrationIfConfigured
final GitHubHelper gitHubHelper = useIntegrationIfConfigured ? this.createGitHubClient() : null;
final JiraClient jiraClient = useIntegrationIfConfigured ? this.createJiraClient() : null;
+ final RedmineClient redmineClient = useIntegrationIfConfigured ? this.createRedmineClient() : null;
final GitLabClient gitLabClient = useIntegrationIfConfigured ? this.createGitLabClient() : null;
-
+
final List patterns = new IssuesUtil(this.settings).getIssues();
for (final GitCommit gitCommit : this.commits) {
@@ -80,6 +85,8 @@ public List parseForIssues(final boolean useIntegrationIfConfigured
this.createParsedIssue(gitLabClient, projectName, issuePattern, matchedIssue);
} else if (issuePattern.getType() == JIRA) {
parsedIssue = this.createParsedIssue(jiraClient, issuePattern, matchedIssue);
+ } else if (issuePattern.getType() == REDMINE) {
+ parsedIssue = this.createParsedIssue(redmineClient, issuePattern, matchedIssue);
} else {
parsedIssue = this.createParsedIssue(issuePattern, issueMatcher, matchedIssue);
}
@@ -183,6 +190,23 @@ private JiraClient createJiraClient() {
return jiraClient;
}
+ private RedmineClient createRedmineClient() {
+ RedmineClient redmineClient = null;
+ if (this.settings.getRedmineServer().isPresent()) {
+ redmineClient = RedmineClientFactory.createRedmineClient(this.settings.getRedmineServer().get());
+ if (this.settings.getRedmineUsername().isPresent()) {
+ redmineClient.withBasicCredentials(
+ this.settings.getRedmineUsername().get(), this.settings.getRedminePassword().get());
+ } else if (this.settings.getRedmineToken().isPresent()) {
+ redmineClient.withTokenCredentials(this.settings.getRedmineToken().get());
+ }
+ if (this.settings.getExtendedRestHeaders() != null) {
+ redmineClient.withHeaders(this.settings.getExtendedRestHeaders());
+ }
+ }
+ return redmineClient;
+ }
+
private GitHubHelper createGitHubClient() {
GitHubHelper gitHubHelper = null;
if (this.settings.getGitHubApi().isPresent()) {
@@ -246,6 +270,38 @@ private ParsedIssue createParsedIssue(
labels);
}
+ private ParsedIssue createParsedIssue(
+ final RedmineClient redmineClient, final SettingsIssue issuePattern, final String matchedIssue) {
+ String link = "";
+ String title = "";
+ String desc = "";
+ String issueType = null;
+ List linkedIssues = null;
+ List labels = null;
+ try {
+ if (redmineClient != null && redmineClient.getIssue(matchedIssue).isPresent()) {
+ final RedmineIssue redmineIssue = redmineClient.getIssue(matchedIssue).get();
+ link = redmineIssue.getLink();
+ title = redmineIssue.getTitle();
+ issueType = redmineIssue.getIssueType();
+ desc = redmineIssue.getDescription();
+ }
+ } catch (final GitChangelogIntegrationException e) {
+ LOG.error(matchedIssue, e);
+ }
+ return new ParsedIssue( //
+ REDMINE, //
+ issuePattern.getName(), //
+ matchedIssue, //
+ desc,
+ link, //
+ title, //
+ issueType, //
+ linkedIssues,
+ labels);
+ }
+
+
private ParsedIssue createParsedIssue(
final GitHubHelper gitHubHelper,
final SettingsIssue issuePattern,
diff --git a/src/main/java/se/bjurr/gitchangelog/internal/settings/IssuesUtil.java b/src/main/java/se/bjurr/gitchangelog/internal/settings/IssuesUtil.java
index 979e38b5..e8f3fee8 100644
--- a/src/main/java/se/bjurr/gitchangelog/internal/settings/IssuesUtil.java
+++ b/src/main/java/se/bjurr/gitchangelog/internal/settings/IssuesUtil.java
@@ -3,6 +3,7 @@
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.GITHUB;
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.GITLAB;
import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.JIRA;
+import static se.bjurr.gitchangelog.internal.settings.SettingsIssueType.REDMINE;
import static se.bjurr.gitchangelog.internal.util.Preconditions.isNullOrEmpty;
import java.util.ArrayList;
@@ -18,6 +19,7 @@ public IssuesUtil(final Settings settings) {
public List getIssues() {
final List issues = new ArrayList<>(this.settings.getCustomIssues());
this.addJira(issues);
+ this.addRedmine(issues);
this.addGitHub(issues);
this.addGitLab(issues);
return issues;
@@ -62,4 +64,26 @@ private void addJira(final List issues) {
}
}
}
+
+ private void addRedmine(final List issues) {
+ if (!isNullOrEmpty(this.settings.getRedmineIssuePattern())) {
+ if (this.settings.getRedmineServer().isPresent()) {
+ issues.add(
+ new SettingsIssue(
+ REDMINE,
+ "Redmine",
+ this.settings.getRedmineIssuePattern(),
+ this.settings.getRedmineServer().orElse("") + "/issues/${PATTERN_GROUP}",
+ null));
+ } else {
+ issues.add(
+ new SettingsIssue(
+ REDMINE,
+ "Redmine",
+ this.settings.getRedmineIssuePattern(),
+ this.settings.getRedmineServer().orElse(null),
+ null));
+ }
+ }
+ }
}
diff --git a/src/main/java/se/bjurr/gitchangelog/internal/settings/Settings.java b/src/main/java/se/bjurr/gitchangelog/internal/settings/Settings.java
index 2e92480f..c6dd6693 100644
--- a/src/main/java/se/bjurr/gitchangelog/internal/settings/Settings.java
+++ b/src/main/java/se/bjurr/gitchangelog/internal/settings/Settings.java
@@ -7,6 +7,7 @@
import static se.bjurr.gitchangelog.api.GitChangelogApiConstants.DEFAULT_GITLAB_ISSUE_PATTERN;
import static se.bjurr.gitchangelog.api.GitChangelogApiConstants.DEFAULT_IGNORE_COMMITS_REGEXP;
import static se.bjurr.gitchangelog.api.GitChangelogApiConstants.DEFAULT_JIRA_ISSUE_PATTEN;
+import static se.bjurr.gitchangelog.api.GitChangelogApiConstants.DEFAULT_REDMINE_ISSUE_PATTEN;
import static se.bjurr.gitchangelog.api.GitChangelogApiConstants.DEFAULT_MINOR_PATTERN;
import static se.bjurr.gitchangelog.api.GitChangelogApiConstants.DEFAULT_NO_ISSUE_NAME;
import static se.bjurr.gitchangelog.api.GitChangelogApiConstants.DEFAULT_PATCH_PATTERN;
@@ -136,6 +137,22 @@ public class Settings implements Serializable {
private String jiraPassword;
/** Authenticate to JIRA. */
private String jiraToken;
+ /**
+ * URL pointing at your Redmine server. When configured, the {@link Issue#getTitle()} will be
+ * populated with title from Redmine.
+ * https://redmine/redmine
+ */
+ private String redmineServer;
+ /**
+ * Pattern to recognize Redmine:s. #([0-9]+)
+ */
+ private String redmineIssuePattern;
+ /** Authenticate to Redmine. */
+ private String redmineUsername;
+ /** Authenticate to Redmine. */
+ private String redminePassword;
+ /** Authenticate to Redmine whith API_KEY */
+ private String redmineToken;
/**
* URL pointing at GitHub API. When configured, the {@link Issue#getTitle()} will be populated
* with title from GitHub.
@@ -266,6 +283,14 @@ public void setJiraServer(final String jiraServer) {
this.jiraServer = jiraServer;
}
+ public void setRedmineIssuePattern(final String redmineIssuePattern) {
+ this.redmineIssuePattern = redmineIssuePattern;
+ }
+
+ public void setRedmineServer(final String redmineServer) {
+ this.redmineServer = redmineServer;
+ }
+
public void addCustomIssue(final SettingsIssue customIssue) {
if (this.customIssues == null) {
this.customIssues = new ArrayList<>();
@@ -297,6 +322,14 @@ public Optional getJiraServer() {
return ofNullable(this.jiraServer);
}
+ public String getRedmineIssuePattern() {
+ return ofNullable(this.redmineIssuePattern).orElse(DEFAULT_REDMINE_ISSUE_PATTEN);
+ }
+
+ public Optional getRedmineServer() {
+ return ofNullable(this.redmineServer);
+ }
+
public static Settings fromFile(final URL url) {
try {
return gson.fromJson(
@@ -446,6 +479,30 @@ public Optional getJiraToken() {
return ofNullable(this.jiraToken);
}
+ public Optional getRedmineUsername() {
+ return ofNullable(this.redmineUsername);
+ }
+
+ public void setRedminePassword(final String redminePassword) {
+ this.redminePassword = redminePassword;
+ }
+
+ public void setRedmineToken(final String redmineToken) {
+ this.redmineToken = redmineToken;
+ }
+
+ public void setRedmineUsername(final String redmineUsername) {
+ this.redmineUsername = redmineUsername;
+ }
+
+ public Optional getRedminePassword() {
+ return ofNullable(this.redminePassword);
+ }
+
+ public Optional getRedmineToken() {
+ return ofNullable(this.redmineToken);
+ }
+
public void setExtendedVariables(final Map extendedVariables) {
this.extendedVariables = extendedVariables;
}
diff --git a/src/main/java/se/bjurr/gitchangelog/internal/settings/SettingsIssueType.java b/src/main/java/se/bjurr/gitchangelog/internal/settings/SettingsIssueType.java
index 344319b8..a8990315 100644
--- a/src/main/java/se/bjurr/gitchangelog/internal/settings/SettingsIssueType.java
+++ b/src/main/java/se/bjurr/gitchangelog/internal/settings/SettingsIssueType.java
@@ -5,5 +5,6 @@ public enum SettingsIssueType {
CUSTOM,
JIRA,
GITHUB,
- GITLAB
+ GITLAB,
+ REDMINE
}
diff --git a/src/test/java/se/bjurr/gitchangelog/api/GitChangelogApiTest.java b/src/test/java/se/bjurr/gitchangelog/api/GitChangelogApiTest.java
index 0fa6c74a..c0c0a541 100644
--- a/src/test/java/se/bjurr/gitchangelog/api/GitChangelogApiTest.java
+++ b/src/test/java/se/bjurr/gitchangelog/api/GitChangelogApiTest.java
@@ -18,6 +18,7 @@
import se.bjurr.gitchangelog.internal.integrations.github.GitHubMockInterceptor;
import se.bjurr.gitchangelog.internal.integrations.github.GitHubServiceFactory;
import se.bjurr.gitchangelog.internal.integrations.jira.JiraClientFactory;
+import se.bjurr.gitchangelog.internal.integrations.redmine.RedmineClientFactory;
import se.bjurr.gitchangelog.internal.integrations.rest.RestClientMock;
import se.bjurr.gitchangelog.test.ApprovalsWrapper;
@@ -28,6 +29,7 @@ public class GitChangelogApiTest {
@Before
public void before() throws Exception {
JiraClientFactory.reset();
+ RedmineClientFactory.reset();
this.mockedRestClient = new RestClientMock();
this.mockedRestClient //
@@ -50,6 +52,13 @@ public void before() throws Exception {
Files.readAllBytes(
Paths.get(
TemplatesTest.class.getResource("/jira-issue-jir-5262.json").toURI())),
+ UTF_8)) //
+ .addMockedResponse(
+ "/redmine/issues/1234.json?null",
+ new String(
+ Files.readAllBytes(
+ Paths.get(
+ TemplatesTest.class.getResource("/redmine-issue-1234.json").toURI())),
UTF_8)); //
mock(this.mockedRestClient);
@@ -69,6 +78,7 @@ public void before() throws Exception {
@After
public void after() {
JiraClientFactory.reset();
+ RedmineClientFactory.reset();
GitHubServiceFactory.setInterceptor(null);
mock(null);
}
diff --git a/src/test/java/se/bjurr/gitchangelog/api/TemplatesTest.java b/src/test/java/se/bjurr/gitchangelog/api/TemplatesTest.java
index ea6e3b75..c43754d3 100644
--- a/src/test/java/se/bjurr/gitchangelog/api/TemplatesTest.java
+++ b/src/test/java/se/bjurr/gitchangelog/api/TemplatesTest.java
@@ -44,6 +44,13 @@ public void before() throws Exception {
Files.readAllBytes(
Paths.get(
TemplatesTest.class.getResource("/jira-issue-jir-5262.json").toURI())),
+ UTF_8)) //
+ .addMockedResponse(
+ "/redmine/issues/1234.json?null",
+ new String(
+ Files.readAllBytes(
+ Paths.get(
+ TemplatesTest.class.getResource("/redmine-issue-1234.json").toURI())),
UTF_8));
mock(mockedRestClient);
@@ -75,6 +82,10 @@ public void before() throws Exception {
.withJiraIssuePattern("\\b[a-zA-Z]([a-zA-Z]+)-([0-9]+)\\b") //
.withJiraUsername("user") //
.withJiraPassword("code") //
+ .withRedmineServer("https://redmineserver/redmine") //
+ .withRedmineIssuePattern("#([0-9]+)") //
+ .withRedmineUsername("user") //
+ .withRedminePassword("code") //
.withGitHubApi("https://api.github.com/repos/tomasbjerre/git-changelog-lib") //
.withGitHubIssuePattern("#([0-9]+)") //
.withCustomIssue(
diff --git a/src/test/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineClientIntegrationTest.java b/src/test/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineClientIntegrationTest.java
new file mode 100644
index 00000000..b504c979
--- /dev/null
+++ b/src/test/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineClientIntegrationTest.java
@@ -0,0 +1,48 @@
+package se.bjurr.gitchangelog.internal.integrations.redmine;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+public class RedmineClientIntegrationTest {
+
+ private static final String EXISTING_REDMINE = "X";
+ private static final String REDMINE_API_URL = "https://redmineserver/";
+ private static final String USER = "U";
+ private static final String PASSWORD = "P";
+ private static final String TOKEN = "API_KEY";
+ private static final String API_HEADER = "X-Redmine-API-Key";
+
+ //@Test
+ public void testThatIssueCanBeFound() throws Exception {
+ final RedmineClient client = new DefaultRedmineClient(REDMINE_API_URL) //
+ .withBasicCredentials(USER, PASSWORD);
+ final java.util.Optional issue = client.getIssue(EXISTING_REDMINE);
+ assertThat(issue.get().getTitle()) //
+ .isEqualTo("git-changelog redmine test");
+ }
+
+ //@Test
+ public void testThatIssueCanBeFoundWithToken() throws Exception {
+ final RedmineClient client = new DefaultRedmineClient(REDMINE_API_URL) //
+ .withTokenCredentials(TOKEN);
+ final java.util.Optional issue = client.getIssue(EXISTING_REDMINE);
+ assertThat(issue.get().getTitle()) //
+ .isEqualTo("git-changelog redmine test");
+ }
+
+ //@Test
+ public void testThatIssueCanBeFoundWithHeaders() throws Exception {
+
+ Map headers = new HashMap<>();
+ headers.put(API_HEADER, TOKEN);
+ final RedmineClient client = new DefaultRedmineClient(REDMINE_API_URL) //
+ .withHeaders(headers);
+ final java.util.Optional issue = client.getIssue(EXISTING_REDMINE);
+ assertThat(issue.get().getTitle()) //
+ .isEqualTo("git-changelog redmine test");
+ }
+}
diff --git a/src/test/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineClientTest.java b/src/test/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineClientTest.java
new file mode 100644
index 00000000..38b64d58
--- /dev/null
+++ b/src/test/java/se/bjurr/gitchangelog/internal/integrations/redmine/RedmineClientTest.java
@@ -0,0 +1,68 @@
+package se.bjurr.gitchangelog.internal.integrations.redmine;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+import se.bjurr.gitchangelog.api.exceptions.GitChangelogIntegrationException;
+
+public class RedmineClientTest {
+
+ @Test
+ public void testThatTrailingSlashIsRemoved() {
+ final RedmineClient client = this.createClient("https://server.com/redmine/");
+ assertThat(client.getApi()) //
+ .isEqualTo("https://server.com/redmine");
+ }
+
+ @Test
+ public void testThatNoTrailingSlashUrlIsUntouched() {
+ final RedmineClient client = this.createClient("https://server.com/redmine");
+ assertThat(client.getApi()) //
+ .isEqualTo("https://server.com/redmine");
+ }
+
+ @Test
+ public void testRemineMatcher() {
+
+ Pattern p = Pattern.compile("#([0-9*])");
+ final Matcher issueMatcher = p.matcher("refs #1234 ve #234 bişiler ve diğer şeyler");
+ while (issueMatcher.find()) {
+ final String matchedIssue = issueMatcher.group();
+ if (matchedIssue.isEmpty()) {
+ continue;
+ }
+ System.out.println(issueMatcher.group(1));
+ }
+
+ }
+
+ private RedmineClient createClient(final String api) {
+ return new RedmineClient(api) {
+
+ @Override
+ public RedmineClient withBasicCredentials(final String username, final String password) {
+ return null;
+ }
+
+ @Override
+ public RedmineClient withTokenCredentials(final String token) {
+ return null;
+ }
+
+ @Override
+ public RedmineClient withHeaders(final Map headers) {
+ return null;
+ }
+
+ @Override
+ public Optional getIssue(final String matched) throws GitChangelogIntegrationException {
+ return null;
+ }
+ };
+ }
+}
diff --git a/src/test/resources/redmine-issue-1234.json b/src/test/resources/redmine-issue-1234.json
new file mode 100644
index 00000000..a1edfff5
--- /dev/null
+++ b/src/test/resources/redmine-issue-1234.json
@@ -0,0 +1,44 @@
+{
+ "issue": {
+ "id": 1234,
+ "project": {
+ "id": 1,
+ "name": "Test"
+ },
+ "tracker": {
+ "id": 2,
+ "name": "Feature"
+ },
+ "status": {
+ "id": 4,
+ "name": "WIP"
+ },
+ "priority": {
+ "id": 13,
+ "name": "Medium"
+ },
+ "author": {
+ "id": 5,
+ "name": "Hakan Uygun"
+ },
+ "assigned_to": {
+ "id": 6,
+ "name": "Hakan Uygun"
+ },
+ "subject": "git-changelog-lib test",
+ "description": "git-changelog-lib redmine support test",
+ "start_date": null,
+ "due_date": null,
+ "done_ratio": 0,
+ "is_private": false,
+ "estimated_hours": null,
+ "total_estimated_hours": null,
+ "spent_hours": 0.0,
+ "total_spent_hours": 0.0,
+ "custom_fields": [
+ ],
+ "created_on": "2021-10-23T16:28:47Z",
+ "updated_on": "2021-11-07T18:27:16Z",
+ "closed_on": null
+ }
+ }
\ No newline at end of file
diff --git a/src/test/resources/settings/git-changelog-test-settings.json b/src/test/resources/settings/git-changelog-test-settings.json
index 5bec8891..ebed761f 100644
--- a/src/test/resources/settings/git-changelog-test-settings.json
+++ b/src/test/resources/settings/git-changelog-test-settings.json
@@ -19,6 +19,11 @@
"jiraUsername": "user",
"jiraPassword": "code",
+ "redmineServer": "https://redmineserver/redmine",
+ "redmineIssuePattern": "#([0-9]+)",
+ "redmineUsername": "user",
+ "redminePassword": "code",
+
"gitHubApi": "https://api.github.com/repos/tomasbjerre/git-changelog-lib",
"gitHubIssuePattern": "#([0-9]+)",
diff --git a/src/test/resources/templatetest/testIssueType.mustache b/src/test/resources/templatetest/testIssueType.mustache
index 6107bb14..a5fdd85f 100644
--- a/src/test/resources/templatetest/testIssueType.mustache
+++ b/src/test/resources/templatetest/testIssueType.mustache
@@ -7,6 +7,7 @@
isGitHub: {{isGitHub}}
isGitLab: {{isGitLab}}
isJira: {{isJira}}
+isRedmine: {{isRedmine}}
isCustom: {{isCustom}}
isNoIssue: {{isNoIssue}}