Skip to content

Commit d676e13

Browse files
authored
Merge pull request #58 from twpol/twpol/issue57
Collect all references in one list
2 parents 75f3834 + a52a522 commit d676e13

File tree

4 files changed

+84
-48
lines changed

4 files changed

+84
-48
lines changed

Git/Commit.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ public class Commit
1818
public string Message { get; private set; }
1919
public string Summary => Message.Split('\n')[0];
2020
public List<Commit> Commits { get; } = new List<Commit>();
21-
public List<string> References { get; } = new List<string>();
2221

2322
internal Commit(string key) => (Key, Message) = (key, "");
2423

Program.cs

Lines changed: 30 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using System.Text.RegularExpressions;
66
using System.Threading.Tasks;
77
using Microsoft.Extensions.Configuration;
8-
using Open_Rails_Triage.Git;
98
using Open_Rails_Triage.Launchpad;
109

1110
namespace Open_Rails_Triage
@@ -46,6 +45,7 @@ static void Main(string[] args)
4645

4746
static async Task AsyncMain(IConfigurationRoot config, bool verbose)
4847
{
48+
var references = new References();
4949
var gitConfig = config.GetSection("git");
5050
var gitHubConfig = config.GetSection("github");
5151
var launchpadConfig = config.GetSection("launchpad");
@@ -54,21 +54,20 @@ static async Task AsyncMain(IConfigurationRoot config, bool verbose)
5454
var git = new Git.Project(GetGitPath(), verbose);
5555
git.Init(gitConfig["projectUrl"]);
5656
git.Fetch();
57-
var commits = git.GetLog(gitConfig["branch"], DateTimeOffset.Parse(gitConfig["startDate"]));
5857

5958
var gitHub = new GitHub.Project(gitHubConfig);
6059

6160
var launchpad = new Launchpad.Cache();
6261
var launchpadProject = await launchpad.GetProject(launchpadConfig["projectUrl"]);
6362

64-
await CommitTriage(commits, gitConfig, gitHub);
65-
await BugTriage(launchpadProject, launchpadConfig, commits);
66-
await SpecificationTriage(launchpadProject, launchpadConfig, commits);
63+
await CommitTriage(git, gitConfig, gitHub, references);
64+
await BugTriage(launchpadProject, launchpadConfig, references);
65+
await SpecificationTriage(launchpadProject, launchpadConfig, references);
6766
await SpecificationApprovals(launchpadProject);
6867

6968
var trello = new Trello.Cache(trelloConfig["key"], trelloConfig["token"]);
7069
var board = await trello.GetBoard(trelloConfig["board"]);
71-
await TrelloTriage(board, trelloConfig, commits);
70+
await TrelloTriage(board, trelloConfig, references);
7271
}
7372

7473
static string GetGitPath()
@@ -77,47 +76,43 @@ static string GetGitPath()
7776
return Path.Combine(Path.GetDirectoryName(appFilePath), "git");
7877
}
7978

