Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
佳 邓
Gitlab4j Api
Commits
e311cac6
Unverified
Commit
e311cac6
authored
Oct 06, 2021
by
Arnaud Lefebvre
Browse files
Groups: add support for custom attributes
Fix #769
parent
37617ec3
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/main/java/org/gitlab4j/api/GroupApi.java
View file @
e311cac6
...
...
@@ -3,6 +3,7 @@ package org.gitlab4j.api;
import
java.io.File
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.Optional
;
import
java.util.stream.Stream
;
...
...
@@ -15,6 +16,7 @@ import org.gitlab4j.api.models.AccessLevel;
import
org.gitlab4j.api.models.AccessRequest
;
import
org.gitlab4j.api.models.AuditEvent
;
import
org.gitlab4j.api.models.Badge
;
import
org.gitlab4j.api.models.CustomAttribute
;
import
org.gitlab4j.api.models.Group
;
import
org.gitlab4j.api.models.GroupFilter
;
import
org.gitlab4j.api.models.GroupParams
;
...
...
@@ -1725,4 +1727,123 @@ public class GroupApi extends AbstractApi {
delete
(
Response
.
Status
.
NO_CONTENT
,
null
,
"groups"
,
getGroupIdOrPath
(
groupIdOrPath
),
"share"
,
sharedWithGroupId
);
}
/**
* Get all custom attributes for the specified group.
*
* <pre><code>GitLab Endpoint: GET /groups/:id/custom_attributes</code></pre>
*
* @param groupIdOrPath the group in the form of an Integer(ID), String(path), or Group instance
* @return a list of group's CustomAttributes
* @throws GitLabApiException if any exception occurs
*/
public
List
<
CustomAttribute
>
getCustomAttributes
(
final
Object
groupIdOrPath
)
throws
GitLabApiException
{
return
(
getCustomAttributes
(
groupIdOrPath
,
getDefaultPerPage
()).
all
());
}
/**
* Get a Pager of custom attributes for the specified group.
*
* <pre><code>GitLab Endpoint: GET /groups/:id/custom_attributes</code></pre>
*
* @param groupIdOrPath the group in the form of an Integer(ID), String(path), or Group instance
* @param itemsPerPage the number of items per page
* @return a Pager of group's custom attributes
* @throws GitLabApiException if any exception occurs
*/
public
Pager
<
CustomAttribute
>
getCustomAttributes
(
final
Object
groupIdOrPath
,
int
itemsPerPage
)
throws
GitLabApiException
{
return
(
new
Pager
<
CustomAttribute
>(
this
,
CustomAttribute
.
class
,
itemsPerPage
,
null
,
"groups"
,
getGroupIdOrPath
(
groupIdOrPath
),
"custom_attributes"
));
}
/**
* Get a Stream of all custom attributes for the specified group.
*
* <pre><code>GitLab Endpoint: GET /groups/:id/custom_attributes</code></pre>
*
* @param groupIdOrPath the group in the form of an Integer(ID), String(path), or Group instance
* @return a Stream of group's custom attributes
* @throws GitLabApiException if any exception occurs
*/
public
Stream
<
CustomAttribute
>
getCustomAttributesStream
(
final
Object
groupIdOrPath
)
throws
GitLabApiException
{
return
(
getCustomAttributes
(
groupIdOrPath
,
getDefaultPerPage
()).
stream
());
}
/**
* Get a single custom attribute for the specified group.
*
* <pre><code>GitLab Endpoint: GET /groups/:id/custom_attributes/:key</code></pre>
*
* @param groupIdOrPath the group in the form of an Integer(ID), String(path), or Group instance
* @param key the key for the custom attribute
* @return a CustomAttribute instance for the specified key
* @throws GitLabApiException if any exception occurs
*/
public
CustomAttribute
getCustomAttribute
(
final
Object
groupIdOrPath
,
final
String
key
)
throws
GitLabApiException
{
Response
response
=
get
(
Response
.
Status
.
OK
,
null
,
"groups"
,
getGroupIdOrPath
(
groupIdOrPath
),
"custom_attributes"
,
key
);
return
(
response
.
readEntity
(
CustomAttribute
.
class
));
}
/**
* Get an Optional instance with the value for a single custom attribute for the specified group.
*
* <pre><code>GitLab Endpoint: GET /groups/:id/custom_attributes/:key</code></pre>
*
* @param groupIdOrPath the group in the form of an Integer(ID), String(path), or Group instance, required
* @param key the key for the custom attribute, required
* @return an Optional instance with the value for a single custom attribute for the specified group
*/
public
Optional
<
CustomAttribute
>
geOptionalCustomAttribute
(
final
Object
groupIdOrPath
,
final
String
key
)
{
try
{
return
(
Optional
.
ofNullable
(
getCustomAttribute
(
groupIdOrPath
,
key
)));
}
catch
(
GitLabApiException
glae
)
{
return
(
GitLabApi
.
createOptionalFromException
(
glae
));
}
}
/**
* Set a custom attribute for the specified group. The attribute will be updated if it already exists,
* or newly created otherwise.
*
* <pre><code>GitLab Endpoint: PUT /groups/:id/custom_attributes/:key</code></pre>
*
* @param groupIdOrPath the group in the form of an Integer(ID), String(path), or Group instance
* @param key the key for the custom attribute
* @param value the value for the customAttribute
* @return a CustomAttribute instance for the updated or created custom attribute
* @throws GitLabApiException if any exception occurs
*/
public
CustomAttribute
setCustomAttribute
(
final
Object
groupIdOrPath
,
final
String
key
,
final
String
value
)
throws
GitLabApiException
{
if
(
Objects
.
isNull
(
key
)
||
key
.
trim
().
isEmpty
())
{
throw
new
IllegalArgumentException
(
"Key cannot be null or empty"
);
}
if
(
Objects
.
isNull
(
value
)
||
value
.
trim
().
isEmpty
())
{
throw
new
IllegalArgumentException
(
"Value cannot be null or empty"
);
}
GitLabApiForm
formData
=
new
GitLabApiForm
().
withParam
(
"value"
,
value
);
Response
response
=
putWithFormData
(
Response
.
Status
.
OK
,
formData
,
"groups"
,
getGroupIdOrPath
(
groupIdOrPath
),
"custom_attributes"
,
key
);
return
(
response
.
readEntity
(
CustomAttribute
.
class
));
}
/**
* Delete a custom attribute for the specified group.
*
* <pre><code>GitLab Endpoint: DELETE /groups/:id/custom_attributes/:key</code></pre>
*
* @param groupIdOrPath the group in the form of an Integer(ID), String(path), or Group instance
* @param key the key of the custom attribute to delete
* @throws GitLabApiException if any exception occurs
*/
public
void
deleteCustomAttribute
(
final
Object
groupIdOrPath
,
final
String
key
)
throws
GitLabApiException
{
if
(
Objects
.
isNull
(
key
)
||
key
.
trim
().
isEmpty
())
{
throw
new
IllegalArgumentException
(
"Key can't be null or empty"
);
}
delete
(
Response
.
Status
.
OK
,
null
,
"groups"
,
getGroupIdOrPath
(
groupIdOrPath
),
"custom_attributes"
,
key
);
}
}
src/test/java/org/gitlab4j/api/AbstractIntegrationTest.java
View file @
e311cac6
...
...
@@ -5,6 +5,7 @@ import java.util.Map;
import
java.util.WeakHashMap
;
import
org.gitlab4j.api.GitLabApi.ApiVersion
;
import
org.gitlab4j.api.models.Group
;
import
org.gitlab4j.api.models.Project
;
import
org.gitlab4j.api.models.User
;
...
...
@@ -16,6 +17,7 @@ import org.gitlab4j.api.models.User;
* TEST_PRIVATE_TOKEN
* TEST_NAMESPACE
* TEST_PROJECT_NAME
* TEST_GROUP
*/
public
class
AbstractIntegrationTest
implements
PropertyConstants
{
...
...
@@ -33,6 +35,7 @@ public class AbstractIntegrationTest implements PropertyConstants {
protected
static
class
BaseTestResources
{
protected
GitLabApi
gitLabApi
;
protected
Project
testProject
;
protected
Group
testGroup
;
protected
BaseTestResources
(
GitLabApi
gitLabApi
)
{
this
.
gitLabApi
=
gitLabApi
;
...
...
@@ -80,6 +83,10 @@ public class AbstractIntegrationTest implements PropertyConstants {
problems
+=
"TEST_PROJECT_NAME cannot be empty\n"
;
}
if
(
TEST_GROUP
==
null
||
TEST_GROUP
.
trim
().
isEmpty
())
{
problems
+=
"TEST_GROUP cannot be empty\n"
;
}
if
(
problems
.
isEmpty
())
{
try
{
GitLabApi
gitLabApi
=
new
GitLabApi
(
ApiVersion
.
V4
,
TEST_HOST_URL
,
TEST_PRIVATE_TOKEN
);
...
...
@@ -123,6 +130,34 @@ public class AbstractIntegrationTest implements PropertyConstants {
}
}
/**
* Get the test Group instance for the calling test class.
*
* @return the test Group instance for the calling test class
*/
protected
static
Group
getTestGroup
()
{
Throwable
t
=
new
Throwable
();
StackTraceElement
directCaller
=
t
.
getStackTrace
()[
1
];
String
callingClassName
=
directCaller
.
getClassName
();
BaseTestResources
baseResources
=
baseTestResourcesMap
.
get
(
callingClassName
);
if
(
baseResources
==
null
||
baseResources
.
gitLabApi
==
null
)
{
System
.
err
.
println
(
"Problems fetching test Project instance: GitLabApi instance is null"
);
return
(
null
);
}
else
if
(
baseResources
.
testGroup
!=
null
)
{
return
(
baseResources
.
testGroup
);
}
try
{
Group
testGroup
=
(
baseResources
.
gitLabApi
.
getGroupApi
().
getGroup
(
TEST_GROUP
));
baseResources
.
testGroup
=
testGroup
;
return
(
testGroup
);
}
catch
(
Exception
e
)
{
System
.
err
.
println
(
"Problems fetching test Project instance: "
+
e
.
getMessage
());
return
(
null
);
}
}
/**
* Get the current user (the testing user).
*
...
...
src/test/java/org/gitlab4j/api/TestGroupCustomAttributes.java
0 → 100644
View file @
e311cac6
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Greg Messner <greg@messners.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package
org.gitlab4j.api
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assume
.
assumeNotNull
;
import
java.util.List
;
import
java.util.Optional
;
import
java.util.stream.Stream
;
import
org.gitlab4j.api.models.CustomAttribute
;
import
org.gitlab4j.api.models.Group
;
import
org.junit.AfterClass
;
import
org.junit.Before
;
import
org.junit.BeforeClass
;
import
org.junit.Test
;
import
org.junit.experimental.categories.Category
;
/**
* In order for these tests to run you must set the following properties in ~/test-gitlab4j.properties
*
* TEST_NAMESPACE
* TEST_GROUP
* TEST_HOST_URL
* TEST_PRIVATE_TOKEN
*
* If any of the above are NULL, all tests in this class will be skipped.
*/
@Category
(
IntegrationTest
.
class
)
public
class
TestGroupCustomAttributes
extends
AbstractIntegrationTest
{
private
static
final
String
TEST_CUSTOM_ATTRIBUTE_KEY
=
"GitLab4JCustomAttributeTestKey"
;
private
static
final
String
TEST_CUSTOM_ATTRIBUTE_VALUE
=
"CustomAttributeValue"
;
private
static
GitLabApi
gitLabApi
;
private
static
Group
testGroup
;
public
TestGroupCustomAttributes
()
{
super
();
}
@BeforeClass
public
static
void
setup
()
{
// Must setup the connection to the GitLab test server and get the test Group instance
gitLabApi
=
baseTestSetup
();
testGroup
=
getTestGroup
();
deleteAllTestCustomAttributes
();
}
@AfterClass
public
static
void
teardown
()
throws
GitLabApiException
{
deleteAllTestCustomAttributes
();
}
private
static
void
deleteAllTestCustomAttributes
()
{
if
(
gitLabApi
!=
null
)
{
try
{
List
<
CustomAttribute
>
customAttributes
=
gitLabApi
.
getGroupApi
().
getCustomAttributes
(
testGroup
);
if
(
customAttributes
!=
null
)
{
for
(
CustomAttribute
customAttribute
:
customAttributes
)
{
if
(
customAttribute
.
getKey
().
startsWith
(
TEST_CUSTOM_ATTRIBUTE_KEY
))
{
gitLabApi
.
getGroupApi
().
deleteCustomAttribute
(
testGroup
,
customAttribute
.
getKey
());
}
}
}
}
catch
(
GitLabApiException
ignore
)
{
}
}
}
@Before
public
void
beforeMethod
()
{
assumeNotNull
(
gitLabApi
);
}
private
CustomAttribute
createCustomAttribute
(
String
key
,
String
value
)
throws
GitLabApiException
{
return
(
gitLabApi
.
getGroupApi
().
setCustomAttribute
(
testGroup
,
key
,
value
));
}
@Test
public
void
testCreate
()
throws
GitLabApiException
{
CustomAttribute
customAttribute
=
createCustomAttribute
(
TEST_CUSTOM_ATTRIBUTE_KEY
,
TEST_CUSTOM_ATTRIBUTE_VALUE
);
assertNotNull
(
customAttribute
);
assertEquals
(
TEST_CUSTOM_ATTRIBUTE_KEY
,
customAttribute
.
getKey
());
assertEquals
(
TEST_CUSTOM_ATTRIBUTE_VALUE
,
customAttribute
.
getValue
());
}
@Test
public
void
testUpdate
()
throws
GitLabApiException
{
assumeNotNull
(
testGroup
);
String
key
=
TEST_CUSTOM_ATTRIBUTE_KEY
+
"TestUpdate"
;
String
value
=
TEST_CUSTOM_ATTRIBUTE_VALUE
;
CustomAttribute
customAttribute
=
createCustomAttribute
(
key
,
value
);
assertNotNull
(
customAttribute
);
assertEquals
(
key
,
customAttribute
.
getKey
());
assertEquals
(
value
,
customAttribute
.
getValue
());
value
=
TEST_CUSTOM_ATTRIBUTE_VALUE
+
" (updated)"
;
customAttribute
=
gitLabApi
.
getGroupApi
().
setCustomAttribute
(
testGroup
,
key
,
value
);
assertEquals
(
key
,
customAttribute
.
getKey
());
assertEquals
(
value
,
customAttribute
.
getValue
());
}
@Test
public
void
testGetCustomAttribute
()
throws
GitLabApiException
{
assumeNotNull
(
testGroup
);
String
key
=
TEST_CUSTOM_ATTRIBUTE_KEY
+
"TestGet"
;
String
value
=
TEST_CUSTOM_ATTRIBUTE_VALUE
+
" (test get)"
;
CustomAttribute
newCustomAttribute
=
createCustomAttribute
(
key
,
value
);
assertNotNull
(
newCustomAttribute
);
Optional
<
CustomAttribute
>
customAttribute
=
gitLabApi
.
getGroupApi
().
geOptionalCustomAttribute
(
testGroup
,
key
);
assertTrue
(
customAttribute
.
isPresent
());
assertEquals
(
key
,
customAttribute
.
get
().
getKey
());
assertEquals
(
value
,
customAttribute
.
get
().
getValue
());
}
@Test
public
void
testListCustomAttributes
()
throws
GitLabApiException
{
assumeNotNull
(
testGroup
);
String
key
=
TEST_CUSTOM_ATTRIBUTE_KEY
+
"TestList"
;
String
value
=
TEST_CUSTOM_ATTRIBUTE_VALUE
+
" (test list)"
;
CustomAttribute
newCustomAttribute
=
createCustomAttribute
(
key
,
value
);
assertNotNull
(
newCustomAttribute
);
List
<
CustomAttribute
>
customAttributes
=
gitLabApi
.
getGroupApi
().
getCustomAttributes
(
testGroup
);
assertNotNull
(
customAttributes
);
for
(
CustomAttribute
customAttribute
:
customAttributes
)
{
if
(
key
.
equals
(
customAttribute
.
getKey
()))
{
assertEquals
(
value
,
customAttribute
.
getValue
());
break
;
}
}
}
@Test
public
void
testDeleteCustomAttribute
()
throws
GitLabApiException
{
assumeNotNull
(
testGroup
);
String
key
=
TEST_CUSTOM_ATTRIBUTE_KEY
+
"TestDelete"
;
String
value
=
TEST_CUSTOM_ATTRIBUTE_VALUE
+
" (test delete)"
;
createCustomAttribute
(
key
,
value
);
Stream
<
CustomAttribute
>
stream
=
gitLabApi
.
getGroupApi
().
getCustomAttributesStream
(
testGroup
);
Optional
<
CustomAttribute
>
match
=
stream
.
filter
(
c
->
c
.
getKey
().
equals
(
key
)).
findFirst
();
assertTrue
(
match
.
isPresent
());
gitLabApi
.
getGroupApi
().
deleteCustomAttribute
(
testGroup
,
key
);
stream
=
gitLabApi
.
getGroupApi
().
getCustomAttributesStream
(
testGroup
);
match
=
stream
.
filter
(
c
->
c
.
getKey
().
equals
(
key
)).
findFirst
();
assertFalse
(
match
.
isPresent
());
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment