Skip to content

Commit bb4d441

Browse files
authored
Merge branch 'master' into add-create-repo-with-template-support
2 parents ac470dd + a8ef0cd commit bb4d441

File tree

67 files changed

+4873
-27
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+4873
-27
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
<properties>
3535
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
3636
<spotbugs-maven-plugin.version>4.0.4</spotbugs-maven-plugin.version>
37-
<spotbugs.version>4.0.6</spotbugs.version>
37+
<spotbugs.version>4.1.1</spotbugs.version>
3838
<spotbugs-maven-plugin.failOnError>true</spotbugs-maven-plugin.failOnError>
3939
<hamcrest.version>2.2</hamcrest.version>
4040
<okhttp3.version>4.4.1</okhttp3.version>
@@ -519,7 +519,7 @@
519519
<dependency>
520520
<groupId>org.mockito</groupId>
521521
<artifactId>mockito-core</artifactId>
522-
<version>3.4.4</version>
522+
<version>3.4.6</version>
523523
<scope>test</scope>
524524
</dependency>
525525
<dependency>

src/main/java/org/kohsuke/github/GHBranch.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import java.util.Collection;
1010
import java.util.Objects;
1111

12+
import javax.annotation.CheckForNull;
13+
1214
/**
1315
* A branch in a repository.
1416
*
@@ -165,6 +167,59 @@ public void enableProtection(EnforcementLevel level, Collection<String> contexts
165167
}
166168
}
167169

170+
/**
171+
* Merge a branch into this branch.
172+
*
173+
* @param headBranch
174+
* the branch whose head will be merged
175+
*
176+
* @param commitMessage
177+
* the commit message
178+
*
179+
* @return the merge {@link GHCommit} created, or {@code null} if the base already contains the head (nothing to
180+
* merge).
181+
*
182+
* @throws IOException
183+
* if merging fails
184+
*/
185+
@CheckForNull
186+
public GHCommit merge(GHBranch headBranch, String commitMessage) throws IOException {
187+
return merge(headBranch.getName(), commitMessage);
188+
}
189+
190+
/**
191+
* Merge a ref into this branch.
192+
*
193+
* @param head
194+
* the ref name that will be merged into this branch. Follows the usual ref naming rules, could be a
195+
* branch name, tag, or commit sha.
196+
*
197+
* @param commitMessage
198+
* the commit message
199+
*
200+
* @return the merge {@link GHCommit} created, or {@code null} if the base already contains the head (nothing to
201+
* merge).
202+
*
203+
* @throws IOException
204+
* if merging fails
205+
*/
206+
@CheckForNull
207+
public GHCommit merge(String head, String commitMessage) throws IOException {
208+
GHCommit result = root.createRequest()
209+
.withUrlPath(owner.getApiTailUrl("merges"))
210+
.method("POST")
211+
.with("commit_message", commitMessage)
212+
.with("base", this.name)
213+
.with("head", head)
214+
.fetch(GHCommit.class);
215+
216+
if (result != null) {
217+
result.wrapUp(owner);
218+
}
219+
220+
return result;
221+
}
222+
168223
String getApiRoute() {
169224
return owner.getApiTailUrl("/branches/" + name);
170225
}

src/main/java/org/kohsuke/github/GHCheckRun.java

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package org.kohsuke.github;
22

3+
import com.fasterxml.jackson.annotation.JsonProperty;
34
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
45

56
import java.io.IOException;
67
import java.net.URL;
8+
import java.util.Arrays;
9+
import java.util.Collections;
710
import java.util.Date;
11+
import java.util.List;
812

