public static async Task DoWork(RebaseCommandSettings settings, CommonSettings commonSettings, Parameters parameters, Jira jira) { var prUrl = parameters.Get("PR url: "); GithubHelper.ParsePrUrl(prUrl, out var repoName, out var prNumber); Console.Write("Getting PR... "); var query = @"query { repository(owner:""trilogy-group"", name:""" + repoName + @"""){ pullRequest(number: " + prNumber + @"){ headRefName } } }"; var repoData = await GithubHelper.Query(query, commonSettings.GithubToken); var branchName = repoData["repository"]["pullRequest"]["headRefName"].Value <string>(); Console.WriteLine("done"); var repoSettings = SettingsHelper.GetRepoSettings(commonSettings, repoName); var mainBranch = SettingsHelper.GetMainBranch(repoSettings); Console.Write($"Rebase {mainBranch} to {branchName}... "); GitHelper.Exec( $"git checkout {mainBranch} && git pull && git checkout {branchName} && git pull && git merge develop --no-edit && git push", repoSettings, commonSettings.ProjectsPath); Console.WriteLine("done"); Console.Write($"Checkout {mainBranch}... "); GitHelper.Exec($"git checkout {mainBranch}", repoSettings, commonSettings.ProjectsPath); Console.WriteLine("done"); }
public static async Task DoWork(CrnCommandSettings settings, CommonSettings commonSettings, Parameters parameters, Jira jira) { throw new CcException("Crn command isn't implemented yet"); var prUrl = parameters.GetPrUrl(); GithubHelper.ParsePrUrl(prUrl, out var repoName, out var prNumber); Console.Write("Getting PR... "); var query = @"query { repository(owner:""trilogy-group"", name:""" + repoName + @"""){ pullRequest(number: " + prNumber + @"){ headRefName } } }"; var repoData = await GithubHelper.Query(query, commonSettings.GithubToken); var branchName = repoData["repository"]["pullRequest"]["headRefName"].Value <string>(); Console.WriteLine("done"); //Console.Write($"Checkout branch {branchName}... "); //GitHelper.Exec($"git checkout {branchName}", repoName, commonSettings.ProjectsPath); //Console.WriteLine("done"); }
private static async Task AssignLabelToPR(CommonSettings commonSettings, string repoName, string reviewLabel, JToken jPullRequest) { Console.Write("Get CRN review label id... "); var getRepoLabels = string.Format(QueryGetRepoLabelsFormat, "trilogy-group", repoName); var repoLabels = await GithubHelper.Query(getRepoLabels, commonSettings.GithubToken); var repoLabelsNode = repoLabels["repository"]["labels"]["nodes"] as JArray; var prId = jPullRequest["id"].Value <string>(); if (repoLabelsNode == null) { Console.Write("No labels found in repo"); return; } if (!repoLabelsNode.Any( x => x["name"].Value <string>().Equals(reviewLabel, StringComparison.OrdinalIgnoreCase))) { Console.Write("No review label found in repo"); return; } var crnReviewLabelId = repoLabelsNode.First( x => x["name"].Value <string>().Equals(reviewLabel, StringComparison.OrdinalIgnoreCase)) ["id"] .Value <string>(); Console.WriteLine("done"); var labelNodes = jPullRequest["labels"]["nodes"] as JArray ?? new JArray(); if (labelNodes.Any()) { if (labelNodes.Any(x => x["id"].Value <string>().Equals(crnReviewLabelId))) { Console.Write($@"""{reviewLabel}"" already assigned... "); Console.WriteLine("done"); return; } Console.Write("Clear labels... "); var mutationClearLabels = string.Format(MutationClearLabelsPRFormat, prId); await GithubHelper.Query(mutationClearLabels, commonSettings.GithubToken); Console.WriteLine("done"); } Console.Write("Add label... "); var mutationAddLabels = string.Format(MutationAddLabelsFormat, prId, crnReviewLabelId); await GithubHelper.Query(mutationAddLabels, commonSettings.GithubToken); Console.WriteLine("done"); }
public static async Task DoWork(PrCommandSettings settings, CommonSettings commonSettings, Parameters parameters, Jira jira) { var ticketUrl = parameters.Get("Enter Jira ticket: "); var issueKey = JiraHelper.GetIssueKey(ticketUrl); var comment = GetComment(settings, parameters); var noteForReviewer = parameters.Get("Note for reviewer: "); if (settings.NotesAliases.ContainsKey(noteForReviewer)) { noteForReviewer = settings.NotesAliases[noteForReviewer]; } bool isOnlyPr = false; if (parameters.Any()) { var str = parameters.Get(string.Empty); if (str == "--onlyPr") { isOnlyPr = true; } else { throw new CcException($"Unknown argument: {str}"); } } Console.Write("Get ticket... "); var issue = await jira.Issues.GetIssueAsync(issueKey); var repoUrl = issue.GetScmUrl(); if (string.IsNullOrWhiteSpace(repoUrl)) { Console.WriteLine("Can't get repo name"); return; } Console.WriteLine("done"); var repoName = repoUrl.Split('/')[4]; if (repoName.EndsWith(".git", StringComparison.OrdinalIgnoreCase)) { repoName = Path.GetFileNameWithoutExtension(repoName); } var repoSettings = SettingsHelper.GetRepoSettings(commonSettings, repoName); var branchPrefix = string.IsNullOrWhiteSpace(repoSettings?.BranchPrefix) ? "feature" : repoSettings.BranchPrefix; var mainBranch = SettingsHelper.GetMainBranch(repoSettings); var key = issue.Key.ToString(); var ticketType = GetTicketType(issue); if (!isOnlyPr) { var stagedFiles = GitHelper.Exec("git diff --name-only --cached", repoSettings, commonSettings.ProjectsPath); var changedFiles = GitHelper.Exec("git diff --name-only", repoSettings, commonSettings.ProjectsPath); if (!stagedFiles.Any() && !changedFiles.Any()) { throw new CcException("No changed files found"); } var filesForCheck = stagedFiles.Any() ? stagedFiles : changedFiles; if (filesForCheck.Any(f => f.EndsWith(".sln", StringComparison.OrdinalIgnoreCase))) { ConsoleHelper.WriteColor("You are going to commit changes in sln-file. Do you really want to do it? [y/N]: ", ConsoleColor.Yellow); var answer = Console.ReadLine() ?? string.Empty; if (!answer.Equals("y", StringComparison.OrdinalIgnoreCase)) { return; } } var currentBranch = GitHelper.GetCurrentBranch(repoSettings, commonSettings.ProjectsPath); if (currentBranch != mainBranch) { ConsoleHelper.WriteColor( $"Your current branch is {currentBranch}, but usually it should be {mainBranch}. Do you really want to create new branch from this one? [y/N]: ", ConsoleColor.Yellow); var answer = Console.ReadLine() ?? string.Empty; if (!answer.Equals("y", StringComparison.OrdinalIgnoreCase)) { return; } } Console.Write("Set assignee... "); if (issue.Assignee == null) { issue.Assignee = commonSettings.JiraUserName; await issue.SaveChangesAsync(); Console.WriteLine("done"); } else { if (issue.Assignee != commonSettings.JiraUserName) { throw new CcException($"Ticket is already assigned to \"{issue.Assignee}\"!"); } else { Console.WriteLine("already assigned"); } } Console.Write("Move ticket to \"In progress\"... "); if (issue.Status.ToString().Equals("To Do", StringComparison.InvariantCultureIgnoreCase)) { await issue.WorkflowTransitionAsync("Not False Positive"); } if (issue.Status.ToString().Equals("Writing Test Code", StringComparison.InvariantCultureIgnoreCase)) { await issue.WorkflowTransitionAsync("Test coverage available"); } if (issue.Status.ToString().Equals("Ready to refactor", StringComparison.InvariantCultureIgnoreCase)) { await issue.WorkflowTransitionAsync("Start progress"); } Console.WriteLine("done"); Console.Write("Push changes... "); var createBranchCommand = $"git checkout -b {branchPrefix}/{key}"; var commitOption = stagedFiles.Any() ? string.Empty : "a"; var commitCommand = $"git commit -{commitOption}m \"{key}: Fixes {ticketType}\""; var pushCommand = $"git push --set-upstream origin {branchPrefix}/{key}"; GitHelper.Exec( $"{createBranchCommand} && {commitCommand} && {pushCommand}", repoSettings, commonSettings.ProjectsPath); Console.WriteLine("done"); Console.Write($"Checkout {mainBranch}... "); try { GitHelper.Exec($"git checkout {mainBranch} && git pull", repoSettings, commonSettings.ProjectsPath); Console.WriteLine("done"); } catch (GitException) { ConsoleHelper.WriteLineColor("failed", ConsoleColor.Yellow); } Console.Write("Waiting... "); Thread.Sleep(TimeSpan.FromSeconds(3)); Console.WriteLine("done"); } Console.Write("Create PR... "); var query = @"query { repository(owner:""trilogy-group"", name:""" + repoName + @"""){ id }}"; var repoData = await GithubHelper.Query(query, commonSettings.GithubToken); var repoId = repoData["repository"]["id"].Value <string>(); var fullNote = string.IsNullOrWhiteSpace(noteForReviewer) ? string.Empty : $@"# Note for Reviewers\r\n- {noteForReviewer}\r\n\r\n"; var(testCoverageMessage, coverageWarning) = GetTestCoverageMessage(issue); var mutation = @"mutation { createPullRequest(input:{ title:""[" + key + "] " + issue.Summary.Replace("\"", "\\\"") + @""", baseRefName: """ + mainBranch + @""", body: ""# Links\r\nhttps://jira.devfactory.com/browse/" + key + @"\r\n\r\n# Changes\r\n- " + comment + @"\r\n\r\n" + fullNote + testCoverageMessage + @""", headRefName: """ + branchPrefix + "/" + key + @""", repositoryId: """ + repoId + @""" }){ pullRequest{ id, url } } }"; var resultJson = await GithubHelper.Query(mutation, commonSettings.GithubToken); var jPullRequest = resultJson["createPullRequest"]["pullRequest"]; var prUrl = jPullRequest["url"].Value <string>(); Console.WriteLine("done"); if (coverageWarning) { Console.WriteLine("Please don't forget to fill test coverage manually"); } if (settings.AssignPr) { Console.Write("Assign PR... "); var prId = jPullRequest["id"].Value <string>(); var currentUserIdJson = await GithubHelper.Query("query {viewer {id}}", commonSettings.GithubToken); var userId = currentUserIdJson["viewer"]["id"].Value <string>(); var assignPrMutation = @"mutation { addAssigneesToAssignable(input: { assignableId: """ + prId + @""", assigneeIds: [""" + userId + @"""]}) { clientMutationId }}"; await GithubHelper.Query(assignPrMutation, commonSettings.GithubToken); Console.WriteLine("done"); } Console.Write("Write PR url to ticket... "); const string codeReviewUrl = "Code Review Ticket URL"; if (issue.CustomFields.Any(f => f.Name == codeReviewUrl)) { issue.CustomFields[codeReviewUrl].Values = new [] { prUrl }; } else { issue.CustomFields.Add(codeReviewUrl, prUrl); } issue.SaveChanges(); Console.WriteLine("done"); Console.WriteLine("New PR url: " + prUrl); }
private async Task <bool> ReviewPr(string qbLink, bool approve, IReadOnlyCollection <string> failedItems) { // Get user login var loginQuery = @"query { viewer { login }}"; var loginData = await GithubHelper.Query(loginQuery, _settings.GithubToken); var login = loginData["viewer"]["login"].Value <string>(); // Get pending review var pendingReviewQuery = @"query q { repository(owner:""" + _prInfo.OwnerName + @""", name:""" + _prInfo.RepoName + @""") { pullRequest(number: " + _prInfo.PrNumber + @") { id reviews(last: 20, author: """ + login + @""") { nodes{ id state } } } } }"; var pendingReviewData = await GithubHelper.Query(pendingReviewQuery, _settings.GithubToken); var pendingReviews = pendingReviewData["repository"]["pullRequest"]["reviews"]["nodes"] as JArray; var pendingReview = pendingReviews?.FirstOrDefault(r => r["state"].Value <string>() == "PENDING"); string reviewId; if (pendingReview == null) { var prId = pendingReviewData["repository"]["pullRequest"]["id"].Value <string>(); var addReviewMutation = @"mutation w{ addPullRequestReview(input: {pullRequestId: """ + prId + @"""}) { pullRequestReview {id} } }"; var reviewData = await GithubHelper.Query(addReviewMutation, _settings.GithubToken); reviewId = reviewData["addPullRequestReview"]["pullRequestReview"]["id"].Value <string>(); } else { reviewId = pendingReview["id"].Value <string>(); } string reviewBody; string reviewEvent; if (approve) { if (_settings.ApprovePrAction == "approve") { reviewBody = $"body: \"QB: {qbLink}\""; reviewEvent = "APPROVE"; } else { reviewBody = $"body: \"Approved\\r\\nQB: {qbLink}\""; reviewEvent = "COMMENT"; } } else { reviewEvent = "REQUEST_CHANGES"; var failedItemsText = string.Join("\\r\\n", failedItems.Select(i => $"**{i}**")); reviewBody = $"body: \"{failedItemsText}\\r\\nQB: {qbLink}\""; } var submitReviewMutation = @"mutation e { submitPullRequestReview(input: { " + reviewBody + @" pullRequestReviewId: """ + reviewId + @""", event: " + reviewEvent + @"}) { clientMutationId } }"; var submitData = await GithubHelper.Query(submitReviewMutation, _settings.GithubToken); return(submitData["submitPullRequestReview"]["clientMutationId"] != null); }
public static async Task DoWork(ReviewCommandSettings settings, CommonSettings commonSettings, Parameters parameters, Jira jira) { var prUrl = parameters.Get("PR url: "); GithubHelper.ParsePrUrl(prUrl, out var repoName, out var prNumber); var timeSpent = parameters.Get("Time spent: "); if (string.IsNullOrWhiteSpace(timeSpent) || timeSpent.Trim() == "0") { throw new CcException("Time spent should not be empty"); } //var coverage = parameters.Get("Coverage percentage: "); //if (string.IsNullOrWhiteSpace(coverage)) //{ // throw new CcException("Coverage should not be empty"); //} Console.Write("Getting PR... "); var prDetails = string.Format(QueryGetPRDetailsFormat, repoName, prNumber); var prInfo = await GithubHelper.Query(prDetails, commonSettings.GithubToken); var jPullRequest = prInfo["repository"]["pullRequest"]; var bodyHtml = jPullRequest["bodyHTML"].Value <string>(); Console.WriteLine("done"); Console.Write("Getting ticket... "); var regex = new Regex(@"https://jira\.devfactory\.com/browse/(CC-\d+)"); var m = regex.Match(bodyHtml); if (!m.Success) { throw new CcException("Ticket not found"); } var issue = await jira.Issues.GetIssueAsync(m.Groups[1].Value); Console.WriteLine("done"); var issueStatus = issue.Status.ToString(); if (!issueStatus.Equals("In progress", StringComparison.InvariantCultureIgnoreCase)) { throw new CcException("Ticket should be in \"In progress\" state"); } var repoSettings = SettingsHelper.GetRepoSettings(commonSettings, repoName); if (string.IsNullOrWhiteSpace(repoSettings?.Pca)) { throw new CcException($"PCA isn't defined for repo \"{repoName}\" in settings.json"); } Console.Write("Moving to review... "); SetCustomField(issue, "Reviewer", repoSettings.Pca); SetCustomField(issue, "Code Review Ticket URL", prUrl); await issue.WorkflowTransitionAsync("Submit for Review", new WorkflowTransitionUpdates() { TimeSpent = timeSpent }); Console.WriteLine("done"); if (settings.AssignPr) { Console.Write("Assigning PR... "); var currentUserIdJson = await GithubHelper.Query("query {viewer {id}}", commonSettings.GithubToken); var userId = currentUserIdJson["viewer"]["id"].Value <string>(); var nodes = jPullRequest["assignees"]["nodes"] as JArray ?? new JArray(); if (nodes.Any(node => node["id"].Value <string>() == userId)) { Console.WriteLine("already assigned"); } else { var assignPrMutation = string.Format(MutationAddAssigneePRFormat, jPullRequest["id"].Value <string>(), userId); await GithubHelper.Query(assignPrMutation, commonSettings.GithubToken); Console.WriteLine("done"); } } if (settings.AssignReviewLabel) { await AssignLabelToPR(commonSettings, repoName, settings.ReviewLabelName, jPullRequest); } }