/// <summary> /// Creates a Pull Request. /// </summary> /// <param name="appConfig">The application configuration object which contains values /// for connecting to the specified GitHub repository.</param> /// <param name="privateKey">The RSA private key of a registered GitHub app installed in the specified repository.</param> /// <returns>A task.</returns> public static async Task CreatePullRequestAsync(ApplicationConfig appConfig, string privateKey) { if (appConfig == null) { throw new ArgumentNullException(nameof(appConfig), "Parameter cannot be null"); } if (string.IsNullOrEmpty(privateKey)) { throw new ArgumentNullException(nameof(privateKey), "Parameter cannot be null or empty"); } var gitHubClient = GitHubClientFactory.GetGitHubClient(appConfig, privateKey); // Create a PR // NB: If the PR already exists, this call will just throw an exception var pullRequest = await gitHubClient.Repository.PullRequest.Create(appConfig.GitHubOrganization, appConfig.GitHubRepoName, new NewPullRequest(appConfig.PullRequestTitle, appConfig.WorkingBranch, appConfig.ReferenceBranch) { Body = appConfig.PullRequestBody }); // Add PR reviewers if (appConfig.Reviewers != null) { var reviewersResult = await gitHubClient.Repository.PullRequest.ReviewRequest.Create(appConfig.GitHubOrganization, appConfig.GitHubRepoName, pullRequest.Number, new PullRequestReviewRequest(appConfig.Reviewers.AsReadOnly(), null)); } var issueUpdate = new IssueUpdate(); // Add PR assignee appConfig.PullRequestAssignees?.ForEach(assignee => issueUpdate.AddAssignee(assignee)); // Add PR label appConfig.PullRequestLabels?.ForEach(label => issueUpdate.AddLabel(label)); // Update the PR with the relevant info. if (issueUpdate.Assignees?.Count > 0 || issueUpdate.Labels?.Count > 0) { await gitHubClient.Issue.Update(appConfig.GitHubOrganization, appConfig.GitHubRepoName, pullRequest.Number, issueUpdate); } }
public async Task CanGetWithAssigneesForRepositoryWithRepositoryId() { await CreateTheWorld(); var newPullRequest = new NewPullRequest("a pull request", branchName, "master"); var result = await _fixture.Create(_context.Repository.Id, newPullRequest); // Add an assignee var issueUpdate = new IssueUpdate(); issueUpdate.AddAssignee(Helper.UserName); await _github.Issue.Update(_context.Repository.Id, result.Number, issueUpdate); // Retrieve the Pull Requests var pullRequests = await _fixture.GetAllForRepository(_context.Repository.Id); Assert.Equal(1, pullRequests.Count); Assert.Equal(result.Title, pullRequests[0].Title); Assert.Equal(Helper.UserName, pullRequests[0].Assignee.Login); Assert.Equal(1, pullRequests[0].Assignees.Count); Assert.Contains(pullRequests[0].Assignees, x => x.Login == Helper.UserName); }
private void CreatePullRequest(Repository repo, GitHubClient gitHubClient, Remote origin, string branch) { // Oktokit is async-heavy, but we don't want to make ICommand asynchronous just for that. CreatePullRequestAsync().GetAwaiter().GetResult(); async Task CreatePullRequestAsync() { string user = origin.Url.Substring("https://github.com/".Length).Split('/').First(); string head = $"{user}:{branch}"; var commitMessage = repo.Commits.First().Message; var commitMessageLines = commitMessage.Replace("\r", "").Split('\n').ToList(); var pullRequestLines = UnwrapLines(commitMessageLines); var request = new NewPullRequest(pullRequestLines.First(), head, "main") { Body = string.Join('\n', pullRequestLines.Skip(1)) }; var pullRequest = await gitHubClient.PullRequest.Create(RepositoryOwner, RepositoryName, request); // Note: using a collection initializer looks reasonable, but fails with an NRE, because the Labels // property is lazily initialized :( var issueUpdate = new IssueUpdate(); issueUpdate.AddLabel(AutoreleasePendingLabel); issueUpdate.AddLabel(AutomergeExactLabel); string assignee = Environment.GetEnvironmentVariable(AssigneeEnvironmentVariable); if (!string.IsNullOrEmpty(assignee)) { issueUpdate.AddAssignee(assignee); } await gitHubClient.Issue.Update(RepositoryOwner, RepositoryName, pullRequest.Number, issueUpdate); // The PR link is useful to be able to click on, and occasionally the release branch is useful. Console.WriteLine($"Created branch {branch} and PR {pullRequest.HtmlUrl}"); } }
public async Task WriteToRepositoryAsync(ApplicationConfig appConfig, string privateKey) { if (appConfig == null) { throw new ArgumentNullException(nameof(appConfig), "Parameter cannot be null"); } try { string token = await GitHubAuthService.GetGithubAppTokenAsync(appConfig, privateKey); // Pass the JWT as a Bearer token to Octokit.net var finalClient = new GitHubClient(new ProductHeaderValue(appConfig.GitHubAppName)) { Credentials = new Credentials(token, AuthenticationType.Bearer) }; // Get repo references var references = await finalClient.Git.Reference.GetAll(appConfig.GitHubOrganization, appConfig.GitHubRepoName); // Check if the working branch is in the refs var workingBranch = references.Where(reference => reference.Ref == $"refs/heads/{appConfig.WorkingBranch}").FirstOrDefault(); // Check if branch already exists. if (workingBranch == null) { // Working branch does not exist so branch off reference branch var refBranch = references.Where(reference => reference.Ref == $"refs/heads/{appConfig.ReferenceBranch}").FirstOrDefault(); // Exception will throw if branch already exists var newBranch = await finalClient.Git.Reference.Create(appConfig.GitHubOrganization, appConfig.GitHubRepoName, new NewReference($"refs/heads/{appConfig.WorkingBranch}", refBranch.Object.Sha)); // create file var createChangeSet = await finalClient.Repository.Content.CreateFile( appConfig.GitHubOrganization, appConfig.GitHubRepoName, appConfig.FileContentPath, new CreateFileRequest(appConfig.CommitMessage, appConfig.FileContent, appConfig.WorkingBranch)); } else { // Get reference of the working branch var masterReference = await finalClient.Git.Reference.Get(appConfig.GitHubOrganization, appConfig.GitHubRepoName, workingBranch.Ref); // Get the latest commit of this branch var latestCommit = await finalClient.Git.Commit.Get(appConfig.GitHubOrganization, appConfig.GitHubRepoName, masterReference.Object.Sha); // Create blob NewBlob blob = new NewBlob { Encoding = EncodingType.Utf8, Content = appConfig.FileContent }; BlobReference blobRef = await finalClient.Git.Blob.Create(appConfig.GitHubOrganization, appConfig.GitHubRepoName, blob); // Create new Tree var tree = new NewTree { BaseTree = latestCommit.Tree.Sha }; // Add items based on blobs tree.Tree.Add(new NewTreeItem { Path = appConfig.FileContentPath, Mode = appConfig.TreeItemMode.ToString(), Type = TreeType.Blob, Sha = blobRef.Sha }); var newTree = await finalClient.Git.Tree.Create(appConfig.GitHubOrganization, appConfig.GitHubRepoName, tree); // Create commit var newCommit = new NewCommit(appConfig.CommitMessage, newTree.Sha, masterReference.Object.Sha); var commit = await finalClient.Git.Commit.Create(appConfig.GitHubOrganization, appConfig.GitHubRepoName, newCommit); // Push the commit await finalClient.Git.Reference.Update(appConfig.GitHubOrganization, appConfig.GitHubRepoName, workingBranch.Ref, new ReferenceUpdate(commit.Sha)); } // Create PR var pullRequest = await finalClient.Repository.PullRequest.Create(appConfig.GitHubOrganization, appConfig.GitHubAppName, new NewPullRequest(appConfig.PullRequestTitle, appConfig.WorkingBranch, appConfig.ReferenceBranch) { Body = appConfig.PullRequestBody }); // Add reviewers var teamMembers = appConfig.Reviewers; var reviewersResult = await finalClient.Repository.PullRequest.ReviewRequest.Create(appConfig.GitHubOrganization, appConfig.GitHubRepoName, pullRequest.Number, new PullRequestReviewRequest(teamMembers.AsReadOnly(), null)); // Add label var issueUpdate = new IssueUpdate(); issueUpdate.AddAssignee(appConfig.PullRequestAssignee); issueUpdate.AddLabel(appConfig.PullRequestLabel); // Update the PR with the relevant info await finalClient.Issue.Update(appConfig.GitHubOrganization, appConfig.GitHubRepoName, pullRequest.Number, issueUpdate); } catch (Exception ex) { throw ex; } }
static async Task Main() { string token = await GetGithubAppToken(); // Pass the JWT as a Bearer token to Octokit.net var finalClient = new GitHubClient(new ProductHeaderValue("PermissionsScraper")) { Credentials = new Credentials(token, AuthenticationType.Bearer) }; // Get Repo references var references = await finalClient.Git.Reference.GetAll("microsoftgraph", "microsoft-graph-devx-content"); // Check if the test branch is in the refs var testBranch = references.Where(reference => reference.Ref == "refs/heads/test").FirstOrDefault(); // check if branch already exists. if (testBranch == null) { // test branch does not exist so branch odd dev var devBranch = references.Where(reference => reference.Ref == "refs/heads/dev").FirstOrDefault(); // exception will throw if branch already exists var newBranch = await finalClient.Git.Reference.Create("microsoftgraph", "microsoft-graph-devx-content", new NewReference("refs/heads/test", devBranch.Object.Sha)); // create file var createChangeSet = await finalClient.Repository.Content.CreateFile( "microsoftgraph", "microsoft-graph-devx-content", "path/file.txt", new CreateFileRequest("File creation", "Hello Andrew!", "test")); } else { // Get reference of test branch var masterReference = await finalClient.Git.Reference.Get("microsoftgraph", "microsoft-graph-devx-content", testBranch.Ref); // Get the laster commit of this branch var latestCommit = await finalClient.Git.Commit.Get("microsoftgraph", "microsoft-graph-devx-content", masterReference.Object.Sha); // Create text blob var textBlob = new NewBlob { Encoding = EncodingType.Utf8, Content = "Hello Sunday" }; var textBlobRef = await finalClient.Git.Blob.Create("microsoftgraph", "microsoft-graph-devx-content", textBlob); // Create new Tree var nt = new NewTree { BaseTree = latestCommit.Tree.Sha }; // Add items based on blobs nt.Tree.Add(new NewTreeItem { Path = "path/file.txt", Mode = "100644", Type = TreeType.Blob, Sha = textBlobRef.Sha }); var newTree = await finalClient.Git.Tree.Create("microsoftgraph", "microsoft-graph-devx-content", nt); // Create Commit var newCommit = new NewCommit("Commit test with several files", newTree.Sha, masterReference.Object.Sha); var commit = await finalClient.Git.Commit.Create("microsoftgraph", "microsoft-graph-devx-content", newCommit); // push the commit await finalClient.Git.Reference.Update("microsoftgraph", "microsoft-graph-devx-content", testBranch.Ref, new ReferenceUpdate(commit.Sha)); } // create PR var pullRequest = await finalClient.Repository.PullRequest.Create("microsoftgraph", "microsoft-graph-devx-content", new NewPullRequest("Timely content update", "test", "dev") { Body = "This is a test PR" }); // Add reviewers var teamMembers = new List <string> { "andrueastman", "bettirosengugi" }; var reviewersResult = await finalClient.Repository.PullRequest.ReviewRequest.Create("microsoftgraph", "microsoft-graph-devx-content", pullRequest.Number, new PullRequestReviewRequest(teamMembers.AsReadOnly(), null)); // Add label var issueUpdate = new IssueUpdate(); issueUpdate.AddAssignee("irvinesunday"); issueUpdate.AddLabel("Generated"); // Update the PR with the relevant info await finalClient.Issue.Update("microsoftgraph", "microsoft-graph-devx-content", pullRequest.Number, issueUpdate); }