913
/**
1014
* Represents a check run.
@@ -14,6 +18,8 @@
1418
@SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD" },
1519
justification = "JSON API")
1620
public class GHCheckRun extends GHObject {
21+
22+
@JsonProperty("repository")
1723
GHRepository owner;
1824
GitHub root;
1925

@@ -34,15 +40,32 @@ public class GHCheckRun extends GHObject {
3440

3541
GHCheckRun wrap(GHRepository owner) {
3642
this.owner = owner;
37-
this.root = owner.root;
43+
wrap(owner.root);
3844
return this;
3945
}
4046

4147
GHCheckRun wrap(GitHub root) {
4248
this.root = root;
4349
if (owner != null) {
4450
owner.wrap(root);
51+
if (pullRequests != null && pullRequests.length != 0) {
52+
for (GHPullRequest singlePull : pullRequests) {
53+
singlePull.wrap(owner);
54+
}
55+
}
56+
57+
}
58+
if (checkSuite != null) {
59+
if (owner != null) {
60+
checkSuite.wrap(owner);
61+
} else {
62+
checkSuite.wrap(root);
63+
}
4564
}
65+
if (app != null) {
66+
app.wrapUp(root);
67+
}
68+
4669
return this;
4770
}
4871

@@ -105,15 +128,22 @@ public String getHeadSha() {
105128
/**
106129
* Gets the pull requests participated in this check run.
107130
*
108-
* @return Pull requests of this check run
131+
* Note this field is only populated for events. When getting a {@link GHCheckRun} outside of an event, this is
132+
* always empty.
133+
*
134+
* @return the list of {@link GHPullRequest}s for this check run. Only populated for events.
135+
* @throws IOException
136+
* the io exception
109137
*/
110-
GHPullRequest[] getPullRequests() throws IOException {
138+
public List<GHPullRequest> getPullRequests() throws IOException {
111139
if (pullRequests != null && pullRequests.length != 0) {
112140
for (GHPullRequest singlePull : pullRequests) {
113-
singlePull.refresh();
141+
// Only refresh if we haven't do so before
142+
singlePull.refresh(singlePull.getTitle());
114143
}
144+
return Collections.unmodifiableList(Arrays.asList(pullRequests));
115145
}
116-
return pullRequests;
146+
return Collections.emptyList();
117147
}
118148

119149
/**

src/main/java/org/kohsuke/github/GHCheckSuite.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package org.kohsuke.github;
22

3+
import com.fasterxml.jackson.annotation.JsonProperty;
34
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
45

56
import java.io.IOException;
67
import java.net.URL;
8+
import java.util.Arrays;
9+
import java.util.Collections;
710
import java.util.Date;
11+
import java.util.List;
812

913
/**
1014
* Represents a check suite.
@@ -14,6 +18,8 @@
1418
@SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD" },
1519
justification = "JSON API")
1620
public class GHCheckSuite extends GHObject {
21+
22+
@JsonProperty("repository")
1723
GHRepository owner;
1824
GitHub root;
1925

@@ -32,14 +38,22 @@ public class GHCheckSuite extends GHObject {
3238

3339
GHCheckSuite wrap(GHRepository owner) {
3440
this.owner = owner;
35-
this.root = owner.root;
41+
this.wrap(owner.root);
3642
return this;
3743
}
3844

3945
GHCheckSuite wrap(GitHub root) {
4046
this.root = root;
4147
if (owner != null) {
4248
owner.wrap(root);
49+
if (pullRequests != null && pullRequests.length != 0) {
50+
for (GHPullRequest singlePull : pullRequests) {
51+
singlePull.wrap(owner);
52+
}
53+
}
54+
}
55+
if (app != null) {
56+
app.wrapUp(root);
4357
}
4458
return this;
4559
}
@@ -153,15 +167,22 @@ public GHApp getApp() {
153167
/**
154168
* Gets the pull requests participated in this check suite.
155169
*
156-
* @return Pull requests
170+
* Note this field is only populated for events. When getting a {@link GHCheckSuite} outside of an event, this is
171+
* always empty.
172+
*
173+
* @return the list of {@link GHPullRequest}s for this check suite. Only populated for events.
174+
* @throws IOException
175+
* the io exception
157176
*/
158-
GHPullRequest[] getPullRequests() throws IOException {
177+
public List<GHPullRequest> getPullRequests() throws IOException {
159178
if (pullRequests != null && pullRequests.length != 0) {
160179
for (GHPullRequest singlePull : pullRequests) {
161-
singlePull.refresh();
180+
// Only refresh if we haven't do so before
181+
singlePull.refresh(singlePull.getTitle());
162182
}
183+
return Collections.unmodifiableList(Arrays.asList(pullRequests));
163184
}
164-
return pullRequests;
185+
return Collections.emptyList();
165186
}
166187

167188
/**

src/main/java/org/kohsuke/github/GHEvent.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public enum GHEvent {
6363
TEAM_ADD,
6464
WATCH,
6565
WORKFLOW_DISPATCH,
66+
WORKFLOW_RUN,
6667

6768
/**
6869
* Special event type that means "every possible event"

src/main/java/org/kohsuke/github/GHIssue.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ private void editNullable(String key, Object value) throws IOException {
239239
}
240240

241241
private void editIssue(String key, Object value) throws IOException {
242-
root.createRequest().with(key, value).method("PATCH").withUrlPath(getIssuesApiRoute()).send();
242+
root.createRequest().withNullable(key, value).method("PATCH").withUrlPath(getIssuesApiRoute()).send();
243243
}
244244

245245
/**
@@ -296,9 +296,9 @@ public void setBody(String body) throws IOException {
296296
*/
297297
public void setMilestone(GHMilestone milestone) throws IOException {
298298
if (milestone == null) {
299-
editNullable("milestone", null);
299+
editIssue("milestone", null);
300300
} else {
301-
edit("milestone", milestone.getNumber());
301+
editIssue("milestone", milestone.getNumber());
302302
}
303303
}
304304

src/main/java/org/kohsuke/github/GHOrganization.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ public GHProject createProject(String name, String body) throws IOException {
465465
* The enum Permission.
466466
*/
467467
public enum Permission {
468-
ADMIN, PUSH, PULL
468+
ADMIN, MAINTAIN, PUSH, TRIAGE, PULL
469469
}
470470

471471
/**

src/main/java/org/kohsuke/github/GitHub.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ public PagedIterable<GHOrganization> listOrganizations(final String since) {
532532
}
533533

534534
/**
535-
* Gets the repository object from 'user/reponame' string that GitHub calls as "repository name"
535+
* Gets the repository object from 'owner/repo' string that GitHub calls as "repository name"
536536
*
537537
* @param name
538538
* the name
@@ -543,6 +543,9 @@ public PagedIterable<GHOrganization> listOrganizations(final String since) {
543543
*/
544544
public GHRepository getRepository(String name) throws IOException {
545545
String[] tokens = name.split("/");
546+
if (tokens.length < 2) {
547+
throw new IllegalArgumentException("Repository name must be in format owner/repo");
548+
}
546549
return createRequest().withUrlPath("/repos/" + tokens[0] + '/' + tokens[1])
547550
.fetch(GHRepository.class)
548551
.wrap(this);

src/main/java/org/kohsuke/github/GitHubResponse.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,14 @@ class GitHubResponse<T> {
7878
@CheckForNull
7979
static <T> T parseBody(ResponseInfo responseInfo, Class<T> type) throws IOException {
8080

81-
if (responseInfo.statusCode() == HttpURLConnection.HTTP_NO_CONTENT && type != null && type.isArray()) {
82-
// no content
83-
return type.cast(Array.newInstance(type.getComponentType(), 0));
81+
if (responseInfo.statusCode() == HttpURLConnection.HTTP_NO_CONTENT) {
82+
if (type != null && type.isArray()) {
83+
// no content for array should be empty array
84+
return type.cast(Array.newInstance(type.getComponentType(), 0));
85+
} else {
86+
// no content for object should be null
87+
return null;
88+
}
8489
}
8590

8691
String data = responseInfo.getBodyAsString();
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package org.kohsuke.github;
2+
3+
import org.junit.Test;
4+
5+
import java.io.IOException;
6+
7+
import static org.hamcrest.Matchers.*;
8+
9+
public class GHBranchTest extends AbstractGitHubWireMockTest {
10+
private static final String BRANCH_1 = "testBranch1";
11+
private static final String BRANCH_2 = "testBranch2";
12+
13+
private GHRepository repository;
14+
15+
@Test
16+
public void testMergeBranch() throws Exception {
17+
repository = getTempRepository();
18+
19+
String masterHead = repository.getRef("heads/master").getObject().getSha();
20+
createRefAndPostContent(BRANCH_1, masterHead);
21+
createRefAndPostContent(BRANCH_2, masterHead);
22+
23+
GHBranch otherBranch = repository.getBranch(BRANCH_2);
24+
String commitMessage = "merging " + BRANCH_2;
25+
GHCommit mergeCommit = repository.getBranch(BRANCH_1).merge(otherBranch, commitMessage);
26+
assertThat(mergeCommit, notNullValue());
27+
assertThat(mergeCommit.getCommitShortInfo().getMessage(), equalTo(commitMessage));
28+
29+
// Merging commit sha should work
30+
commitMessage = "merging from " + mergeCommit.getSHA1();
31+
GHBranch master = repository.getBranch("master");
32+
mergeCommit = master.merge(mergeCommit.getSHA1(), commitMessage);
33+
34+
assertThat(mergeCommit, notNullValue());
35+
assertThat(mergeCommit.getCommitShortInfo().getMessage(), equalTo(commitMessage));
36+
37+
mergeCommit = master.merge(mergeCommit.getSHA1(), commitMessage);
38+
// Should be null since all changes already merged
39+
assertThat(mergeCommit, nullValue());
40+
}
41+
42+
private void createRefAndPostContent(String branchName, String sha) throws IOException {
43+
String refName = "refs/heads/" + branchName;
44+
repository.createRef(refName, sha);
45+
repository.createContent().content(branchName).message(branchName).path(branchName).branch(branchName).commit();
46+
}
47+
}

0 commit comments

Comments
 (0)