public static async IAsyncEnumerable <(string repo, string label, string original)> MatchNodes(this HttpClient github, LabelEditedPayload payload) { var count = 0; var id = payload.RepositoryId; var limit = payload.Limit; var oldName = payload.ChangedNameFrom; var newName = payload.LabelName; var search = $"{newName} {oldName}"; var privacy = payload.IgnorePrivate ? ", privacy: PUBLIC" : string.Empty; var suffix = $", ownerAffiliations: OWNER{privacy}) {{ pageInfo {{ endCursor hasNextPage }} nodes {{ databaseId name labels(first: 10, query: \\\"{search}\\\") {{ nodes {{ name color description }} }} }} }} }} }}\"}}"; var query = $"{{\"query\":\"{{ viewer {{ repositories(first: {Math.Min(GitHubApi.MAX_ITEMS_PER_TRANSACTION, limit)}" + suffix; bool hasNextPage; var promise = github.GraphQL(query); do { // Wait for results JObject data = await promise; var repos = data[DATA][VIEWER][REPOSITORIES]; var page = repos[PAGEINFO]; hasNextPage = page[HASNEXTPAGE].Value <bool>(); // If more data is available request it now if (hasNextPage) { query = $"{{\"query\":\"{{ viewer {{ repositories(first: {GitHubApi.MAX_ITEMS_PER_TRANSACTION}, after: \\\"{page["endCursor"].Value<string>()}\\\"" + suffix; promise = github.GraphQL(query); } // Yield label info for each matching repository foreach (var node in repos[NODES]) { // Skip source repository if (node[DATABASEID].Value <long>() == id) { continue; } // Scan and initialize found labels JToken source = null; JToken target = null; foreach (var label in node[LABELS][NODES]) { var name = label[NAME].Value <string>(); if (name == newName) { target = label; } if (name == oldName) { source = label; } } var tuple = ( repo : node[NAME].Value <string>(), label : null as string, original : null as string ); // Assign found labels if (null != source && null != target) { tuple.label = target.Value <string>(); tuple.original = source[NAME].Value <string>(); } else if (null != source) { tuple.label = source[NAME].Value <string>(); } else if (null != target) { tuple.label = target[NAME].Value <string>(); } yield return(tuple); if (limit < ++count) { yield break; } } }while (hasNextPage); }
static async Task HandleLabelEditedEvent(this HttpClient github, LabelEditedPayload payload, ILogger log) { var count = 0; var owner = payload.OwnerLogin; var name = payload.LabelName; var color = payload.LabelColor; var changedName = payload.ChangedName; var description = payload.LabelDescription; log.LogInformation($"Updating label '{name}' in '{owner}' initiated by '{payload.SenderLogin}'"); // When label is renamed, it requires checks for new and old // name so it is split in two possible cases here if (null != changedName && changedName.HasValues) { // Process changes in the name await foreach (var node in github.MatchNodes(payload)) { if (null != node.original) { // This is the case where both, the new label, and the old are present // We need to delete one modify the other var method = $"/repos/{owner}/{node.repo}/labels/{node.original}"; (await github.DeleteAsync(method)).EnsureSuccessStatusCode(); } if (null != node.label) { // Update existing label var content = new StringContent($"{{ \"new_name\": \"{name}\", \"description\": \"{description}\", \"color\": \"{color}\" }} "); (await github.PatchAsync($"/repos/{owner}/{node.repo}/labels/{node.label}", content)) .EnsureSuccessStatusCode(); count += 1; } else { // Create label var content = new StringContent($"{{ \"name\": \"{node.label}\", \"description\": \"{description}\", \"color\": \"{color}\" }} "); (await github.PostAsync($"/repos/{owner}/{node.repo}/labels", content)) .EnsureSuccessStatusCode(); count += 1; } } } else { // Process changes in color or description await foreach (var node in github.GetNodes(payload)) { var repo = node[GitHubApi.NAME].Value <string>(); var content = new StringContent($"{{ \"name\": \"{name}\", \"description\": \"{description}\", \"color\": \"{color}\" }} "); var label = node[GitHubApi.LABEL]; if (null != label && label.HasValues) { // Update existing label (await github.PatchAsync($"/repos/{owner}/{repo}/labels/{name}", content)) .EnsureSuccessStatusCode(); count += 1; } else { // Create label (await github.PostAsync($"/repos/{owner}/{repo}/labels", content)) .EnsureSuccessStatusCode(); count += 1; } } } var message = $"Successfully updated in {count} repositories"; log.LogInformation(message); }