Skip to content

Commit f83f7cf

Browse files
committed
Added support for issue links (#419).
1 parent ec54b2a commit f83f7cf

File tree

3 files changed

+129
-6
lines changed

3 files changed

+129
-6
lines changed

src/main/java/org/gitlab4j/api/IssuesApi.java

Lines changed: 107 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,15 @@
3535
import org.gitlab4j.api.models.Duration;
3636
import org.gitlab4j.api.models.Issue;
3737
import org.gitlab4j.api.models.IssueFilter;
38+
import org.gitlab4j.api.models.IssueLink;
3839
import org.gitlab4j.api.models.MergeRequest;
3940
import org.gitlab4j.api.models.TimeStats;
4041
import org.gitlab4j.api.utils.DurationUtils;
4142

4243
/**
4344
* This class provides an entry point to all the GitLab API Issue calls.
45+
* @see <a href="https://docs.gitlab.com/ce/api/issues.html">Issues API at GitLab</a>
46+
* @see <a href="https://docs.gitlab.com/ce/api/issue_links.html">Issue Links API at GitLab</a>
4447
*/
4548
public class IssuesApi extends AbstractApi implements Constants {
4649

@@ -81,7 +84,7 @@ public List<Issue> getIssues(int page, int perPage) throws GitLabApiException {
8184
* <pre><code>GitLab Endpoint: GET /issues</code></pre>
8285
*r
8386
* @param itemsPerPage the number of issues per page
84-
* @return the list of issues in the specified range
87+
* @return the Pager of issues in the specified range
8588
* @throws GitLabApiException if any exception occurs
8689
*/
8790
public Pager<Issue> getIssues(int itemsPerPage) throws GitLabApiException {
@@ -101,7 +104,7 @@ public Stream<Issue> getIssuesStream() throws GitLabApiException {
101104
}
102105

103106
/**
104-
* Get a list of project's issues. Only returns the first page
107+
* Get a list of project's issues.
105108
*
106109
* <pre><code>GitLab Endpoint: GET /projects/:id/issues</code></pre>
107110
*
@@ -136,7 +139,7 @@ public List<Issue> getIssues(Object projectIdOrPath, int page, int perPage) thro
136139
*
137140
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
138141
* @param itemsPerPage the number of issues per page
139-
* @return the list of issues in the specified range
142+
* @return the Pager of issues in the specified range
140143
* @throws GitLabApiException if any exception occurs
141144
*/
142145
public Pager<Issue> getIssues(Object projectIdOrPath, int itemsPerPage) throws GitLabApiException {
@@ -196,7 +199,7 @@ public List<Issue> getIssues(Object projectIdOrPath, IssueFilter filter, int pag
196199
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
197200
* @param filter {@link IssueFilter} a IssueFilter instance with the filter settings.
198201
* @param itemsPerPage the number of Project instances that will be fetched per page.
199-
* @return the list of issues in the specified range.
202+
* @return the Pager of issues in the specified range.
200203
* @throws GitLabApiException if any exception occurs
201204
*/
202205
public Pager<Issue> getIssues(Object projectIdOrPath, IssueFilter filter, int itemsPerPage) throws GitLabApiException {
@@ -258,7 +261,7 @@ public List<Issue> getIssues(IssueFilter filter, int page, int perPage) throws G
258261
*
259262
* @param filter {@link IssueFilter} a IssueFilter instance with the filter settings.
260263
* @param itemsPerPage the number of Project instances that will be fetched per page.
261-
* @return the list of issues in the specified range.
264+
* @return the Pager of issues in the specified range.
262265
* @throws GitLabApiException if any exception occurs
263266
*/
264267
public Pager<Issue> getIssues(IssueFilter filter, int itemsPerPage) throws GitLabApiException {
@@ -273,7 +276,7 @@ public Pager<Issue> getIssues(IssueFilter filter, int itemsPerPage) throws GitLa
273276
* <pre><code>GitLab Endpoint: GET /issues</code></pre>
274277
*
275278
* @param filter {@link IssueFilter} a IssueFilter instance with the filter settings
276-
* @return the list of issues in the specified range.
279+
* @return the Stream of issues in the specified range.
277280
* @throws GitLabApiException if any exception occurs
278281
*/
279282
public Stream<Issue> getIssuesStream(IssueFilter filter) throws GitLabApiException {
@@ -698,4 +701,102 @@ public Pager<MergeRequest> getClosedByMergeRequests(Object projectIdOrPath, Inte
698701
public Stream<MergeRequest> getClosedByMergeRequestsStream(Object projectIdOrPath, Integer issueIid) throws GitLabApiException {
699702
return (getClosedByMergeRequests(projectIdOrPath, issueIid, getDefaultPerPage()).stream());
700703
}
704+
705+
/**
706+
* Get a list of related issues of a given issue, sorted by the relationship creation datetime (ascending).
707+
* Issues will be filtered according to the user authorizations.
708+
*
709+
* <p>NOTE: Only available in GitLab Starter, GitLab Bronze, and higher tiers.</p>
710+
*
711+
* <pre><code>GitLab Endpoint: GET /projects/:id/issues/:issue_iid/links</code></pre>
712+
*
713+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
714+
* @param issueIid the internal ID of a project's issue
715+
* @return a list of related issues of a given issue, sorted by the relationship creation datetime (ascending)
716+
* @throws GitLabApiException if any exception occurs
717+
*/
718+
public List<Issue> getIssueLinks(Object projectIdOrPath, Integer issueIid) throws GitLabApiException {
719+
return (getIssueLinks(projectIdOrPath, issueIid, getDefaultPerPage()).all());
720+
}
721+
722+
/**
723+
* Get a Pager of related issues of a given issue, sorted by the relationship creation datetime (ascending).
724+
* Issues will be filtered according to the user authorizations.
725+
*
726+
* <p>NOTE: Only available in GitLab Starter, GitLab Bronze, and higher tiers.</p>
727+
*
728+
* <pre><code>GitLab Endpoint: GET /projects/:id/issues/:issue_iid/links</code></pre>
729+
*
730+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
731+
* @param issueIid the internal ID of a project's issue
732+
* @param itemsPerPage the number of issues per page
733+
* @return a Pager of related issues of a given issue, sorted by the relationship creation datetime (ascending)
734+
* @throws GitLabApiException if any exception occurs
735+
*/
736+
public Pager<Issue> getIssueLinks(Object projectIdOrPath, Integer issueIid, int itemsPerPage) throws GitLabApiException {
737+
return (new Pager<Issue>(this, Issue.class, itemsPerPage, null,
738+
"projects", getProjectIdOrPath(projectIdOrPath), "issues", issueIid, "links"));
739+
}
740+
741+
/**
742+
* Get a Stream of related issues of a given issue, sorted by the relationship creation datetime (ascending).
743+
* Issues will be filtered according to the user authorizations.
744+
*
745+
* <p>NOTE: Only available in GitLab Starter, GitLab Bronze, and higher tiers.</p>
746+
*
747+
* <pre><code>GitLab Endpoint: GET /projects/:id/issues/:issue_iid/links</code></pre>
748+
*
749+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
750+
* @param issueIid the internal ID of a project's issue
751+
* @return a Stream of related issues of a given issue, sorted by the relationship creation datetime (ascending)
752+
* @throws GitLabApiException if any exception occurs
753+
*/
754+
public Stream<Issue> getIssueLinksStream(Object projectIdOrPath, Integer issueIid) throws GitLabApiException {
755+
return (getIssueLinks(projectIdOrPath, issueIid, getDefaultPerPage()).stream());
756+
}
757+
758+
/**
759+
* Creates a two-way relation between two issues. User must be allowed to update both issues in order to succeed.
760+
*
761+
* <p>NOTE: Only available in GitLab Starter, GitLab Bronze, and higher tiers.</p>
762+
*
763+
* <pre><code>GitLab Endpoint: POST /projects/:id/issues/:issue_iid/links</code></pre>
764+
*
765+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
766+
* @param issueIid the internal ID of a project's issue
767+
* @param targetProjectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance of the target project
768+
* @param targetIssueIid the internal ID of a target project’s issue
769+
* @return an instance of IssueLink holding the link relationship
770+
* @throws GitLabApiException if any exception occurs
771+
*/
772+
public IssueLink createIssueLink(Object projectIdOrPath, Integer issueIid,
773+
Object targetProjectIdOrPath, Integer targetIssueIid) throws GitLabApiException {
774+
775+
GitLabApiForm formData = new GitLabApiForm()
776+
.withParam("target_project_id", getProjectIdOrPath(targetProjectIdOrPath), true)
777+
.withParam("target_issue_iid", targetIssueIid, true);
778+
779+
Response response = post(Response.Status.OK, formData.asMap(),
780+
"projects", getProjectIdOrPath(projectIdOrPath), "issues", issueIid, "links");
781+
return (response.readEntity(IssueLink.class));
782+
}
783+
784+
/**
785+
* Deletes an issue link, thus removes the two-way relationship.
786+
*
787+
* <p>NOTE: Only available in GitLab Starter, GitLab Bronze, and higher tiers.</p>
788+
*
789+
* <pre><code>GitLab Endpoint: POST /projects/:id/issues/:issue_iid/links/:issue_link_id</code></pre>
790+
*
791+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
792+
* @param issueIid the internal ID of a project's issue, required
793+
* @param issueLinkId the ID of an issue relationship, required
794+
* @return an instance of IssueLink holding the deleted link relationship
795+
* @throws GitLabApiException if any exception occurs
796+
*/
797+
public IssueLink deleteIssueLink(Object projectIdOrPath, Integer issueIid, Integer issueLinkId) throws GitLabApiException {
798+
Response response = delete(Response.Status.OK, null,
799+
"projects", getProjectIdOrPath(projectIdOrPath), "issues", issueIid, "links", issueLinkId);
800+
return (response.readEntity(IssueLink.class));
801+
}
701802
}

src/main/java/org/gitlab4j/api/models/Issue.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class Issue {
2121
private Date dueDate;
2222
private Integer id;
2323
private Integer iid;
24+
private Integer issueLinkId;
2425
private List<String> labels;
2526
private Milestone milestone;
2627
private Integer projectId;
@@ -105,6 +106,14 @@ public void setIid(Integer iid) {
105106
this.iid = iid;
106107
}
107108

109+
public Integer getIssueLinkId() {
110+
return issueLinkId;
111+
}
112+
113+
public void setIssueLinkId(Integer issueLinkId) {
114+
this.issueLinkId = issueLinkId;
115+
}
116+
108117
public List<String> getLabels() {
109118
return labels;
110119
}

src/test/java/org/gitlab4j/api/TestGitLabApiBeans.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.gitlab4j.api.models.ImpersonationToken;
5959
import org.gitlab4j.api.models.ImportStatus;
6060
import org.gitlab4j.api.models.Issue;
61+
import org.gitlab4j.api.models.IssueLink;
6162
import org.gitlab4j.api.models.Job;
6263
import org.gitlab4j.api.models.Key;
6364
import org.gitlab4j.api.models.Label;
@@ -231,6 +232,18 @@ public void testIssue() throws Exception {
231232
assertTrue(compareJson(issue, "issue.json"));
232233
}
233234

235+
@Test
236+
public void testIssueLink() throws Exception {
237+
IssueLink issueLink = unmarshalResource(IssueLink.class, "issue-link.json");
238+
assertTrue(compareJson(issueLink, "issue-link.json"));
239+
}
240+
241+
@Test
242+
public void testLinkedIssues() throws Exception {
243+
List<Issue> linkedIssues = unmarshalResourceList(Issue.class, "linked-issues.json");
244+
assertTrue(compareJson(linkedIssues, "linked-issues.json"));
245+
}
246+
234247
@Test
235248
public void testCommitDiscussions() throws Exception {
236249
List<Discussion> discussions = unmarshalResourceList(Discussion.class, "commit-discussions.json");

0 commit comments

Comments
 (0)