Skip to content

Commit cbb919b

Browse files
author
Calin Lupas
authored
Merge pull request #36 from DevExcelerate/feature/refactor
#22 #25 Add CSV conversion method and update data models for YML seri…
2 parents 9ebc3bd + 6dac231 commit cbb919b

7 files changed

Lines changed: 112 additions & 35 deletions

File tree

src/DevExcelerateApi/Core/Extensions/StringExtensions.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,16 @@ public static string SanitizeResourceName(this string name)
4747

4848
return InvalidCharsRegex.Replace(name, string.Empty);
4949
}
50+
51+
public static List<string>? ConvertCsvToList(this string? csvString)
52+
{
53+
if (string.IsNullOrEmpty(csvString))
54+
return null;
55+
56+
return [.. csvString.Split(Constants.Comma, StringSplitOptions.RemoveEmptyEntries)
57+
.Select(i => i.Trim())
58+
.Where(i => !string.IsNullOrEmpty(i))
59+
.Distinct()];
60+
}
5061
}
5162
}

src/DevExcelerateApi/Models/CreateRepositoryRequestModel.cs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,53 @@
11
using DevExcelerateApi.Core.Extensions;
22
using DevExcelerateApi.Helpers;
3+
using YamlDotNet.Serialization;
34

45
namespace DevExcelerateApi.Models
56
{
67
public class CreateRepositoryRequestModel : DevExIssueRequestModel
78
{
9+
[YamlMember(Alias = "owner", Order = 10)]
810
public string? RepositoryOwner { get; set; } // will be inherited from issue
911

12+
[YamlMember(Alias = "repository_name", Order = 11)]
1013
public string? RepositoryName { get; set; }
1114

15+
[YamlMember(Alias = "visibility", Order = 12)]
1216
public string? RepositoryVisibility { get; set; }
1317

18+
[YamlMember(Alias = "classification", Order = 13)]
1419
public string? RepositoryClassification { get; set; }
1520

21+
[YamlMember(Alias = "repository_description", Order = 14)]
1622
public string? RepositoryDescription { get; set; }
1723

24+
[YamlMember(Alias = "default_branch", Order = 15)]
1825
public string? RepositoryDefaultBranch { get; set; }
1926

27+
[YamlIgnore]
2028
public string? RepositoryMaintainers { get; set; } // will be inherited from issue
2129

30+
[YamlMember(Alias = "maintainers", Order = 16)]
31+
public List<string>? MaintainerList { get; set; }
32+
33+
[YamlIgnore]
2234
public string? RepositoryReaders { get; set; }
2335

36+
[YamlMember(Alias = "readers", Order = 17)]
37+
public List<string>? ReaderList { get; set; }
38+
39+
[YamlIgnore]
2440
public string? RepositoryContributors { get; set; }
2541

42+
[YamlMember(Alias = "contributors", Order = 18)]
43+
public List<string>? ContributorList { get; set; }
44+
45+
[YamlIgnore]
2646
public string? RepositoryRulesets { get; set; }
2747

48+
[YamlMember(Alias = "rulesets", Order = 19)]
49+
public List<string>? RulesetList { get; set; }
50+
2851
public static new CreateRepositoryRequestModel Parse(IDictionary<string, object?> values)
2952
{
3053
ArgumentNullException.ThrowIfNull(values);
@@ -48,9 +71,13 @@ public class CreateRepositoryRequestModel : DevExIssueRequestModel
4871
RepositoryClassification = repositoryClassification?.ToString(),
4972
RepositoryDescription = repositoryDescription?.ToString(),
5073
RepositoryMaintainers = repositoryMaintainers?.ToString(),
74+
MaintainerList = repositoryMaintainers?.ToString().ConvertCsvToList(),
5175
RepositoryReaders = repositoryReaders?.ToString(),
76+
ReaderList = repositoryReaders?.ToString().ConvertCsvToList(),
5277
RepositoryContributors = repositoryContributors?.ToString(),
53-
RepositoryRulesets = repositoryRulesets?.ToString()
78+
ContributorList = repositoryContributors?.ToString().ConvertCsvToList(),
79+
RepositoryRulesets = repositoryRulesets?.ToString(),
80+
RulesetList = repositoryRulesets?.ToString().ConvertCsvToList()
5481
};
5582
}
5683

@@ -60,8 +87,8 @@ public bool IsValid()
6087
!string.IsNullOrEmpty(RepositoryVisibility) &&
6188
!string.IsNullOrEmpty(RepositoryClassification) &&
6289
!string.IsNullOrEmpty(RepositoryDescription) &&
63-
!string.IsNullOrEmpty(RepositoryContributors) &&
64-
!string.IsNullOrEmpty(RepositoryRulesets);
90+
ContributorList?.Count > 0 &&
91+
RulesetList?.Count > 0;
6592
}
6693

