/// <summary> /// Label a pull request /// </summary> /// <param name="payload">The <see cref="PullRequestEventPayload"/> for the pull request</param> /// <param name="oneCheckTags"><see langword="true"/> if additional tags should be contionally applied, <see langword="false"/> otherwise</param> /// <returns>A <see cref="Task"/> representing the running operation</returns> async Task TagPR(PullRequestEventPayload payload, bool oneCheckTags) { async Task <bool?> MergeableCheck() { //check if the PR is mergeable, if not, don't tag it bool?mergeable = payload.PullRequest.Mergeable; for (var I = 0; !mergeable.HasValue && I < 3; ++I) { await Task.Delay(I * 1000).ConfigureAwait(false); mergeable = (await gitHubManager.GetPullRequest(payload.PullRequest.Number).ConfigureAwait(false)).Mergeable; } return(mergeable); }; var mergeableTask = MergeableCheck().ConfigureAwait(false); var filesChanged = gitHubManager.GetPullRequestChangedFiles(payload.PullRequest.Number).ConfigureAwait(false); var currentLabelsTask = gitHubManager.GetIssueLabels(payload.PullRequest.Number).ConfigureAwait(false); var labelsToAdd = new List <string>(); var labelsToRemove = new List <string>(); var lowerTitle = payload.PullRequest.Title.ToLower(CultureInfo.CurrentCulture); if (lowerTitle.Contains("refactor")) { labelsToAdd.Add("Refactor"); } if (lowerTitle.Contains("[dnm]")) { labelsToAdd.Add("Do Not Merge"); } if (lowerTitle.Contains("[wip]")) { labelsToAdd.Add("Work In Progress"); } if (lowerTitle.Contains("revert")) { labelsToAdd.Add("Revert"); } if (lowerTitle.Contains("removes")) { labelsToAdd.Add("Removal"); } var mergeableCheck = await mergeableTask; if (mergeableCheck.HasValue) { if (!mergeableCheck.Value) { labelsToAdd.Add("Merge Conflict"); } else { labelsToRemove.Add("Merge Conflict"); } } var treeToLabelMappings = new Dictionary <string, string> { { "_maps", "Map Edit" }, { "tools", "Tools" }, { "SQL", "SQL" }, { ".github", "GitHub" } }; var addOnlyTreeToLabelMappings = new Dictionary <string, string> { { "icons", "Sprites" }, { "sound", "Sounds" }, { "config", "Config Update" }, { "code/controllers/configuration/entries", "Config Update" }, { "tgui", "UI" } }; foreach (var I in await filesChanged) { foreach (var J in treeToLabelMappings) { if (I.FileName.StartsWith(J.Key, StringComparison.CurrentCulture)) { labelsToAdd.Add(J.Value); } else { labelsToRemove.Add(J.Value); } } if (oneCheckTags) { foreach (var J in addOnlyTreeToLabelMappings) { if (I.FileName.StartsWith(J.Key, StringComparison.CurrentCulture)) { labelsToAdd.Add(J.Value); } } } } void UniqueAdd(string label) { if (!labelsToAdd.Contains(label)) { labelsToAdd.Add(label); } } //github close syntax (without "close" variants) if (Regex.IsMatch(payload.PullRequest.Body, "(?i)(fix|fixes|fixed|resolve|resolves|resolved)\\s*#[1-9][0-9]*")) { UniqueAdd("Fix"); } //run through the changelog var changelog = Changelog.GetChangelog(payload.PullRequest, out bool malformed); if (changelog != null) { foreach (var I in changelog.Changes.Select(x => x.Type)) { switch (I) { case ChangelogEntryType.Admin: UniqueAdd("Administration"); break; case ChangelogEntryType.Balance: UniqueAdd("Balance/Rebalance"); break; case ChangelogEntryType.BugFix: UniqueAdd("Fix"); break; case ChangelogEntryType.Code_Imp: UniqueAdd("Code Improvement"); break; case ChangelogEntryType.Config: UniqueAdd("Config Update"); break; case ChangelogEntryType.ImageAdd: UniqueAdd("Sprites"); break; case ChangelogEntryType.ImageDel: UniqueAdd("Sprites"); UniqueAdd("Removal"); break; case ChangelogEntryType.Refactor: UniqueAdd("Refactor"); break; case ChangelogEntryType.RscAdd: UniqueAdd("Feature"); break; case ChangelogEntryType.RscDel: UniqueAdd("Removal"); break; case ChangelogEntryType.SoundAdd: UniqueAdd("Sounds"); break; case ChangelogEntryType.SoundDel: UniqueAdd("Sounds"); UniqueAdd("Removal"); break; case ChangelogEntryType.SpellCheck: UniqueAdd("Grammar and Formatting"); break; case ChangelogEntryType.Tweak: UniqueAdd("Tweak"); break; } } } labelsToAdd.RemoveAll(x => labelsToRemove.Contains(x)); var newLabels = new List <string>(); foreach (var I in labelsToAdd) { newLabels.Add(I); } var currentLabels = new List <Label>(await currentLabelsTask); currentLabels.RemoveAll(x => labelsToRemove.Contains(x.Name) || labelsToAdd.Contains(x.Name)); foreach (var I in currentLabels) { newLabels.Add(I.Name); } await gitHubManager.SetIssueLabels(payload.PullRequest.Number, newLabels).ConfigureAwait(false); }