Skip to content

Commit 965f031

Browse files
authored
Add Group Variables CRUD methods (#146)
1 parent 6eb1e68 commit 965f031

File tree

8 files changed

+247
-3
lines changed

8 files changed

+247
-3
lines changed

src/GitLabApiClient/GroupsClient.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,5 +336,44 @@ public async Task<GroupLabel> UpdateLabelAsync(GroupId groupId, UpdateGroupLabel
336336
/// <param name="name">Name of the label.</param>
337337
public async Task DeleteLabelAsync(GroupId groupId, string name) =>
338338
await _httpFacade.Delete($"groups/{groupId}/labels?name={name}");
339+
340+
/// <summary>
341+
/// Retrieves group variables by its id.
342+
/// </summary>
343+
/// <param name="groupId">Id of the group.</param>
344+
public async Task<IList<Variable>> GetVariablesAsync(GroupId groupId) =>
345+
await _httpFacade.GetPagedList<Variable>($"groups/{groupId}/variables");
346+
347+
/// <summary>
348+
/// Creates new project variable.
349+
/// </summary>
350+
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
351+
/// <param name="request">Create variable request.</param>
352+
/// <returns>Newly created variable.</returns>
353+
public async Task<Variable> CreateVariableAsync(GroupId groupId, CreateGroupVariableRequest request)
354+
{
355+
Guard.NotNull(request, nameof(request));
356+
return await _httpFacade.Post<Variable>($"groups/{groupId}/variables", request);
357+
}
358+
359+
/// <summary>
360+
/// Updates an existing group variable.
361+
/// </summary>
362+
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
363+
/// <param name="request">Update variable request.</param>
364+
/// <returns>Newly modified variable.</returns>
365+
public async Task<Variable> UpdateVariableAsync(GroupId groupId, UpdateGroupVariableRequest request)
366+
{
367+
Guard.NotNull(request, nameof(request));
368+
return await _httpFacade.Put<Variable>($"groups/{groupId}/variables/{request.Key}", request);
369+
}
370+
371+
/// <summary>
372+
/// Deletes group variable
373+
/// </summary>
374+
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
375+
/// <param name="key">The Key ID of the variable.</param>
376+
public async Task DeleteVariableAsync(GroupId groupId, string key) =>
377+
await _httpFacade.Delete($"groups/{groupId}/variables/{key}");
339378
}
340379
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Newtonsoft.Json;
2+
3+
namespace GitLabApiClient.Models.Groups.Requests
4+
{
5+
public class CreateGroupVariableRequest
6+
{
7+
/// <summary>
8+
/// The type of a variable.
9+
/// Available types are: env_var (default) and file
10+
/// </summary>
11+
[JsonProperty("variable_type")]
12+
public string VariableType { get; set; }
13+
14+
/// <summary>
15+
/// The key of a variable
16+
/// </summary>
17+
[JsonProperty("key")]
18+
public string Key { get; set; }
19+
20+
/// <summary>
21+
/// The value of a variable
22+
/// </summary>
23+
[JsonProperty("value")]
24+
public string Value { get; set; }
25+
26+
/// <summary>
27+
/// Whether the variable is protected
28+
/// </summary>
29+
[JsonProperty("protected")]
30+
public bool? Protected { get; set; }
31+
32+
/// <summary>
33+
/// Whether the variable is masked
34+
/// </summary>
35+
[JsonProperty("masked")]
36+
public bool? Masked { get; set; }
37+
}
38+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Newtonsoft.Json;
2+
3+
namespace GitLabApiClient.Models.Groups.Requests
4+
{
5+
public class UpdateGroupVariableRequest
6+
{
7+
/// <summary>
8+
/// The type of a variable.
9+
/// Available types are: env_var (default) and file
10+
/// </summary>
11+
[JsonProperty("variable_type")]
12+
public string VariableType { get; set; }
13+
14+
/// <summary>
15+
/// The key of a variable
16+
/// </summary>
17+
[JsonProperty("key")]
18+
public string Key { get; set; }
19+
20+
/// <summary>
21+
/// The value of a variable
22+
/// </summary>
23+
[JsonProperty("value")]
24+
public string Value { get; set; }
25+
26+
/// <summary>
27+
/// Whether the variable is protected
28+
/// </summary>
29+
[JsonProperty("protected")]
30+
public bool? Protected { get; set; }
31+
32+
/// <summary>
33+
/// Whether the variable is masked
34+
/// </summary>
35+
[JsonProperty("masked")]
36+
public bool? Masked { get; set; }
37+
}
38+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Newtonsoft.Json;
2+
3+
namespace GitLabApiClient.Models.Groups.Responses
4+
{
5+
public sealed class Variable
6+
{
7+
/// <summary>
8+
/// The type of a variable.
9+
/// Available types are: env_var (default) and file
10+
/// </summary>
11+
[JsonProperty("variable_type")]
12+
public string VariableType { get; set; }
13+
14+
/// <summary>
15+
/// The key of a variable
16+
/// </summary>
17+
[JsonProperty("key")]
18+
public string Key { get; set; }
19+
20+
/// <summary>
21+
/// The value of a variable
22+
/// </summary>
23+
[JsonProperty("value")]
24+
public string Value { get; set; }
25+
26+
/// <summary>
27+
/// Whether the variable is protected
28+
/// </summary>
29+
[JsonProperty("protected")]
30+
public bool Protected { get; set; }
31+
32+
/// <summary>
33+
/// Whether the variable is masked
34+
/// </summary>
35+
[JsonProperty("masked")]
36+
public bool Masked { get; set; }
37+
}
38+
}

src/GitLabApiClient/ProjectsClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public async Task<IList<User>> GetUsersAsync(ProjectId projectId) =>
7171
/// Retrieves project variables by its id.
7272
/// </summary>
7373
/// <param name="projectId">Id of the project.</param>
74-
public async Task<IList<Variable>> GetVariablesAsync(int projectId) =>
74+
public async Task<IList<Variable>> GetVariablesAsync(ProjectId projectId) =>
7575
await _httpFacade.GetPagedList<Variable>($"projects/{projectId}/variables");
7676

7777
/// <summary>

test/GitLabApiClient.Test/GitLabClientTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public async void CanLogin()
6666
accessTokenResponse.CreatedAt.Should().NotBeNull();
6767
accessTokenResponse.AccessToken.Should().HaveLength(64);
6868
accessTokenResponse.RefreshToken.Should().HaveLength(64);
69-
accessTokenResponse.TokenType.Should().Be("bearer");
69+
accessTokenResponse.TokenType.Should().BeEquivalentTo("bearer");
7070
var currentSessionAsync = await sut.Users.GetCurrentSessionAsync();
7171
currentSessionAsync.Username.Should().Be(GitLabApiHelper.TestUserName);
7272

test/GitLabApiClient.Test/GroupsClientTest.cs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Generic;
22
using System.IO;
3+
using System.Linq;
34
using System.Threading.Tasks;
45
using FluentAssertions;
56
using GitLabApiClient.Internal.Queries;
@@ -19,6 +20,7 @@ public class GroupsClientTest
1920
{
2021
private readonly List<int> _groupIdsToClean = new List<int>();
2122
private List<int> MilestoneIdsToClean { get; } = new List<int>();
23+
private List<string> VariableIdsToClean { get; } = new List<string>();
2224

2325
private readonly GroupsClient _sut = new GroupsClient(
2426
GetFacade(),
@@ -229,6 +231,92 @@ public async Task CreatedGroupMilestoneCanBeClosed()
229231
updatedMilestone.Should().Match<Milestone>(i => i.State == MilestoneState.Closed);
230232
}
231233

234+
[Fact]
235+
public async Task GroupVariablesRetrieved()
236+
{
237+
//arrange
238+
var createdVariable = await _sut.CreateVariableAsync(GitLabApiHelper.TestGroupId, new CreateGroupVariableRequest
239+
{
240+
VariableType = "env_var",
241+
Key = "SOME_VAR_KEY_RETRIEVE",
242+
Value = "VALUE_VAR",
243+
Masked = true,
244+
Protected = true
245+
});
246+
247+
VariableIdsToClean.Add(createdVariable.Key);
248+
249+
//act
250+
var variables = await _sut.GetVariablesAsync(GitLabApiHelper.TestGroupId);
251+
var variable = variables.First(v => v.Key == createdVariable.Key);
252+
253+
//assert
254+
variables.Should().NotBeEmpty();
255+
variable.Should().Match<Variable>(v =>
256+
v.VariableType == createdVariable.VariableType &&
257+
v.Key == createdVariable.Key &&
258+
v.Value == createdVariable.Value &&
259+
v.Masked == createdVariable.Masked &&
260+
v.Protected == createdVariable.Protected);
261+
}
262+
263+
[Fact]
264+
public async Task GroupVariablesCreated()
265+
{
266+
var request = new CreateGroupVariableRequest
267+
{
268+
VariableType = "env_var",
269+
Key = "SOME_VAR_KEY_CREATED",
270+
Value = "VALUE_VAR",
271+
Masked = true,
272+
Protected = true
273+
};
274+
275+
var variable = await _sut.CreateVariableAsync(GitLabApiHelper.TestGroupId, request);
276+
277+
variable.Should().Match<Variable>(v => v.VariableType == request.VariableType
278+
&& v.Key == request.Key
279+
&& v.Value == request.Value
280+
&& v.Masked == request.Masked
281+
&& v.Protected == request.Protected);
282+
283+
VariableIdsToClean.Add(request.Key);
284+
}
285+
286+
[Fact]
287+
public async Task GroupVariableCanBeUpdated()
288+
{
289+
var request = new CreateGroupVariableRequest
290+
{
291+
VariableType = "env_var",
292+
Key = "SOME_VAR_KEY_TO_UPDATE",
293+
Value = "VALUE_VAR",
294+
Masked = true,
295+
Protected = true
296+
};
297+
298+
var variable = await _sut.CreateVariableAsync(GitLabApiHelper.TestGroupId, request);
299+
300+
VariableIdsToClean.Add(request.Key);
301+
302+
var updateRequest = new UpdateGroupVariableRequest
303+
{
304+
VariableType = "file",
305+
Key = request.Key,
306+
Value = "UpdatedValue",
307+
Masked = request.Masked,
308+
Protected = request.Protected,
309+
};
310+
311+
var variableUpdated = await _sut.UpdateVariableAsync(GitLabApiHelper.TestGroupId, updateRequest);
312+
313+
variableUpdated.Should().Match<Variable>(v => v.VariableType == updateRequest.VariableType
314+
&& v.Key == updateRequest.Key
315+
&& v.Value == updateRequest.Value
316+
&& v.Masked == updateRequest.Masked
317+
&& v.Protected == updateRequest.Protected);
318+
}
319+
232320
[Fact]
233321
public Task InitializeAsync()
234322
=> CleanupGroups();
@@ -244,6 +332,9 @@ private async Task CleanupGroups()
244332

245333
foreach (int groupId in _groupIdsToClean)
246334
await _sut.DeleteAsync(groupId.ToString());
335+
336+
foreach (string variableId in VariableIdsToClean)
337+
await _sut.DeleteVariableAsync(GitLabApiHelper.TestGroupId, variableId);
247338
}
248339

249340
private static string GetRandomGroupName()

test/GitLabApiClient.Test/Utilities/GitLabContainerFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class GitLabContainerFixture : IAsyncLifetime
2121
public static string GitlabHost { get; private set; }
2222

2323
private IContainerService _gitlabContainer;
24-
private readonly string _gitlabDockerImage = "gitlab/gitlab-ce:12.5.4-ce.0";
24+
private readonly string _gitlabDockerImage = "gitlab/gitlab-ce:12.10.2-ce.0";
2525

2626
public async Task InitializeAsync()
2727
{

0 commit comments

Comments
 (0)