6794
public string SerializeToYaml()

src/DevExcelerateApi/Models/CreateTeamRequestModel.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,45 @@
11
using DevExcelerateApi.Core.Extensions;
22
using DevExcelerateApi.Helpers;
3+
using YamlDotNet.Serialization;
34

45
namespace DevExcelerateApi.Models
56
{
67
public class CreateTeamRequestModel : DevExIssueRequestModel
78
{
9+
[YamlMember(Alias = "owner", Order = 10)]
810
public string? TeamOwner { get; set; } // will be inherited from issue
911

12+
[YamlMember(Alias = "team_name", Order = 11)]
1013
public string? TeamName { get; set; }
1114

15+
[YamlMember(Alias = "team_description", Order = 12)]
1216
public string? TeamDescription { get; set; }
1317

18+
[YamlMember(Alias = "parent_team_name", Order = 13)]
1419
public string? ParentTeamName { get; set; }
1520

21+
[YamlMember(Alias = "identity_provider_group", Order = 14)]
1622
public string? TeamIdentityProviderGroup { get; set; }
1723

1824
// TeamPrivacy: secret, closed (visible to all members of the organization.)
25+
[YamlMember(Alias = "visibility", Order = 15)]
1926
public string? TeamVisibility { get; set; }
2027

28+
[YamlIgnore]
2129
public string? TeamMaintainers { get; set; } // will be inherited from issue
2230

31+
[YamlMember(Alias = "maintainers", Order = 16)]
32+
public List<string>? MaintainerList { get; set; }
33+
34+
[YamlIgnore]
2335
public string? TeamMembers { get; set; }
2436

37+
[YamlMember(Alias = "members", Order = 17)]
38+
public List<string>? MemberList { get; set; }
39+
40+
[YamlMember(Alias = "repositories", Order = 20)]
41+
public List<string>? RepositoryList { get; set; }
42+
2543
public static new CreateTeamRequestModel Parse(IDictionary<string, object?> values)
2644
{
2745
ArgumentNullException.ThrowIfNull(values);
@@ -45,7 +63,9 @@ public class CreateTeamRequestModel : DevExIssueRequestModel
4563
TeamIdentityProviderGroup = teamIdentityProviderGroup?.ToString(),
4664
TeamVisibility = teamVisibility?.ToString(),
4765
TeamMaintainers = teamMaintainers?.ToString(),
66+
MaintainerList = teamMaintainers?.ToString().ConvertCsvToList(),
4867
TeamMembers = teamMembers?.ToString(),
68+
MemberList = teamMembers?.ToString().ConvertCsvToList(),
4969
};
5070
}
5171

src/DevExcelerateApi/Models/DevExIssueRequestModel.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
1-
namespace DevExcelerateApi.Models
1+
using YamlDotNet.Serialization;
2+
3+
namespace DevExcelerateApi.Models
24
{
35
public class DevExIssueRequestModel
46
{
7+
[YamlMember(Alias = "name", Order = 1)]
58
public string? Name { get; set; }
69

10+
[YamlMember(Alias = "description", Order = 2)]
711
public string? Description { get; set; }
812

13+
[YamlMember(Alias = "resource", Order = 3)]
914
public string? Resource { get; set; }
1015

16+
[YamlMember(Alias = "type", Order = 4)]
1117
public RequestType RequestType { get; set; }
1218

19+
[YamlMember(Alias = "issue", Order = 5)]
1320
public long? RequestIssue { get; set; }
1421

22+
[YamlMember(Alias = "issue_url", Order = 6)]
1523
public string? RequestIssueHtmlUrl { get; set; }
1624

25+
[YamlMember(Alias = "issue_user", Order = 7)]
1726
public string? RequestUser { get; set; }
1827

1928
public static DevExIssueRequestModel Parse(IDictionary<string, object?> values)

src/DevExcelerateApi/Services/DevExIssuesEventProcessorService.cs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using DevExcelerateApi.Core.Extensions;
2-
using DevExcelerateApi.Core.Options;
32
using DevExcelerateApi.Data;
43
using DevExcelerateApi.Models;
5-
using Microsoft.Extensions.Options;
64
using Microsoft.FeatureManagement;
75
using Octokit.Webhooks;
86
using Octokit.Webhooks.Events;
@@ -19,7 +17,6 @@ public class DevExIssuesEventProcessorService(
1917
ITeamService teamService,
2018
IIssueService issueService,
2119
GitHubWebhookRepository gitHubWebhookRepository,
22-
IOptions<GitHubOptions> gitHubOptions,
2320
ILocalizationService localizationService,
2421
IVariantFeatureManager featureManager)
2522
: IDevExIssuesEventProcessorService
@@ -29,7 +26,6 @@ public class DevExIssuesEventProcessorService(
2926
private readonly ITeamService _teamService = teamService;
3027
private readonly IIssueService _issueService = issueService;
3128
private readonly GitHubWebhookRepository _gitHubWebhookRepository = gitHubWebhookRepository;
32-
private readonly GitHubOptions _gitHubOptions = gitHubOptions.Value;
3329
private readonly ILocalizationService _localizationService = localizationService;
3430
private readonly IVariantFeatureManager _featureManager = featureManager;
3531

@@ -115,6 +111,11 @@ private async Task ValidateIssueApproval(IssuesEvent issuesEvent)
115111
{
116112
await ValidateIssue(issuesEvent!);
117113
}
114+
// Failed
115+
else if ((issuesEvent?.Issue?.Labels?.Any(i => i.Name.IsIssueFailed())).GetValueOrDefault())
116+
{
117+
await ValidateIssue(issuesEvent!);
118+
}
118119
}
119120

120121
private async Task ValidateIssue(IssuesEvent issuesEvent)
@@ -126,18 +127,23 @@ private async Task ValidateIssue(IssuesEvent issuesEvent)
126127
{
127128
case RequestType.CREATE_REPOSITORY:
128129
// Check ticket status => From Approved to Validated or Failed
129-
if ((issuesEvent?.Issue?.Labels?.Any(i => i.Name.IsIssueApproved())).GetValueOrDefault())
130+
// From Failed -> Validated (if action = edited)
131+
if (
132+
(issuesEvent?.Issue?.Labels?.Any(i => i.Name.IsIssueApproved())).GetValueOrDefault()
133+
||
134+
((issuesEvent?.Issue?.Labels?.Any(i => i.Name.IsIssueFailed())).GetValueOrDefault() && issuesEvent?.Action == IssuesActionValue.Edited)
135+
)
130136
{
131137
// Check if the issue form is valid
132138
await _repositoryService.ValidateCreateRepository(issuesEvent!, createPullRequest: false);
133-
}
139+
}
134140
else if ((issuesEvent?.Issue?.Labels?.Any(i => i.Name.IsIssueValidated())).GetValueOrDefault())
135141
{
136142
if (await _featureManager.IsEnabledAsync("UseInventoryWithPullRequest"))
137143
{
138144
// IF validated, create a pull request
139145
await _repositoryService.ValidateCreateRepository(issuesEvent!, createPullRequest: true);
140-
}
146+
}
141147
else
142148
{
143149
await _repositoryService.SaveRepository(issuesEvent!);
@@ -147,7 +153,11 @@ private async Task ValidateIssue(IssuesEvent issuesEvent)
147153

148154
case RequestType.CREATE_TEAM:
149155
// Check ticket status => From Approved to Validated or Failed
150-
if ((issuesEvent?.Issue?.Labels?.Any(i => i.Name.IsIssueApproved())).GetValueOrDefault())
156+
if (
157+
(issuesEvent?.Issue?.Labels?.Any(i => i.Name.IsIssueApproved())).GetValueOrDefault()
158+
||
159+
((issuesEvent?.Issue?.Labels?.Any(i => i.Name.IsIssueFailed())).GetValueOrDefault() && issuesEvent?.Action == IssuesActionValue.Edited)
160+
)
151161
{
152162
// Check if the issue form is valid
153163
await _teamService.ValidateCreateTeam(issuesEvent!, createPullRequest: false);

src/DevExcelerateApi/Services/RepositoryService.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ public async Task ValidateCreateRepository(IssuesEvent issuesEvent, bool createP
5353
// Validate if the teams exist
5454
var teamsString = $"{repoRequest.RepositoryMaintainers},{repoRequest.RepositoryContributors},{repoRequest.RepositoryReaders}";
5555

56-
var teams = teamsString.Split(Constants.Comma, StringSplitOptions.RemoveEmptyEntries).Select(i => i.Trim()).Distinct();
56+
var teams = teamsString.ConvertCsvToList();
5757

58-
foreach (var team in teams)
58+
foreach (var team in teams!)
5959
{
6060
// Check if the team is valid
6161
try
@@ -83,9 +83,9 @@ public async Task ValidateCreateRepository(IssuesEvent issuesEvent, bool createP
8383
if (repoRequest.RepositoryRulesets != null)
8484
{
8585
// Check if the rulesets exist as values of the custom property
86-
var rulesets = repoRequest.RepositoryRulesets.Split(Constants.Comma, StringSplitOptions.RemoveEmptyEntries).Select(i => i.Trim());
86+
var rulesets = repoRequest.RepositoryRulesets.ConvertCsvToList();
8787

88-
foreach (var ruleset in rulesets)
88+
foreach (var ruleset in rulesets!)
8989
{
9090
// Check if the custom property has valid values
9191
try
@@ -142,12 +142,12 @@ public async Task ValidateCreateRepository(IssuesEvent issuesEvent, bool createP
142142

143143
if (isValid)
144144
{
145-
validationMessage = $"{_localizationService.GetLocalizedString(Constants.ISSUE_VALIDATED)}\n{string.Join("\n- ", validationReasons)}";
145+
validationMessage = $"{_localizationService.GetLocalizedString(Constants.ISSUE_VALIDATED)}\n- {string.Join("\n- ", validationReasons)}";
146146
await _issueService.ChangeIssueLabel([TicketStatus.VALIDATED.ToString()], issuesEvent!);
147147
}
148148
else
149149
{
150-
validationMessage = $"{_localizationService.GetLocalizedString(Constants.ISSUE_FAILED)}\n{string.Join("\n- ", validationReasons)}";
150+
validationMessage = $"{_localizationService.GetLocalizedString(Constants.ISSUE_FAILED)}\n- {string.Join("\n- ", validationReasons)}";
151151
await _issueService.ChangeIssueLabel([TicketStatus.FAILED.ToString()], issuesEvent!);
152152
}
153153

@@ -298,9 +298,9 @@ public async Task SaveRepository(PullRequestEvent pullRequestEvent)
298298
// Step 2: Add the reader teams to the repo
299299
if (repoRequest.RepositoryReaders != null)
300300
{
301-
var teams = repoRequest.RepositoryReaders.Split(Constants.Comma).Select(i => i.Trim()).Distinct();
301+
var teams = repoRequest.RepositoryReaders.ConvertCsvToList();
302302

303-
foreach (var team in teams)
303+
foreach (var team in teams!)
304304
{
305305
await installationClient.Organization.Team.AddOrUpdateTeamRepositoryPermissions(repoRequest.RepositoryOwner, team, repoRequest.RepositoryOwner, repoRequest.RepositoryName, CollaboratorPermission.Pull.ToString().ToLowerInvariant());
306306
}
@@ -309,8 +309,8 @@ public async Task SaveRepository(PullRequestEvent pullRequestEvent)
309309
// Step 3: Add the contributor teams to the repo
310310
if (repoRequest.RepositoryContributors != null)
311311
{
312-
var teams = repoRequest.RepositoryContributors.Split(Constants.Comma).Select(i => i.Trim()).Distinct();
313-
foreach (var team in teams)
312+
var teams = repoRequest.RepositoryContributors.ConvertCsvToList();
313+
foreach (var team in teams!)
314314
{
315315
await installationClient.Organization.Team.AddOrUpdateTeamRepositoryPermissions(repoRequest.RepositoryOwner, team, repoRequest.RepositoryOwner, repoRequest.RepositoryName, CollaboratorPermission.Push.ToString().ToLowerInvariant());
316316
}
@@ -319,8 +319,8 @@ public async Task SaveRepository(PullRequestEvent pullRequestEvent)
319319
// Step 4: Add the maintain teams to the repo
320320
if (repoRequest.RepositoryMaintainers != null)
321321
{
322-
var teams = repoRequest.RepositoryMaintainers.Split(Constants.Comma).Select(i => i.Trim()).Distinct();
323-
foreach (var team in teams)
322+
var teams = repoRequest.RepositoryMaintainers.ConvertCsvToList();
323+
foreach (var team in teams!)
324324
{
325325
await installationClient.Organization.Team.AddOrUpdateTeamRepositoryPermissions(repoRequest.RepositoryOwner, team, repoRequest.RepositoryOwner, repoRequest.RepositoryName, CollaboratorPermission.Maintain.ToString().ToLowerInvariant());
326326
}
@@ -334,7 +334,7 @@ public async Task SaveRepository(PullRequestEvent pullRequestEvent)
334334
// Add the repo branch protection rulesets based on the custom properties
335335
if (repoRequest.RepositoryRulesets != null)
336336
{
337-
var rulesets = repoRequest.RepositoryRulesets.Split(Constants.Comma, StringSplitOptions.RemoveEmptyEntries).Select(i => i.Trim()).ToList();
337+
var rulesets = repoRequest.RepositoryRulesets.ConvertCsvToList();
338338

339339
await installationClient.Repository.CustomProperty.CreateOrUpdate(repoRequest.RepositoryOwner, repoRequest.RepositoryName, new UpsertRepositoryCustomPropertyValues()
340340
{
@@ -395,7 +395,7 @@ public async Task SaveRepository(PullRequestEvent pullRequestEvent)
395395
{
396396
// Raise the PR to the inventory repo
397397
var prTitle = $"{repoRequest.RequestType} - {repoRequest.RepositoryName} - {Constants.GitHubPullRequestTitleIssueNumber}{repoRequest.RequestIssue}";
398-
var prBody = $"{_localizationService.GetLocalizedString(Constants.PULL_REQUEST_BODY)}\n\n- Issue Request: {repoRequest.RequestIssueHtmlUrl}\n\n{repoRequestYaml}";
398+
var prBody = $"{_localizationService.GetLocalizedString(Constants.PULL_REQUEST_BODY)}\n\n- Issue Request: {repoRequest.RequestIssueHtmlUrl}\n\n```yaml\n{repoRequestYaml}\n```";
399399

400400
var pr = await gitHubClient.CreatePullRequestAsync(
401401
repoRequest.RepositoryOwner!,

0 commit comments

Comments
 (0)