Skip to content

Commit f9fbd88

Browse files
authored
Add method to update code_owner_approval_required flag to Protected Branches API (gitlab4j#870)
1 parent 0ec95c1 commit f9fbd88

File tree

5 files changed

+129
-19
lines changed

5 files changed

+129
-19
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ local.properties
2626
.classpath
2727
.settings/
2828
.loadpath
29+
30+
### Visual Studio Code ###
31+
.vscode
2932

3033
# External tool builders
3134
.externalToolBuilders/
@@ -45,7 +48,7 @@ target/
4548

4649
# Test properties file for gitlab4j
4750
test-gitlab4j.properties
48-
!src/test/resoures/test-gitlab4j.properties
51+
!src/test/resources/test-gitlab4j.properties
4952

5053
# git-changelog plugin #
5154
.okhttpcache

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

+36
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,42 @@ protected Response head(Response.Status expectedStatus, MultivaluedMap<String, S
272272
}
273273
}
274274

275+
/**
276+
* Perform an HTTP PATCH call with the specified query parameters and path objects, returning
277+
* a ClientResponse instance with the data returned from the endpoint.
278+
*
279+
* @param expectedStatus the HTTP status that should be returned from the server
280+
* @param queryParams multivalue map of request parameters
281+
* @param pathArgs variable list of arguments used to build the URI
282+
* @return a ClientResponse instance with the data returned from the endpoint
283+
* @throws GitLabApiException if any exception occurs during execution
284+
*/
285+
protected Response patch(Response.Status expectedStatus, MultivaluedMap<String, String> queryParams, Object... pathArgs) throws GitLabApiException {
286+
try {
287+
return validate(getApiClient().patch(queryParams, pathArgs), expectedStatus);
288+
} catch (Exception e) {
289+
throw handle(e);
290+
}
291+
}
292+
293+
/**
294+
* Perform an HTTP PATCH call with the specified query parameters and URL, returning
295+
* a ClientResponse instance with the data returned from the endpoint.
296+
*
297+
* @param expectedStatus the HTTP status that should be returned from the server
298+
* @param queryParams multivalue map of request parameters
299+
* @param url the fully formed path to the GitLab API endpoint
300+
* @return a ClientResponse instance with the data returned from the endpoint
301+
* @throws GitLabApiException if any exception occurs during execution
302+
*/
303+
protected Response patch(Response.Status expectedStatus, MultivaluedMap<String, String> queryParams, URL url) throws GitLabApiException {
304+
try {
305+
return validate(getApiClient().patch(queryParams, url), expectedStatus);
306+
} catch (Exception e) {
307+
throw handle(e);
308+
}
309+
}
310+
275311
/**
276312
* Perform an HTTP POST call with the specified form data and path objects, returning
277313
* a ClientResponse instance with the data returned from the endpoint.

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

+32-3
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,8 @@ void enableRequestResponseLogging(Logger logger, Level level, int maxEntityLengt
287287
* @param readTimeout the per request read timeout in milliseconds, can be null to use default
288288
*/
289289
void setRequestTimeout(Integer connectTimeout, Integer readTimeout) {
290-
this.connectTimeout = connectTimeout;
291-
this.readTimeout = readTimeout;
290+
this.connectTimeout = connectTimeout;
291+
this.readTimeout = readTimeout;
292292
}
293293

