Skip to content

Commit 3d5196f

Browse files
fix: allow null app ids to provide the same behaviour as the deprecated endpoint & post-review changes
1 parent 3882581 commit 3d5196f

File tree

5 files changed

+135
-25
lines changed

5 files changed

+135
-25
lines changed

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

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

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

@@ -226,6 +227,8 @@ public boolean isEnabled() {
226227
*/
227228
public static class Check {
228229
private String context;
230+
231+
@JsonInclude(JsonInclude.Include.NON_NULL)
229232
private Integer appId;
230233

231234
/**
@@ -240,7 +243,9 @@ public Check() {
240243
* @param context
241244
* the context string of the check
242245
* @param appId
243-
* the application ID the check is supposed to come from
246+
* the application ID the check is supposed to come from. Pass "-1" to explicitly allow any app to
247+
* set the status. Pass "null" to automatically select the GitHub App that has recently provided this
248+
* check.
244249
*/
245250
public Check(String context, Integer appId) {
246251
this.context = context;

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

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.List;
1212
import java.util.Map;
1313
import java.util.Set;
14+
import java.util.stream.Collectors;
1415

1516
import static org.kohsuke.github.internal.Previews.LUKE_CAGE;
1617

@@ -50,11 +51,8 @@ public class GHBranchProtectionBuilder {
5051
* the checks
5152
* @return the gh branch protection builder
5253
*/
53-
public GHBranchProtectionBuilder addRequiredChecksWithAppIds(Collection<GHBranchProtection.Check> checks) {
54-
if (!(getStatusChecks() instanceof StatusChecksWithAppId)) {
55-
statusChecks = new StatusChecksWithAppId();
56-
}
57-
((StatusChecksWithAppId) getStatusChecks()).checks.addAll(checks);
54+
public GHBranchProtectionBuilder addRequiredStatusChecks(Collection<GHBranchProtection.Check> checks) {
55+
getStatusChecks().checks.addAll(checks);
5856
return this;
5957
}
6058

@@ -67,10 +65,9 @@ public GHBranchProtectionBuilder addRequiredChecksWithAppIds(Collection<GHBranch
6765
*/
6866
@Deprecated
6967
public GHBranchProtectionBuilder addRequiredChecks(Collection<String> checks) {
70-
if (!(getStatusChecks() instanceof StatusChecksDeprecated)) {
71-
statusChecks = new StatusChecksDeprecated();
72-
}
73-
((StatusChecksDeprecated) getStatusChecks()).contexts.addAll(checks);
68+
getStatusChecks().checks.addAll(checks.stream()
69+
.map(context -> new GHBranchProtection.Check(context, null))
70+
.collect(Collectors.toList()));
7471
return this;
7572
}
7673

@@ -94,8 +91,8 @@ public GHBranchProtectionBuilder addRequiredChecks(String... checks) {
9491
* the checks
9592
* @return the gh branch protection builder
9693
*/
97-
public GHBranchProtectionBuilder addRequiredChecksWithAppIds(GHBranchProtection.Check... checks) {
98-
addRequiredChecksWithAppIds(Arrays.asList(checks));
94+
public GHBranchProtectionBuilder addRequiredChecks(GHBranchProtection.Check... checks) {
95+
addRequiredStatusChecks(Arrays.asList(checks));
9996
return this;
10097
}
10198

@@ -564,7 +561,7 @@ private Restrictions getRestrictions() {
564561

565562
private StatusChecks getStatusChecks() {
566563
if (statusChecks == null) {
567-
statusChecks = new StatusChecksWithAppId();
564+
statusChecks = new StatusChecks();
568565
}
569566
return statusChecks;
570567
}
@@ -578,15 +575,8 @@ private static class Restrictions {
578575
private Set<String> users = new HashSet<String>();
579576
}
580577

581-
private static abstract class StatusChecks {
582-
boolean strict;
583-
}
584-
585-
private static class StatusChecksWithAppId extends StatusChecks {
578+
private static class StatusChecks {
586579
final List<GHBranchProtection.Check> checks = new ArrayList<>();
587-
}
588-
589-
private static class StatusChecksDeprecated extends StatusChecks {
590-
final List<String> contexts = new ArrayList<>();
580+
boolean strict;
591581
}
592582
}

src/test/java/org/kohsuke/github/GHBranchProtectionTest.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,18 +200,20 @@ public void testSignedCommits() throws Exception {
200200
@Test
201201
public void testChecksWithAppIds() throws Exception {
202202
GHBranchProtection protection = branch.enableProtection()
203-
.addRequiredChecksWithAppIds(new GHBranchProtection.Check("context", -1),
204-
new GHBranchProtection.Check("context2", 123))
203+
.addRequiredChecks(new GHBranchProtection.Check("context", -1),
204+
new GHBranchProtection.Check("context2", 123),
205+
new GHBranchProtection.Check("context3", null))
205206
.enable();
206207

207208
ArrayList<GHBranchProtection.Check> resultChecks = new ArrayList<>(
208209
protection.getRequiredStatusChecks().getChecks());
209210

210-
assertThat(resultChecks.size(), is(2));
211+
assertThat(resultChecks.size(), is(3));
211212
assertThat(resultChecks.get(0).getContext(), is("context"));
212213
assertThat(resultChecks.get(0).getAppId(), nullValue());
213214
assertThat(resultChecks.get(1).getContext(), is("context2"));
214215
assertThat(resultChecks.get(1).getAppId(), is(123));
216+
assertThat(resultChecks.get(2).getContext(), is("context3"));
215217
}
216218

217219
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"url": "https://api.github.com/repos/hub4j-test-org/temp-testChecksWithAppIds/branches/main/protection",
3+
"required_status_checks": {
4+
"url": "https://api.github.com/repos/hub4j-test-org/temp-testChecksWithAppIds/branches/main/protection/required_status_checks",
5+
"strict": false,
6+
"contexts": [
7+
"context",
8+
"context2",
9+
"context3"
10+
],
11+
"contexts_url": "https://api.github.com/repos/hub4j-test-org/temp-testChecksWithAppIds/branches/main/protection/required_status_checks/contexts",
12+
"checks": [
13+
{
14+
"context": "context",
15+
"app_id": null
16+
},
17+
{
18+
"context": "context2",
19+
"app_id": 123
20+
},
21+
{
22+
"context": "context3",
23+
"app_id": null
24+
}
25+
]
26+
},
27+
"required_signatures": {
28+
"url": "https://api.github.com/repos/hub4j-test-org/temp-testChecksWithAppIds/branches/main/protection/required_signatures",
29+
"enabled": false
30+
},
31+
"enforce_admins": {
32+
"url": "https://api.github.com/repos/hub4j-test-org/temp-testChecksWithAppIds/branches/main/protection/enforce_admins",
33+
"enabled": false
34+
},
35+
"required_linear_history": {
36+
"enabled": false
37+
},
38+
"allow_force_pushes": {
39+
"enabled": false
40+
},
41+
"allow_deletions": {
42+
"enabled": false
43+
},
44+
"block_creations": {
45+
"enabled": false
46+
},
47+
"required_conversation_resolution": {
48+
"enabled": false
49+
},
50+
"lock_branch": {
51+
"enabled": false
52+
},
53+
"allow_fork_syncing": {
54+
"enabled": false
55+
}
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"id": "9f6f5be6-b5c5-4840-865c-ba84ad262118",
3+
"name": "repos_hub4j-test-org_temp-testcheckswithappids_branches_main_protection",
4+
"request": {
5+
"url": "/repos/hub4j-test-org/temp-testChecksWithAppIds/branches/main/protection",
6+
"method": "PUT",
7+
"headers": {
8+
"Accept": {
9+
"equalTo": "application/vnd.github.luke-cage-preview+json"
10+
}
11+
},
12+
"bodyPatterns": [
13+
{
14+
"equalToJson": "{\"required_pull_request_reviews\":null,\"required_status_checks\":{\"checks\":[{\"context\":\"context\",\"app_id\":-1},{\"context\":\"context2\",\"app_id\":123},{\"context\":\"context3\"}],\"strict\":false},\"restrictions\":null,\"enforce_admins\":false}",
15+
"ignoreArrayOrder": true,
16+
"ignoreExtraElements": false
17+
}
18+
]
19+
},
20+
"response": {
21+
"status": 200,
22+
"bodyFileName": "6-r_h_t_branches_main_protection.json",
23+
"headers": {
24+
"Server": "GitHub.com",
25+
"Date": "Thu, 13 Jun 2024 14:46:41 GMT",
26+
"Content-Type": "application/json; charset=utf-8",
27+
"Cache-Control": "private, max-age=60, s-maxage=60",
28+
"Vary": [
29+
"Accept, Authorization, Cookie, X-GitHub-OTP",
30+
"Accept-Encoding, Accept, X-Requested-With"
31+
],
32+
"ETag": "W/\"59d4b1a76c2903c6f8950aecee97ded98e0a0704a6ec06aebd22434d63b3a19c\"",
33+
"X-OAuth-Scopes": "admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, copilot, delete:packages, delete_repo, gist, notifications, project, repo, user, workflow, write:discussion, write:packages",
34+
"X-Accepted-OAuth-Scopes": "",
35+
"github-authentication-token-expiration": "2024-06-16 12:56:36 UTC",
36+
"X-GitHub-Media-Type": "github.v3; param=luke-cage-preview; format=json",
37+
"x-github-api-version-selected": "2022-11-28",
38+
"X-RateLimit-Limit": "5000",
39+
"X-RateLimit-Remaining": "4966",
40+
"X-RateLimit-Reset": "1718293429",
41+
"X-RateLimit-Used": "34",
42+
"X-RateLimit-Resource": "core",
43+
"Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset",
44+
"Access-Control-Allow-Origin": "*",
45+
"Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
46+
"X-Frame-Options": "deny",
47+
"X-Content-Type-Options": "nosniff",
48+
"X-XSS-Protection": "0",
49+
"Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
50+
"Content-Security-Policy": "default-src 'none'",
51+
"X-GitHub-Request-Id": "C8E4:2DA98F:90511D4:9134847:666B0651"
52+
}
53+
},
54+
"uuid": "9f6f5be6-b5c5-4840-865c-ba84ad262118",
55+
"persistent": true,
56+
"insertionIndex": 6
57+
}

0 commit comments

Comments
 (0)