80-
static async Task CommitTriage(List<Commit> commits, IConfigurationSection gitConfig, GitHub.Project gitHub)
79+
static async Task CommitTriage(Git.Project git, IConfigurationSection gitConfig, GitHub.Project gitHub, References references)
8180
{
8281
Console.WriteLine("Commit triage");
8382
Console.WriteLine("=============");
8483
Console.WriteLine();
8584

8685
var webUrlConfig = gitConfig.GetSection("webUrl");
8786
var exceptionalLabels = gitConfig.GetSection("references:exceptionalLabels").GetChildren().Select(item => item.Value);
88-
int.TryParse(gitConfig["references:minimumLines"], out var minimumLines);
87+
if (!int.TryParse(gitConfig["references:minimumLines"], out var minimumLines)) minimumLines = 0;
8988
var requiredLabels = gitConfig.GetSection("references:requiredLabels").GetChildren().Select(node => node.Value);
90-
var referencePattern = new Regex(gitConfig["references:references"]);
91-
foreach (var commit in commits)
89+
90+
foreach (var commit in git.GetLog(gitConfig["branch"], DateTimeOffset.Parse(gitConfig["startDate"])))
9291
{
93-
var data = await GetCommitDetails(gitHub, referencePattern, commit);
94-
commit.References.AddRange(data.References);
95-
foreach (var subCommit in commit.Commits)
96-
{
97-
var subData = await GetCommitDetails(gitHub, referencePattern, subCommit);
98-
commit.References.AddRange(subData.References);
99-
}
92+
references.Add(commit, out var referenceTypes);
10093

101-
if (data.PR != null)
94+
var pr = await gitHub.GetPullRequest(commit);
95+
var labels = pr?.Labels.Nodes.Select(n => n.Name) ?? Array.Empty<string>();
96+
if (pr != null)
10297
{
103-
if (data.PR.Labels.Nodes.Any(label => exceptionalLabels.Contains(label.Name))) continue;
104-
if (data.PR.Additions <= minimumLines && data.PR.Deletions <= minimumLines) continue;
98+
if (pr.Labels.Nodes.Any(label => exceptionalLabels.Contains(label.Name))) continue;
99+
if (pr.Additions <= minimumLines && pr.Deletions <= minimumLines) continue;
105100
}
106101

107102
var issues = new List<string>();
108103

109-
if (!requiredLabels.Any(label => data.Labels.Contains(label)))
104+
if (requiredLabels.Any() && !requiredLabels.Any(label => labels.Contains(label)))
110105
{
111106
issues.Add("Missing required labels");
112107
}
113-
if (data.References.Count() == 0)
108+
if (!IsValuePresentMissing(gitConfig.GetSection("references:types"), referenceTypes.ToArray()))
114109
{
115110
issues.Add("Missing required references");
116111
}
117112

118113
if (issues.Count > 0)
119114
{
120-
Console.WriteLine($"- [{commit.Summary}]({webUrlConfig["commit"].Replace("%KEY%", commit.Key)}) {string.Join(", ", data.Labels)} **at** {commit.AuthorDate} **by** {commit.AuthorName}");
115+
Console.WriteLine($"- [{commit.Summary}]({webUrlConfig["commit"].Replace("%KEY%", commit.Key)}) {string.Join(", ", labels)} **at** {commit.AuthorDate} **by** {commit.AuthorName}");
121116
foreach (var issue in issues)
122117
{
123118
Console.WriteLine($" - **Issue:** {issue}");
@@ -127,18 +122,7 @@ static async Task CommitTriage(List<Commit> commits, IConfigurationSection gitCo
127122
}
128123
}
129124

130-
static async Task<(GitHub.GraphPullRequest PR, IEnumerable<string> Labels, IEnumerable<string> References)> GetCommitDetails(GitHub.Project gitHub, Regex referencePattern, Commit commit)
131-
{
132-
var pr = await gitHub.GetPullRequest(commit);
133-
var message = pr != null ? pr.Title + "\n" + pr.Body : commit.Message;
134-
return (
135-
PR: pr,
136-
Labels: pr?.Labels.Nodes.Select(n => n.Name) ?? new string[0],
137-
References: referencePattern.Matches(message).Select(match => match.Value)
138-
);
139-
}
140-
141-
static async Task BugTriage(Launchpad.Project project, IConfigurationSection config, List<Commit> commits)
125+
static async Task BugTriage(Launchpad.Project project, IConfigurationSection config, References references)
142126
{
143127
Console.WriteLine("Bug triage");
144128
Console.WriteLine("==========");
@@ -167,6 +151,8 @@ static async Task BugTriage(Launchpad.Project project, IConfigurationSection con
167151
continue;
168152
}
169153

154+
references.Add(bug, out var _);
155+
170156
var issues = new List<string>();
171157

172158
var idealTitles = new List<string>();
@@ -263,14 +249,13 @@ static async Task BugTriage(Launchpad.Project project, IConfigurationSection con
263249
}
264250
}
265251

266-
var commitMentions = commits.Where(commit => commit.References.Contains(bugTask.Json.web_link));
267-
if (commitMentions.Any())
252+
if (references.TryGetValue(bugTask.Json.web_link, out var reference) && reference.GitCommits.Any())
268253
{
269254
if (bugTask.Status < Status.InProgress)
270255
{
271256
issues.Add("Code was committed but bug is not in progress or fixed");
272257
}
273-
var latestCommit = commitMentions.OrderBy(commit => commit.AuthorDate).Last();
258+
var latestCommit = reference.GitCommits.OrderBy(commit => commit.AuthorDate).Last();
274259
if ((DateTimeOffset.Now - latestCommit.AuthorDate).TotalDays > 28
275260
&& bugTask.Status < Status.FixCommitted)
276261
{
@@ -469,7 +454,7 @@ static SortedSet<string> GetBugIdealTags(IConfigurationSection config, string ti
469454
return tags;
470455
}
471456

472-
static async Task SpecificationTriage(Launchpad.Project project, IConfigurationSection config, List<Commit> commits)
457+
static async Task SpecificationTriage(Launchpad.Project project, IConfigurationSection config, References references)
473458
{
474459
Console.WriteLine("Specification triage");
475460
Console.WriteLine("====================");
@@ -539,8 +524,7 @@ static async Task SpecificationTriage(Launchpad.Project project, IConfigurationS
539524
{
540525
issues.Add("Implementation is completed but milestone is missing");
541526
}
542-
var commitMentions = commits.Where(commit => commit.References.Contains(specification.Json.web_link));
543-
if (commitMentions.Any())
527+
if (references.TryGetValue(specification.Json.web_link, out var reference) && reference.GitCommits.Any())
544528
{
545529
if (milestone != null
546530
&& milestone.Id != config["currentMilestone"])
@@ -552,7 +536,7 @@ static async Task SpecificationTriage(Launchpad.Project project, IConfigurationS
552536
{
553537
issues.Add("Code was committed but definition is not approved");
554538
}
555-
var latestCommit = commitMentions.OrderBy(commit => commit.AuthorDate).Last();
539+
var latestCommit = reference.GitCommits.OrderBy(commit => commit.AuthorDate).Last();
556540
if ((DateTimeOffset.Now - latestCommit.AuthorDate).TotalDays > 28
557541
&& specification.Implementation != Implementation.Implemented)
558542
{
@@ -602,10 +586,10 @@ static async Task SpecificationApprovals(Launchpad.Project project)
602586
}
603587
}
604588

605-
static async Task TrelloTriage(Trello.Board board, IConfigurationSection config, List<Commit> commits)
589+
static async Task TrelloTriage(Trello.Board board, IConfigurationSection config, References references)
606590
{
607-
Console.WriteLine("Roadmap triage");
608-
Console.WriteLine("==============");
591+
Console.WriteLine("Trello triage");
592+
Console.WriteLine("=============");
609593
Console.WriteLine();
610594

611595
var lists = Filter(await board.GetLists(), list => list.Name, config["includeLists"], config["excludeLists"]);
@@ -696,7 +680,7 @@ static async Task TrelloTriage(Trello.Board board, IConfigurationSection config,
696680
var complete = checklist.Items.Find(item => item.Name == orderName)?.Complete;
697681
// "https://trello.com/c/JGosmRnZ/159-consist-editor" --> "https://trello.com/c/JGosmRnZ"
698682
var url = string.Join("/", card.Uri.ToString().Split('/').Take(5));
699-
var expectedComplete = commits.Any(commit => commit.References.Contains(url));
683+
var expectedComplete = references.TryGetValue(url, out var reference) && reference.GitCommits.Any();
700684
if (complete != expectedComplete)
701685
{
702686
Console.WriteLine($" - [{card.Name}]({card.Uri}): {checklistConfig.Key} checklist item {orderName} is {complete}; expected {expectedComplete}");

References.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Text.RegularExpressions;
4+
5+
namespace Open_Rails_Triage
6+
{
7+
class References : Dictionary<string, Reference>
8+
{
9+
public static readonly Regex ReferencesPattern = new("(https://bugs\\.launchpad\\.net/[^/]+/\\+bug/[0-9]+|https://blueprints\\.launchpad\\.net/[^/]+/\\+spec/[0-9a-z-]+|https://trello\\.com/c/[0-9a-zA-Z]+)");
10+
11+
public static string GetReferenceType(string reference) => reference switch
12+
{
13+
string a when a.Contains("//bugs.launchpad.net/") => "launchpad-bug",
14+
string a when a.Contains("//blueprints.launchpad.net/") => "launchpad-blueprint",
15+
string a when a.Contains("//trello.com/c/") => "trello-card",
16+
_ => "unknown"
17+
};
18+
19+
public void Add(Git.Commit commit, out HashSet<string> types)
20+
{
21+
types = new();
22+
foreach (var match in commit.Commits.Select(commit => ReferencesPattern.Matches(commit.Message)).Append(ReferencesPattern.Matches(commit.Message)).SelectMany(match => match).Select(match => match.Value))
23+
{
24+
types.Add(GetReferenceType(match));
25+
GetReference(match).GitCommits.Add(commit);
26+
}
27+
}
28+
29+
public void Add(Launchpad.Bug bug, out HashSet<string> types)
30+
{
31+
types = new();
32+
foreach (var match in ReferencesPattern.Matches(bug.Description).Select(match => match.Value))
33+
{
34+
types.Add(GetReferenceType(match));
35+
GetReference(match).LaunchpadBugs.Add(bug);
36+
}
37+
}
38+
39+
Reference GetReference(string key)
40+
{
41+
if (!ContainsKey(key)) this[key] = new();
42+
return this[key];
43+
}
44+
}
45+
46+
class Reference
47+
{
48+
public List<Git.Commit> GitCommits { get; } = new();
49+
public List<Launchpad.Bug> LaunchpadBugs { get; } = new();
50+
}
51+
}

config.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
"2": "enhancement",
2020
"3": "refactoring"
2121
},
22-
"references": "(https://bugs\\.launchpad\\.net/or/\\+bug/[0-9]+|https://blueprints\\.launchpad\\.net/or/\\+spec/[0-9a-z-]+|https://trello\\.com/c/[0-9a-zA-Z]+)"
22+
"types": {
23+
"anyPresent": "launchpad-bug trello-card launchpad-blueprint"
24+
}
2325
}
2426
},
2527
"github": {

0 commit comments

Comments
 (0)