294294
/**
@@ -470,6 +470,35 @@ protected Response head(MultivaluedMap<String, String> queryParams, URL url) {
470470
return (invocation(url, queryParams).head());
471471
}
472472

473+
/**
474+
* Perform an HTTP PATCH call with the specified query parameters and path objects, returning
475+
* a ClientResponse instance with the data returned from the endpoint.
476+
*
477+
* @param queryParams multivalue map of request parameters
478+
* @param pathArgs variable list of arguments used to build the URI
479+
* @return a ClientResponse instance with the data returned from the endpoint
480+
* @throws IOException if an error occurs while constructing the URL
481+
*/
482+
protected Response patch(MultivaluedMap<String, String> queryParams, Object... pathArgs) throws IOException {
483+
URL url = getApiUrl(pathArgs);
484+
return (patch(queryParams, url));
485+
}
486+
487+
/**
488+
* Perform an HTTP PATCH call with the specified query parameters and URL, returning
489+
* a ClientResponse instance with the data returned from the endpoint.
490+
*
491+
* @param queryParams multivalue map of request parameters
492+
* @param url the fully formed path to the GitLab API endpoint
493+
* @return a ClientResponse instance with the data returned from the endpoint
494+
*/
495+
protected Response patch(MultivaluedMap<String, String> queryParams, URL url) {
496+
Entity<?> empty = Entity.text("");
497+
// use "X-HTTP-Method-Override" header on POST to override to unsupported PATCH
498+
return (invocation(url, queryParams)
499+
.header("X-HTTP-Method-Override", "PATCH").post(empty));
500+
}
501+
473502
/**
474503
* Perform an HTTP POST call with the specified form data and path objects, returning
475504
* a ClientResponse instance with the data returned from the endpoint.
@@ -918,7 +947,7 @@ public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngi
918947
// Ignore differences between given hostname and certificate hostname
919948
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
920949
@Override
921-
public boolean verify(String hostname, SSLSession session) {
950+
public boolean verify(String hostname, SSLSession session) {
922951
return true;
923952
}
924953
};

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

+38-14
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,8 @@ public ProtectedBranch protectBranch(Object projectIdOrPath, String branchName,
154154
* @throws GitLabApiException if any exception occurs
155155
*/
156156
public ProtectedBranch protectBranch(Object projectIdOrPath, String branchName,
157-
AccessLevel pushAccessLevel, AccessLevel mergeAccessLevel, AccessLevel unprotectAccessLevel,
158-
Boolean codeOwnerApprovalRequired) throws GitLabApiException {
157+
AccessLevel pushAccessLevel, AccessLevel mergeAccessLevel, AccessLevel unprotectAccessLevel,
158+
Boolean codeOwnerApprovalRequired) throws GitLabApiException {
159159
Form formData = new GitLabApiForm()
160160
.withParam("name", branchName, true)
161161
.withParam("push_access_level", pushAccessLevel)
@@ -184,10 +184,10 @@ public ProtectedBranch protectBranch(Object projectIdOrPath, String branchName,
184184
* @throws GitLabApiException if any exception occurs
185185
*/
186186
public ProtectedBranch protectBranch(Object projectIdOrPath, String branchName,
187-
Integer allowedToPushUserId, Integer allowedToMergeUserId, Integer allowedToUnprotectUserId,
188-
Boolean codeOwnerApprovalRequired) throws GitLabApiException {
187+
Integer allowedToPushUserId, Integer allowedToMergeUserId, Integer allowedToUnprotectUserId,
188+
Boolean codeOwnerApprovalRequired) throws GitLabApiException {
189189

190-
Form formData = new GitLabApiForm()
190+
Form formData = new GitLabApiForm()
191191
.withParam("name", branchName, true)
192192
.withParam("allowed_to_push[][user_id]", allowedToPushUserId)
193193
.withParam("allowed_to_merge[][user_id]", allowedToMergeUserId)
@@ -215,22 +215,46 @@ public ProtectedBranch protectBranch(Object projectIdOrPath, String branchName,
215215
* @throws GitLabApiException if any exception occurs
216216
*/
217217
public ProtectedBranch protectBranch(Object projectIdOrPath, String branchName,
218-
AllowedTo allowedToPush, AllowedTo allowedToMerge, AllowedTo allowedToUnprotect,
219-
Boolean codeOwnerApprovalRequired) throws GitLabApiException {
218+
AllowedTo allowedToPush, AllowedTo allowedToMerge, AllowedTo allowedToUnprotect,
219+
Boolean codeOwnerApprovalRequired) throws GitLabApiException {
220220

221221
GitLabApiForm formData = new GitLabApiForm()
222222
.withParam("name", branchName, true)
223223
.withParam("code_owner_approval_required", codeOwnerApprovalRequired);
224224

225-
if (allowedToPush != null)
226-
allowedToPush.getForm(formData, "allowed_to_push");
227-
if (allowedToMerge != null)
228-
allowedToMerge.getForm(formData, "allowed_to_merge");
229-
if (allowedToUnprotect != null)
230-
allowedToUnprotect.getForm(formData, "allowed_to_unprotect");
225+
if (allowedToPush != null)
226+
allowedToPush.getForm(formData, "allowed_to_push");
227+
if (allowedToMerge != null)
228+
allowedToMerge.getForm(formData, "allowed_to_merge");
229+
if (allowedToUnprotect != null)
230+
allowedToUnprotect.getForm(formData, "allowed_to_unprotect");
231231

232-
Response response = post(Response.Status.CREATED, formData.asMap(),
232+
Response response = post(Response.Status.CREATED, formData.asMap(),
233233
"projects", getProjectIdOrPath(projectIdOrPath), "protected_branches");
234234
return (response.readEntity(ProtectedBranch.class));
235235
}
236+
237+
/**
238+
* Sets the code_owner_approval_required flag on the specified protected branch.
239+
*
240+
* <p>NOTE: This method is only available in GitLab Premium or higher.</p>
241+
*
242+
* <pre><code>GitLab Endpoint: PATCH /projects/:id/protected_branches/:branch_name?code_owner_approval_required=true</code></pre>
243+
*
244+
* @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance
245+
* @param branchName the name of the branch to protect, can be a wildcard
246+
* @param codeOwnerApprovalRequired prevent pushes to this branch if it matches an item in the CODEOWNERS file.
247+
* @return the branch info for the protected branch
248+
* @throws GitLabApiException if any exception occurs
249+
*/
250+
public ProtectedBranch setCodeOwnerApprovalRequired(Object projectIdOrPath, String branchName,
251+
Boolean codeOwnerApprovalRequired) throws GitLabApiException {
252+
Form formData = new GitLabApiForm()
253+
.withParam("code_owner_approval_required", codeOwnerApprovalRequired);
254+
255+
Response response = patch(Response.Status.OK, formData.asMap(),
256+
"projects", this.getProjectIdOrPath(projectIdOrPath),
257+
"protected_branches", urlEncode(branchName));
258+
return (response.readEntity(ProtectedBranch.class));
259+
}
236260
}

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

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package org.gitlab4j.api;
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertFalse;
45
import static org.junit.jupiter.api.Assertions.assertNotNull;
6+
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
57
import static org.junit.jupiter.api.Assertions.assertTrue;
68
import static org.junit.jupiter.api.Assumptions.assumeTrue;
79

@@ -45,7 +47,7 @@ public class TestProtectedBranchesApi extends AbstractIntegrationTest {
4547

4648
@BeforeAll
4749
public static void setup() {
48-
// Must setup the connection to the GitLab test server and get the test Project instance
50+
// Must setup the connection to the GitLab test server and get the test Project instance
4951
gitLabApi = baseTestSetup();
5052
testProject = getTestProject();
5153
}
@@ -124,4 +126,20 @@ public void testProtectBranch() throws GitLabApiException {
124126
assertTrue(branches.stream()
125127
.anyMatch((protectedBranch) -> protectedBranch.getName().equals(TEST_BRANCH_NAME)));
126128
}
129+
130+
@Test
131+
public void testSetCodeOwnerApprovalRequired() throws GitLabApiException {
132+
133+
assumeTrue(testProject != null);
134+
135+
ProtectedBranch branch = gitLabApi.getProtectedBranchesApi().getProtectedBranch(testProject, TEST_BRANCH_NAME);
136+
assertNotNull(branch);
137+
// current version returns null, but will return boolean (false) with newer Premium
138+
assertFalse(branch.getCodeOwnerApprovalRequired() != null);
139+
140+
// current version returns 404, but will return branch with "code_owner_approval_required = true" with newer Premium
141+
GitLabApiException gae = assertThrowsExactly(GitLabApiException.class,
142+
() -> gitLabApi.getProtectedBranchesApi().setCodeOwnerApprovalRequired(testProject, TEST_BRANCH_NAME, true));
143+
assertTrue(gae.getHttpStatus() == 404);
144+
}
127145
}

0 commit comments

Comments
 (0)