Exemple #1
0
        /// <summary>
        /// Push changes to branch
        /// </summary>
        /// <param name="teamProjectName"></param>
        /// <param name="gitRepoName"></param>
        /// <param name="branchRef"></param>
        /// <param name="branchOldId"></param>
        /// <param name="targetPath"></param>
        /// <param name="fileContent"></param>
        /// <param name="itemContentType"></param>
        /// <param name="versionControlChangeType"></param>
        /// <param name="commitComment"></param>
        private static void PushChanges(string teamProjectName, string gitRepoName, string branchRef, string branchOldId, string targetPath, string fileContent, ItemContentType itemContentType, VersionControlChangeType versionControlChangeType, string commitComment)
        {
            GitRefUpdate branch = new GitRefUpdate();

            branch.OldObjectId = branchOldId;
            branch.Name        = branchRef;

            GitCommitRef newCommit = new GitCommitRef();

            newCommit.Comment = commitComment;
            GitChange gitChange = new GitChange();

            gitChange.ChangeType = versionControlChangeType;
            gitChange.Item       = new GitItem()
            {
                Path = targetPath
            };
            gitChange.NewContent = new ItemContent()
            {
                Content = fileContent, ContentType = itemContentType
            };
            newCommit.Changes = new GitChange[] { gitChange };

            GitPush gitPush = new GitPush();

            gitPush.RefUpdates = new GitRefUpdate[] { branch };
            gitPush.Commits    = new GitCommitRef[] { newCommit };

            var pushResult = GitClient.CreatePushAsync(gitPush, teamProjectName, gitRepoName).Result;

            Console.WriteLine("Push id: " + pushResult.PushId);
        }
Exemple #2
0
        /// <summary>
        /// Push changes to remove, rename or move files
        /// </summary>
        /// <param name="teamProjectName"></param>
        /// <param name="gitRepoName"></param>
        /// <param name="branchRef"></param>
        /// <param name="branchOldId"></param>
        /// <param name="oldPath"></param>
        /// <param name="targetPath"></param>
        /// <param name="versionControlChangeType"></param>
        /// <param name="commitComment"></param>
        private static void PushChanges(string teamProjectName, string gitRepoName, string branchRef, string branchOldId, string oldPath, string targetPath, VersionControlChangeType versionControlChangeType, string commitComment)
        {
            GitRefUpdate branch = new GitRefUpdate();

            branch.OldObjectId = branchOldId;
            branch.Name        = branchRef;

            GitCommitRef newCommit = new GitCommitRef();

            newCommit.Comment = commitComment;
            GitChange gitChange = new GitChange();

            gitChange.ChangeType = versionControlChangeType;
            if (!string.IsNullOrEmpty(oldPath))
            {
                gitChange.SourceServerItem = oldPath;
            }
            gitChange.Item = new GitItem()
            {
                Path = targetPath
            };
            newCommit.Changes = new GitChange[] { gitChange };

            GitPush gitPush = new GitPush();

            gitPush.RefUpdates = new GitRefUpdate[] { branch };
            gitPush.Commits    = new GitCommitRef[] { newCommit };

            var pushResult = GitClient.CreatePushAsync(gitPush, teamProjectName, gitRepoName).Result;

            Console.WriteLine("Push id: " + pushResult.PushId);
        }
        public static void WithCommit(this TestCompositionRoot root,
                                      string repositoryName,
                                      string authorName,
                                      string authorEmail  = null,
                                      DateTime?commitDate = null,
                                      int deletions       = 0,
                                      int edits           = 0,
                                      int additions       = 0,
                                      string organization = "jrolstad",
                                      string project      = "the-project")
        {
            var item = new GitCommitRef
            {
                author = new GitUserDate
                {
                    date  = commitDate ?? DateTime.Now.AddDays(-7),
                    email = authorEmail ?? Base64Encode(authorName),
                    name  = authorName
                },
                changeCounts = new ChangeCountDictionary
                {
                    Add    = additions,
                    Edit   = edits,
                    Delete = deletions
                },
                commitId     = Guid.NewGuid().ToString(),
                RepositoryId = Base64Encode(repositoryName)
            };


            WithItem(organization, project, root.Context.Commits, item);
        }
Exemple #4
0
        public GitPush CreatePush(string projectName, string repoName)
        {
            VssConnection connection = this.Connection;
            GitHttpClient gitClient  = connection.GetClient <GitHttpClient>();

            var repo = gitClient.GetRepositoryAsync(projectName, repoName).Result;

            //// we will create a new push by making a small change to the default branch
            //// first, find the default branch

            //GitRef defaultBranch = gitClient.GetRefsAsync(repo.Id).Result.First();

            // next, craft the branch and commit that we'll push
            GitRefUpdate newBranch = new GitRefUpdate()
            {
                Name        = $"refs/heads/master",
                OldObjectId = "0000000000000000000000000000000000000000"
            };
            string       newFileName = $"test.md";
            GitCommitRef newCommit   = new GitCommitRef()
            {
                Comment = "Add a sample file",
                Changes = new GitChange[]
                {
                    new GitChange()
                    {
                        ChangeType = VersionControlChangeType.Add,
                        Item       = new GitItem()
                        {
                            Path = $"/master/{newFileName}"
                        },
                        NewContent = new ItemContent()
                        {
                            Content     = "# Thank you for using VSTS!",
                            ContentType = ItemContentType.RawText,
                        },
                    }
                },
            };

            // create the push with the new branch and commit
            GitPush push = gitClient.CreatePushAsync(new GitPush()
            {
                RefUpdates = new GitRefUpdate[] { newBranch },
                Commits    = new GitCommitRef[] { newCommit },
            }, repo.Id).Result;

            Console.WriteLine("project {0}, repo {1}", projectName, repo.Name);
            Console.WriteLine("push {0} updated {1} to {2}",
                              push.PushId, push.RefUpdates.First().Name, push.Commits.First().CommitId);



            return(push);
        }
        private static GitPullRequest CreatePullRequestInternal(ClientSampleContext context, GitRepository repo, GitHttpClient gitClient)
        {
            // we need a new branch with changes in order to create a PR
            // first, find the default branch
            string defaultBranchName = WithoutRefsPrefix(repo.DefaultBranch);
            GitRef defaultBranch     = gitClient.GetRefsAsync(repo.Id, filter: defaultBranchName).Result.First();

            // next, craft the branch and commit that we'll push
            GitRefUpdate newBranch = new GitRefUpdate()
            {
                Name        = $"refs/heads/vsts-api-sample/{ChooseRefsafeName()}",
                OldObjectId = defaultBranch.ObjectId,
            };
            string       newFileName = $"{ChooseItemsafeName()}.md";
            GitCommitRef newCommit   = new GitCommitRef()
            {
                Comment = "Add a sample file",
                Changes = new GitChange[]
                {
                    new GitChange()
                    {
                        ChangeType = VersionControlChangeType.Add,
                        Item       = new GitItem()
                        {
                            Path = $"/vsts-api-sample/{newFileName}"
                        },
                        NewContent = new ItemContent()
                        {
                            Content     = "# Thank you for using VSTS!",
                            ContentType = ItemContentType.RawText,
                        },
                    }
                },
            };

            // create the push with the new branch and commit
            GitPush push = gitClient.CreatePushAsync(new GitPush()
            {
                RefUpdates = new GitRefUpdate[] { newBranch },
                Commits    = new GitCommitRef[] { newCommit },
            }, repo.Id).Result;

            // finally, create a PR
            var pr = gitClient.CreatePullRequestAsync(new GitPullRequest()
            {
                SourceRefName = newBranch.Name,
                TargetRefName = repo.DefaultBranch,
                Title         = $"Add {newFileName} (from VSTS REST samples)",
                Description   = "Adding this file from the pull request samples",
            },
                                                      repo.Id).Result;

            return(pr);
        }
        public static async Task <GitPush> PushChangesAsync(this IAzdoGitHttpClient gitHttpClient, string commitMessage, Guid repositoryId, GitRef branchRef,
                                                            IDictionary <string, string> files)
        {
            GitRefUpdate branchRefUpdate = new GitRefUpdate
            {
                Name        = branchRef.Name,
                OldObjectId = branchRef.ObjectId
            };

            string branchName = branchRef.Name.Substring(branchRefUpdate.Name.LastIndexOf('/') + 1);

            var fileInfos = files
                            .Select(kvp => new
            {
                Exists       = FileExistsAsync(gitHttpClient, repositoryId, branchName, kvp.Key),
                Path         = kvp.Key,
                FileContents = kvp.Value
            })
                            .ToArray();

            // Wait for all of the operations that check for file existence to complete
            await Task.WhenAll(fileInfos.Select(info => info.Exists));

            GitChange[] changes = fileInfos
                                  .Select(info =>
                                          new GitChange
            {
                ChangeType = info.Exists.Result ? VersionControlChangeType.Edit : VersionControlChangeType.Add,
                Item       = new GitItem
                {
                    Path = info.Path
                },
                NewContent = new ItemContent
                {
                    Content     = Convert.ToBase64String(Encoding.UTF8.GetBytes(info.FileContents)),
                    ContentType = ItemContentType.Base64Encoded
                }
            })
                                  .ToArray();

            GitCommitRef commitRef = new GitCommitRef
            {
                Comment = commitMessage,
                Changes = changes
            };

            GitPush push = new GitPush
            {
                RefUpdates = new GitRefUpdate[] { branchRefUpdate },
                Commits    = new GitCommitRef[] { commitRef }
            };

            return(await gitHttpClient.CreatePushAsync(push, repositoryId));
        }
Exemple #7
0
 private async Task WriteCommitDetails(GitRepository repository, GitCommitRef commit, string workItemId, ISink sink)
 {
     await sink.Write(
         new string[]
     {
         repository.Name,
         commit.CommitId,
         commit.Author.Date.ToString("s"),
         commit.Author.Name,
         commit.Comment,
         workItemId
     });
 }
Exemple #8
0
        /// <summary>
        /// Converts a <see cref="GitCommitRef"/> to a <see cref="AzureDevOpsCommit"/>.
        /// </summary>
        /// <param name="commit">Commit to convert.</param>
        /// <returns>Converted commit.</returns>
        public static AzureDevOpsCommit ToAzureDevOpsCommit(this GitCommitRef commit)
        {
            commit.NotNull(nameof(commit));

            return
                (new AzureDevOpsCommit
            {
                Id = commit.CommitId,
                Message = commit.Comment,
                IsMessageTruncated = commit.CommentTruncated,
                ParentIds = commit.Parents,
                RemoteUrl = commit.RemoteUrl,
            });
        }
        public GitRevert CreateRevert()
        {
            VssConnection connection = this.Context.Connection;
            GitHttpClient gitClient  = connection.GetClient <GitHttpClient>();

            Guid          projectId  = ClientSampleHelpers.FindAnyProject(this.Context).Id;
            GitRepository repo       = GitSampleHelpers.FindAnyRepository(this.Context, projectId);
            string        branchName = repo.DefaultBranch;
            string        branchNameWithoutRefsHeads = branchName.Remove(0, "refs/heads/".Length);

            // find the latest commit on default
            GitCommitRef latestCommitOnDefault = gitClient.GetCommitsAsync(repo.Id, new GitQueryCommitsCriteria()
            {
                ItemVersion = new GitVersionDescriptor()
                {
                    Version     = branchNameWithoutRefsHeads,
                    VersionType = GitVersionType.Branch
                },
                Top = 1
            }).Result.First();

            // generate a unique name to suggest for the branch
            string suggestedBranchName = "refs/heads/azure-devops-dotnet-samples/" + GitSampleHelpers.ChooseRefsafeName();

            // write down the name for a later sample
            this.Context.SetValue <string>("$gitSamples.suggestedRevertBranchName", suggestedBranchName);

            // revert it relative to default branch
            GitRevert revert = gitClient.CreateRevertAsync(
                new GitAsyncRefOperationParameters()
            {
                OntoRefName      = branchName,
                GeneratedRefName = suggestedBranchName,
                Repository       = repo,
                Source           = new GitAsyncRefOperationSource()
                {
                    CommitList = new GitCommitRef[] { new GitCommitRef()
                                                      {
                                                          CommitId = latestCommitOnDefault.CommitId
                                                      } }
                },
            },
                projectId,
                repo.Id).Result;

            Console.WriteLine("Revert {0} created", revert.RevertId);

            // typically, the next thing you'd do is create a PR for this revert
            return(revert);
        }
        private async Task <string> InnerCreateBranch(string name, GitHttpClient client, Guid repositoryID, string newObjectCommitID)
        {
            bool isCIFileExist = true;

            try
            {
                _ = await client.GetItemAsync(repositoryID, ciFilePath);
            }
            catch (Exception)
            {
                isCIFileExist = false;
            }

            GitRefUpdate newBranch = new GitRefUpdate()
            {
                Name        = $"{_azureDevopsConfiguration.GITSourceControl.NewBranchPath}/{name}",
                OldObjectId = newObjectCommitID
            };

            GitCommitRef newCommit = new GitCommitRef()
            {
                Comment = "***No_CI****",
                Changes = new GitChange[]
                {
                    new GitChange()
                    {
                        ChangeType = isCIFileExist ? VersionControlChangeType.Edit : VersionControlChangeType.Add,
                        Item       = new GitItem()
                        {
                            Path = $"/_no_ci_file"
                        },
                        NewContent = new ItemContent()
                        {
                            Content     = "",
                            ContentType = ItemContentType.RawText,
                        },
                    }
                }
            };

            GitPush push = await client.CreatePushAsync(new GitPush()
            {
                RefUpdates = new GitRefUpdate[] { newBranch },
                Commits    = new GitCommitRef[] { newCommit },
            }, repositoryID);

            return(push.Commits.First(x => !String.IsNullOrEmpty(x.CommitId))?.CommitId);
        }
Exemple #11
0
        private object GetFirstReleaseBranchByCommit(Guid repoId, GitCommitRef lastCommit, List <GitRef> releaseBranches)
        {
            foreach (var releaseBranch in releaseBranches)
            {
                var newBranchVersionDescriptor = new GitVersionDescriptor()
                {
                    VersionType = GitVersionType.Branch, Version = AzureGitHelper.WithoutRefsAndHeadsPrefix(releaseBranch.Name)
                };
                var criteria = new GitQueryCommitsCriteria()
                {
                    Ids = new List <string>()
                    {
                        lastCommit.CommitId
                    }, Top = 1, ItemVersion = newBranchVersionDescriptor
                };

                if (gitClient.GetCommitsAsync(repoId, criteria, top: 1).Result.Any())
                {
                    return(releaseBranch);
                }
            }

            return(null);
        }
Exemple #12
0
        public void GitCommitRefTests_Constructor()
        {
            // Arrange
            var obj = BaseTests.LoadJson("Get-VSTeamGitCommit.json");

            // Act
            var target = new GitCommitRef(obj[0], "Project Name");

            // Assert
            Assert.AreEqual(0, target.Adds, "Adds");
            Assert.AreEqual(3, target.Edits, "Edits");
            Assert.AreEqual(0, target.Deletes, "Deletes");
            Assert.AreEqual("Clean up.", target.Comment, "Comment");
            Assert.AreEqual("6843b66ef58214061b996508ae37a8bbd67a12c2", target.CommitId, "CommitId");
            Assert.AreEqual("https://dev.azure.com/Test/PeopleTracker/_git/Bakeoff/commit/6843b66ef58214061b996508ae37a8bbd67a12c2", target.RemoteUrl, "RemoteUrl");
            Assert.AreEqual("https://dev.azure.com/Test/00000000-0000-0000-0000-000000000000/_apis/git/repositories/00000000-0000-0000-0000-000000000000/commits/6843b66ef58214061b996508ae37a8bbd67a12c2", target.Url, "Url");


            Assert.IsNotNull(target.Author, "Author");
            Assert.IsNotNull(target.Committer, "Committer");
            Assert.AreEqual("Donovan Brown", target.Committer.Name, "Committer.Name");
            Assert.AreEqual("*****@*****.**", target.Committer.Email, "Committer.Email");
            Assert.AreEqual("8/8/2019 8:58:58 pm", target.Committer.Date.ToString("M/d/yyyy h:mm:ss tt").ToLower(), "Committer.Date");
        }
        public async Task <GitRepository> CreateRepository(string projectName, string repositoryName, bool initialise)
        {
            GitRepository repo = null;

            try
            {
                GitRepositoryCreateOptions options = new GitRepositoryCreateOptions
                {
                    Name = repositoryName
                };
                repo = await Git.CreateRepositoryAsync(options, projectName, null, null, default);
            }
            catch (Exception ex)
            {
                throw new Exception($"Failed to create new repository: {repositoryName}", ex);
            }

            if (initialise)
            {
                GitRefUpdate newBranch = new GitRefUpdate
                {
                    Name        = "refs/heads/master",
                    OldObjectId = new string('0', 40)
                };

                GitCommitRef newCommit = new GitCommitRef()
                {
                    Comment = "Add a sample file",
                    Changes = new GitChange[]
                    {
                        new GitChange()
                        {
                            ChangeType = VersionControlChangeType.Add,
                            Item       = new GitItem()
                            {
                                Path = "/readme.md"
                            },
                            NewContent = new ItemContent()
                            {
                                Content     = "Empty file for initial commit",
                                ContentType = ItemContentType.RawText,
                            },
                        }
                    },
                };

                try
                {
                    _ = await Git.CreatePushAsync(new GitPush()
                    {
                        RefUpdates = new GitRefUpdate[] { newBranch },
                        Commits    = new GitCommitRef[] { newCommit },
                    }, repo.Id);
                }
                catch (Exception ex)
                {
                    throw new Exception($"Could not initialise repository: {repositoryName}", ex);
                }
            }

            return(repo);
        }
        public async Task CopyFolderToRepository(GitRepository sourceRepository, string directoryName, GitRepository targetRepository, ContentReplacer replacer)
        {
            string        refId             = new string('0', 40);
            string        defaultBranchName = "heads/master";
            List <GitRef> refs = null;

            try
            {
                refs = await Git.GetRefsAsync(targetRepository.Id, filter : defaultBranchName);

                if (refs.Count > 0)
                {
                    GitRef defaultBranch = refs.First();
                    refId = defaultBranch.ObjectId;
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Could not get master ref", ex);
            }

            GitRefUpdate refUpdate = new GitRefUpdate()
            {
                Name        = "refs/heads/master",
                OldObjectId = refId
            };

            List <GitChange> changes = new List <GitChange>();

            List <GitItem> items = null;

            try
            {
                items = await Git.GetItemsAsync(sourceRepository.Id, scopePath : directoryName, recursionLevel : VersionControlRecursionType.Full);

                foreach (GitItem item in items)
                {
                    if (item.GitObjectType == GitObjectType.Blob)
                    {
                        Stream stream = await Git.GetItemContentAsync(repositoryId : sourceRepository.Id, path : item.Path);

                        StreamReader reader  = new StreamReader(stream);
                        string       content = reader.ReadToEnd();
                        string       newPath = item.Path.Remove(0, directoryName.Length);

                        if (replacer != null)
                        {
                            content = replacer.ReplaceContent(newPath, content);
                        }

                        GitChange change = new GitChange
                        {
                            ChangeType = VersionControlChangeType.Add,
                            Item       = new GitItem()
                            {
                                Path = newPath
                            },
                            NewContent = new ItemContent()
                            {
                                Content     = content,
                                ContentType = ItemContentType.RawText,
                            }
                        };
                        changes.Add(change);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error copying files", ex);
            }

            GitCommitRef newCommit = new GitCommitRef()
            {
                Comment = $"Copying files from {sourceRepository.Name}",
                Changes = changes.ToArray()
            };

            try
            {
                _ = await Git.CreatePushAsync(new GitPush()
                {
                    RefUpdates = new GitRefUpdate[] { refUpdate },
                    Commits    = new GitCommitRef[] { newCommit },
                }, targetRepository.Id);
            }
            catch (Exception ex)
            {
                throw new Exception("Error pushing commit", ex);
            }
        }
Exemple #15
0
        public GitPush CreatePush()
        {
            VssConnection connection = this.Context.Connection;
            GitHttpClient gitClient  = connection.GetClient <GitHttpClient>();

            TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context);
            GitRepository        repo    = GitSampleHelpers.FindAnyRepository(this.Context, project.Id);

            // we will create a new push by making a small change to the default branch
            // first, find the default branch
            string defaultBranchName = GitSampleHelpers.WithoutRefsPrefix(repo.DefaultBranch);
            GitRef defaultBranch     = gitClient.GetRefsAsync(repo.Id, filter: defaultBranchName).Result.First();

            // next, craft the branch and commit that we'll push
            GitRefUpdate newBranch = new GitRefUpdate()
            {
                Name        = $"refs/heads/vsts-api-sample/{GitSampleHelpers.ChooseRefsafeName()}",
                OldObjectId = defaultBranch.ObjectId,
            };
            string       newFileName = $"{GitSampleHelpers.ChooseItemsafeName()}.md";
            GitCommitRef newCommit   = new GitCommitRef()
            {
                Comment = "Add a sample file",
                Changes = new GitChange[]
                {
                    new GitChange()
                    {
                        ChangeType = VersionControlChangeType.Add,
                        Item       = new GitItem()
                        {
                            Path = $"/vsts-api-sample/{newFileName}"
                        },
                        NewContent = new ItemContent()
                        {
                            Content     = "# Thank you for using VSTS!",
                            ContentType = ItemContentType.RawText,
                        },
                    }
                },
            };

            // create the push with the new branch and commit
            GitPush push = gitClient.CreatePushAsync(new GitPush()
            {
                RefUpdates = new GitRefUpdate[] { newBranch },
                Commits    = new GitCommitRef[] { newCommit },
            }, repo.Id).Result;

            Console.WriteLine("project {0}, repo {1}", project.Name, repo.Name);
            Console.WriteLine("push {0} updated {1} to {2}",
                              push.PushId, push.RefUpdates.First().Name, push.Commits.First().CommitId);

            // now clean up after ourselves (and in case logging is on, don't log these calls)
            ClientSampleHttpLogger.SetSuppressOutput(this.Context, true);

            // delete the branch
            GitRefUpdateResult refDeleteResult = gitClient.UpdateRefsAsync(
                new GitRefUpdate[]
            {
                new GitRefUpdate()
                {
                    OldObjectId = push.RefUpdates.First().NewObjectId,
                    NewObjectId = new string('0', 40),
                    Name        = push.RefUpdates.First().Name,
                }
            },
                repositoryId: repo.Id).Result.First();

            // pushes and commits are immutable, so no way to clean them up
            // but the commit will be unreachable after this

            return(push);
        }
        public GitPullRequest CreatePullRequestInner(bool cleanUp)
        {
            VssConnection connection = this.Context.Connection;
            GitHttpClient gitClient  = connection.GetClient <GitHttpClient>();

            TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context);
            GitRepository        repo    = GitSampleHelpers.FindAnyRepository(this.Context, project.Id);

            // we need a new branch with changes in order to create a PR
            // first, find the default branch
            string defaultBranchName = GitSampleHelpers.WithoutRefsPrefix(repo.DefaultBranch);
            GitRef defaultBranch     = gitClient.GetRefsAsync(repo.Id, filter: defaultBranchName).Result.First();

            // next, craft the branch and commit that we'll push
            GitRefUpdate newBranch = new GitRefUpdate()
            {
                Name        = $"refs/heads/vsts-api-sample/{GitSampleHelpers.ChooseRefsafeName()}",
                OldObjectId = defaultBranch.ObjectId,
            };
            string       newFileName = $"{GitSampleHelpers.ChooseItemsafeName()}.md";
            GitCommitRef newCommit   = new GitCommitRef()
            {
                Comment = "Add a sample file",
                Changes = new GitChange[]
                {
                    new GitChange()
                    {
                        ChangeType = VersionControlChangeType.Add,
                        Item       = new GitItem()
                        {
                            Path = $"/vsts-api-sample/{newFileName}"
                        },
                        NewContent = new ItemContent()
                        {
                            Content     = "# Thank you for using VSTS!",
                            ContentType = ItemContentType.RawText,
                        },
                    }
                },
            };

            // create the push with the new branch and commit
            GitPush push = gitClient.CreatePushAsync(new GitPush()
            {
                RefUpdates = new GitRefUpdate[] { newBranch },
                Commits    = new GitCommitRef[] { newCommit },
            }, repo.Id).Result;

            // finally, create a PR
            var pr = gitClient.CreatePullRequestAsync(new GitPullRequest()
            {
                SourceRefName = newBranch.Name,
                TargetRefName = repo.DefaultBranch,
                Title         = $"Add {newFileName} (from VSTS REST samples)",
                Description   = "Adding this file from the pull request samples",
            },
                                                      repo.Id).Result;

            Console.WriteLine("project {0}, repo {1}", project.Name, repo.Name);
            Console.WriteLine("{0} (#{1}) {2} -> {3}",
                              pr.Title.Substring(0, Math.Min(40, pr.Title.Length)),
                              pr.PullRequestId,
                              pr.SourceRefName,
                              pr.TargetRefName);

            if (cleanUp)
            {
                // clean up after ourselves (and in case logging is on, don't log these calls)
                ClientSampleHttpLogger.SetSuppressOutput(this.Context, true);

                // abandon the PR
                GitPullRequest updatedPr = new GitPullRequest()
                {
                    Status = PullRequestStatus.Abandoned,
                };
                pr = gitClient.UpdatePullRequestAsync(updatedPr, repo.Id, pr.PullRequestId).Result;

                // delete the branch
                GitRefUpdateResult refDeleteResult = gitClient.UpdateRefsAsync(
                    new GitRefUpdate[]
                {
                    new GitRefUpdate()
                    {
                        OldObjectId = push.RefUpdates.First().NewObjectId,
                        NewObjectId = new string('0', 40),
                        Name        = push.RefUpdates.First().Name,
                    }
                },
                    repositoryId: repo.Id).Result.First();
            }

            return(pr);
        }
        public static async Task <(bool success, int pullRequestId)> PerformInsertionAsync(
            RoslynInsertionToolOptions options,
            CancellationToken cancellationToken)
        {
            Options = options;
            Console.WriteLine($"{Environment.NewLine}New Insertion Into {Options.VisualStudioBranchName} Started{Environment.NewLine}");

            var newPackageFiles = new List <string>();

            try
            {
                Console.WriteLine($"Verifying given authentication for {Options.VSTSUri}");
                try
                {
                    ProjectCollection.Authenticate();
                }
                catch (Exception ex)
                {
                    LogError($"Could not authenticate with {Options.VSTSUri}");
                    LogError(ex);
                    return(false, 0);
                }

                Console.WriteLine($"Verification succeeded for {Options.VSTSUri}");

                // ********************** Create dummy PR *****************************
                if (Options.CreateDummyPr)
                {
                    GitPullRequest dummyPR;
                    try
                    {
                        dummyPR = await CreatePlaceholderBranchAsync(cancellationToken);
                    }
                    catch (Exception ex)
                    {
                        LogError($"Unable to create placeholder PR for '{options.VisualStudioBranchName}'");
                        LogError(ex);
                        return(false, 0);
                    }

                    if (dummyPR == null)
                    {
                        LogError($"Unable to create placeholder PR for '{options.VisualStudioBranchName}'");
                        return(false, 0);
                    }

                    return(true, dummyPR.PullRequestId);
                }

                // ********************** Get Last Insertion *****************************
                cancellationToken.ThrowIfCancellationRequested();

                BuildVersion buildVersion;

                Build buildToInsert;
                Build latestBuild = null;
                bool  retainBuild = false;

                // Get the version from DevOps Pipelines queue, e.g. Roslyn-Master-Signed-Release.
                if (string.IsNullOrEmpty(Options.SpecificBuild))
                {
                    buildToInsert = await GetLatestPassedBuildAsync(cancellationToken);

                    buildVersion = BuildVersion.FromTfsBuildNumber(buildToInsert.BuildNumber, Options.BuildQueueName);
                    Console.WriteLine("Found build number " + buildVersion);

                    //  Get the latest build, whether passed or failed.  If the buildToInsert has already been inserted but
                    //  there is a later failing build, then send an error
                    latestBuild = await GetLatestBuildAsync(cancellationToken);
                }
                else
                {
                    buildVersion  = BuildVersion.FromString(Options.SpecificBuild);
                    buildToInsert = await GetSpecificBuildAsync(buildVersion, cancellationToken);
                }

                var insertionArtifacts = await GetInsertionArtifactsAsync(buildToInsert, cancellationToken);

                cancellationToken.ThrowIfCancellationRequested();

                // *********** Look up existing PR ********************
                var gitClient = ProjectCollection.GetClient <GitHttpClient>();
                var branches  = await gitClient.GetRefsAsync(
                    VSRepoId,
                    filter : $"heads/{Options.VisualStudioBranchName}",
                    cancellationToken : cancellationToken);

                var baseBranch = branches.Single(b => b.Name == $"refs/heads/{Options.VisualStudioBranchName}");

                var pullRequestId = Options.UpdateExistingPr;
                var useExistingPr = pullRequestId != 0;

                GitPullRequest pullRequest;
                string         insertionBranchName;
                if (useExistingPr)
                {
                    pullRequest = await gitClient.GetPullRequestByIdAsync(pullRequestId, cancellationToken : cancellationToken);

                    insertionBranchName = pullRequest.SourceRefName.Substring("refs/heads/".Length);

                    var refs = await gitClient.GetRefsAsync(VSRepoId, filter : $"heads/{insertionBranchName}", cancellationToken : cancellationToken);

                    var insertionBranch = refs.Single(r => r.Name == $"refs/heads/{insertionBranchName}");

                    if (Options.OverwritePr)
                    {
                        // overwrite existing PR branch back to base before pushing new commit
                        var updateToBase = new GitRefUpdate
                        {
                            OldObjectId = insertionBranch.ObjectId,
                            NewObjectId = baseBranch.ObjectId,
                            Name        = $"refs/heads/{insertionBranchName}"
                        };
                        await gitClient.UpdateRefsAsync(new[] { updateToBase }, VSRepoId, cancellationToken : cancellationToken);
                    }
                    else
                    {
                        // not overwriting PR, so the insertion branch is actually the base
                        baseBranch = insertionBranch;
                    }
                }
                else
                {
                    pullRequest         = null;
                    insertionBranchName = GetNewBranchName();
                }

                var allChanges = new List <GitChange>();

                var coreXT = await CoreXT.Load(gitClient, baseBranch.ObjectId);

                if (Options.InsertCoreXTPackages)
                {
                    // ************** Update Nuget Packages For Branch************************
                    cancellationToken.ThrowIfCancellationRequested();
                    Console.WriteLine($"Updating Nuget Packages");
                    bool success;
                    (success, newPackageFiles) = UpdatePackages(
                        buildVersion,
                        coreXT,
                        insertionArtifacts.GetPackagesDirectory(),
                        cancellationToken);
                    retainBuild |= success;

                    // *********** Copy OptimizationInputs.props file ***********************
                    foreach (var propsFile in insertionArtifacts.GetOptProfPropertyFiles())
                    {
                        var targetFilePath = "src/Tests/config/runsettings/Official/OptProf/External/" + Path.GetFileName(propsFile);

                        var version = new GitVersionDescriptor {
                            VersionType = GitVersionType.Commit, Version = baseBranch.ObjectId
                        };
                        var stream = await gitClient.GetItemContentAsync(VSRepoId, targetFilePath, download : true, versionDescriptor : version);

                        var originalContent = new StreamReader(stream).ReadToEnd();

                        var newContent = File.ReadAllText(propsFile);

                        if (GetChangeOpt(targetFilePath, originalContent, newContent) is GitChange change)
                        {
                            allChanges.Add(change);
                        }
                    }
                }

                if (Options.UpdateCoreXTLibraries || Options.UpdateAssemblyVersions)
                {
                    // ************** Update assembly versions ************************
                    cancellationToken.ThrowIfCancellationRequested();
                    Console.WriteLine($"Updating assembly versions");
                    if (await UpdateAssemblyVersionsOpt(gitClient, baseBranch.ObjectId, insertionArtifacts) is GitChange assemblyVersionChange)
                    {
                        allChanges.Add(assemblyVersionChange);
                    }

                    // if we got this far then we definitely need to retain this build
                    retainBuild = true;
                }

                // *********** Update toolset ********************
                if (Options.InsertToolset)
                {
                    UpdateToolsetPackage(coreXT, insertionArtifacts, buildVersion);
                    retainBuild = true;
                }

                // ************ Update .corext\Configs\default.config ********************
                cancellationToken.ThrowIfCancellationRequested();
                Console.WriteLine($"Updating CoreXT default.config file");
                if (coreXT.SaveConfigOpt() is GitChange configChange)
                {
                    allChanges.Add(configChange);
                }

                // *********** Update .corext\Configs\components.json ********************

                BuildVersion oldComponentVersion = default;
                if (Options.InsertWillowPackages)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    Console.WriteLine($"Updating CoreXT components file");

                    var components = await GetLatestComponentsAsync(buildToInsert, cancellationToken);

                    var shouldSave = false;
                    foreach (var newComponent in components)
                    {
                        if (coreXT.TryGetComponentByName(newComponent.Name, out var oldComponent))
                        {
                            if (oldComponent.BuildVersion != default)
                            {
                                oldComponentVersion = oldComponent.BuildVersion;
                            }
                            coreXT.UpdateComponent(newComponent);
                            shouldSave = true;
                        }
                    }
                    if (shouldSave)
                    {
                        var allComponentChanges = coreXT.SaveComponents();
                        allChanges.AddRange(allComponentChanges);
                        retainBuild = true;
                    }
                }

                // ************* Ensure the build is retained on the servers *************
                if (Options.RetainInsertedBuild && retainBuild && !buildToInsert.KeepForever.GetValueOrDefault())
                {
                    Console.WriteLine("Marking inserted build for retention.");
                    buildToInsert.KeepForever = true;
                    var buildClient = ProjectCollection.GetClient <BuildHttpClient>();
                    await buildClient.UpdateBuildAsync(buildToInsert);
                }

                // ************* Bail out if there are no changes ************************
                if (!allChanges.Any())
                {
                    LogWarning("No meaningful changes since the last insertion was merged. PR will not be created or updated.");
                    return(true, 0);
                }

                // ********************* Create push *************************************
                var insertionBranchUpdate = new GitRefUpdate
                {
                    Name        = $"refs/heads/{insertionBranchName}",
                    OldObjectId = baseBranch.ObjectId
                };

                var commit = new GitCommitRef
                {
                    Comment = $"Updating {Options.InsertionName} to {buildVersion}",
                    Changes = allChanges
                };
                var push = new GitPush
                {
                    RefUpdates = new[] { insertionBranchUpdate },
                    Commits    = new[] { commit }
                };

                await gitClient.CreatePushAsync(push, VSRepoId, cancellationToken : cancellationToken);

                // ********************* Create pull request *****************************
                var oldBuild = await GetSpecificBuildAsync(oldComponentVersion, cancellationToken);

                var prDescriptionMarkdown = CreatePullRequestDescription(oldBuild, buildToInsert, useMarkdown: true);

                if (buildToInsert.Result == BuildResult.PartiallySucceeded)
                {
                    prDescriptionMarkdown += Environment.NewLine + ":warning: The build being inserted has partially succeeded.";
                }

                if (!useExistingPr || Options.OverwritePr)
                {
                    try
                    {
                        var nl = Environment.NewLine;
                        if (oldBuild is null)
                        {
                            prDescriptionMarkdown += $"{nl}---{nl}Unable to find details for previous build ({oldComponentVersion}){nl}";
                        }
                        else
                        {
                            var(changes, diffLink) = await GetChangesBetweenBuildsAsync(oldBuild, buildToInsert, cancellationToken);

                            var diffDescription = changes.Any()
                                ? $"[View Complete Diff of Changes]({diffLink})"
                                : "No source changes since previous insertion";

                            prDescriptionMarkdown += nl + "---" + nl + diffDescription + nl;
                            prDescriptionMarkdown  = AppendChangesToDescription(prDescriptionMarkdown, oldBuild ?? buildToInsert, changes);
                        }
                    }
                    catch (Exception e)
                    {
                        LogWarning("Failed to create diff links.");
                        LogWarning(e.Message);
                    }
                }

                if (useExistingPr)
                {
                    try
                    {
                        if (Options.OverwritePr)
                        {
                            pullRequest = await OverwritePullRequestAsync(pullRequestId, prDescriptionMarkdown, buildVersion.ToString(), options.TitlePrefix, cancellationToken);
                        }
                        pullRequestId = pullRequest.PullRequestId;
                    }
                    catch (Exception ex)
                    {
                        LogError($"Unable to update pull request for '{pullRequest.SourceRefName}'");
                        LogError(ex);
                        return(false, 0);
                    }
                }
                else
                {
                    // create a new PR
                    Console.WriteLine($"Create Pull Request");
                    try
                    {
                        // If this insertion was queued for PR validation, for a dev branch, or for a feature branch,
                        // then add the build queuer as a reviewer instead of mlinfraswat.
                        var isPrValidation       = !string.IsNullOrEmpty(GetBuildPRNumber(buildToInsert));
                        var isDevOrFeatureBranch = Options.BranchName.StartsWith("dev/") || Options.BranchName.StartsWith("features/");

                        var reviewerId = isPrValidation || isDevOrFeatureBranch
                            ? buildToInsert.RequestedBy.Id
                            : MLInfraSwatUserId.ToString();

                        pullRequest = await CreatePullRequestAsync(insertionBranchName, prDescriptionMarkdown, buildVersion.ToString(), options.TitlePrefix, reviewerId, cancellationToken);

                        if (pullRequest == null)
                        {
                            LogError($"Unable to create pull request for '{insertionBranchName}'");
                            return(false, 0);
                        }

                        pullRequestId = pullRequest.PullRequestId;
                    }
                    catch (Exception ex)
                    {
                        LogError($"Unable to create pull request for '{insertionBranchName}'");
                        LogError(ex);
                        return(false, 0);
                    }
                }

                // ********************* Create validation build *****************************
                if (Options.QueueValidationBuild)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    Console.WriteLine($"Create Validation Build");
                    try
                    {
                        if (Options.CreateDraftPr)
                        {
                            // When creating Draft PRs no policies are automatically started.
                            // If we do not queue a CloudBuild the Perf DDRITs request will
                            // spin waiting for a build to test against until it timesout.
                            await QueueBuildPolicy(pullRequest, "CloudBuild - PR");
                        }

                        await QueueBuildPolicy(pullRequest, "Request Perf DDRITs");
                    }
                    catch (Exception ex)
                    {
                        LogWarning($"Unable to create a CloudBuild validation build for '{insertionBranchName}'");
                        LogWarning(ex);
                    }

                    if (Options.CreateDraftPr)
                    {
                        // When creating Draft PRs no policies are automatically started.
                        await TryQueueBuildPolicy(pullRequest, "Insertion Hash Check", insertionBranchName);
                        await TryQueueBuildPolicy(pullRequest, "Insertion Sign Check", insertionBranchName);
                        await TryQueueBuildPolicy(pullRequest, "Insertion Symbol Check", insertionBranchName);
                    }
                }

                // ********************* Set PR to Auto-Complete *****************************
                if (Options.SetAutoComplete)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    Console.WriteLine($"Set PR to Auto-Complete");
                    try
                    {
                        var prDescriptionText = CreatePullRequestDescription(oldBuild, buildToInsert, useMarkdown: false);
                        await SetAutoCompleteAsync(pullRequest, prDescriptionText, cancellationToken);
                    }
                    catch (Exception ex)
                    {
                        LogWarning($"Unable to Set PR to Auto-Complete for '{insertionBranchName}'");
                        LogWarning(ex);
                    }
                }

                return(true, pullRequestId);
            }
            catch (Exception ex)
            {
                LogError(ex);
                return(false, 0);
            }
            finally
            {
                Options = null;
            }
        }
Exemple #18
0
        private void uploadFile(string userName, string password)
        {
            NetworkCredential netCred = new NetworkCredential(userName, password);
            WindowsCredential winCred = new WindowsCredential(netCred);
            VssCredentials    creds   = new VssClientCredentials(winCred);

            creds.Storage = new VssClientCredentialStorage();


            // Connect to VSTS
            VssConnection connection = new VssConnection(new Uri(c_collectionUri), creds);

            // Get a GitHttpClient to talk to the Git endpoints
            GitHttpClient gitClient = connection.GetClient <GitHttpClient>();

            // Get data about a specific repository
            var repo = gitClient.GetRepositoryAsync(c_projectName, c_repoName).GetAwaiter().GetResult();


            GitRef       branch    = gitClient.GetRefsAsync(repo.Id, filter: "heads/OfficeMarketing").GetAwaiter().GetResult().First();
            GitRefUpdate refUpdate = new GitRefUpdate()
            {
                Name        = $"refs/heads/OfficeMarketing",
                OldObjectId = branch.ObjectId,
            };
            GitCommitRef newCommit = new GitCommitRef()
            {
                Comment = "add Json and xml file",
                Changes = new GitChange[]
                {
                    new GitChange()
                    {
                        ChangeType = VersionControlChangeType.Add,
                        Item       = new GitItem()
                        {
                            Path = $"IRIS/Chatbot/Source/" + ChampaignNamelabel1.Text + "/" + ChampaignNamelabel1.Text + ".en-US.json"
                        },
                        NewContent = new ItemContent()
                        {
                            Content     = writeToJson(),
                            ContentType = ItemContentType.RawText,
                        }
                    },
                    new GitChange()
                    {
                        ChangeType = VersionControlChangeType.Add,
                        Item       = new GitItem()
                        {
                            Path = $"IRIS/Chatbot/Source/" + ChampaignNamelabel1.Text + "/ExceptionMarketReference.xml"
                        },
                        NewContent = new ItemContent()
                        {
                            Content     = writeToXml(),
                            ContentType = ItemContentType.RawText,
                        }
                    }
                },
            };
            // create the push with the new branch and commit
            GitPush push = gitClient.CreatePushAsync(new GitPush()

            {
                RefUpdates = new GitRefUpdate[] { refUpdate },

                Commits = new GitCommitRef[] { newCommit },
            }, repo.Id).GetAwaiter().GetResult();
        }
Exemple #19
0
        private void uploadFile()
        {
            try
            {
                //VssCredentials creds = new VssClientCredentials();
                //creds.Storage = new VssClientCredentialStorage();
                VssBasicCredential creds = new VssBasicCredential(@"fareast\v-shgao", @"2wsx@WSX");

                // Connect to VSTS
                VssConnection connection = new VssConnection(new Uri(c_collectionUri), creds);

                // Get a GitHttpClient to talk to the Git endpoints
                GitHttpClient gitClient = connection.GetClient <GitHttpClient>();

                // Get data about a specific repository
                var          repo      = gitClient.GetRepositoryAsync(c_projectName, c_repoName).GetAwaiter().GetResult();
                GitRef       branch    = gitClient.GetRefsAsync(repo.Id, filter: "heads/OfficeMarketing").GetAwaiter().GetResult().First();
                GitRefUpdate refUpdate = new GitRefUpdate()
                {
                    Name        = $"refs/heads/OfficeMarketing",
                    OldObjectId = branch.ObjectId,
                };
                GitCommitRef newCommit = new GitCommitRef()
                {
                    Comment = "add Json and xml file",
                    Changes = new GitChange[]
                    {
                        new GitChange()
                        {
                            ChangeType = VersionControlChangeType.Add,
                            Item       = new GitItem()
                            {
                                Path = $"IRIS/Chatbot/Source/" + ChampaignNamelabel1.Text + "/" + ChampaignNamelabel1.Text + ".en-US.json"
                            },
                            NewContent = new ItemContent()
                            {
                                Content     = writeToJson(),
                                ContentType = ItemContentType.RawText,
                            }
                        },
                        new GitChange()
                        {
                            ChangeType = VersionControlChangeType.Add,
                            Item       = new GitItem()
                            {
                                Path = $"IRIS/Chatbot/Source/" + ChampaignNamelabel1.Text + "/ExceptionMarketReference.xml"
                            },
                            NewContent = new ItemContent()
                            {
                                Content     = writeToXml(),
                                ContentType = ItemContentType.RawText,
                            }
                        }
                    },
                };
                // create the push with the new branch and commit
                GitPush push = gitClient.CreatePushAsync(new GitPush()

                {
                    RefUpdates = new GitRefUpdate[] { refUpdate },

                    Commits = new GitCommitRef[] { newCommit },
                }, repo.Id).GetAwaiter().GetResult();
            }
            catch (VssUnauthorizedException e)
            {
                Form3 f3 = new Form3();
                f3.ShowDialog();
                if (f3.DialogResult == DialogResult.OK)
                {
                    try {
                        uploadFile(f3.UserName, f3.Password);
                        MessageBox.Show("Upload Successfully");
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Upload Fail:" + ex.Message);
                    }
                }
            }

            catch (Exception ex)
            {
                MessageBox.Show("UpLoad Fail:" + ex.Message);
            }
        }
        public static async Task <(bool success, int pullRequestId)> PerformInsertionAsync(
            RoslynInsertionToolOptions options,
            CancellationToken cancellationToken)
        {
            Options = options;
            Console.WriteLine($"{Environment.NewLine}New Insertion Into {Options.VisualStudioBranchName} Started{Environment.NewLine}");
            var newPackageFiles = new List <string>();

            try
            {
                Console.WriteLine($"Verifying given authentication for {Options.VisualStudioRepoAzdoUri}");
                try
                {
                    VisualStudioRepoConnection.Authenticate();
                }
                catch (Exception ex)
                {
                    LogError($"Could not authenticate with {Options.VisualStudioRepoAzdoUri}");
                    LogError(ex);
                    return(false, 0);
                }

                Console.WriteLine($"Verification succeeded for {Options.VisualStudioRepoAzdoUri}");

                if (ComponentBuildConnection != VisualStudioRepoConnection)
                {
                    Console.WriteLine($"Verifying given authentication for {Options.ComponentBuildAzdoUri}");
                    try
                    {
                        ComponentBuildConnection.Authenticate();
                    }
                    catch (Exception ex)
                    {
                        LogError($"Could not authenticate with {Options.ComponentBuildAzdoUri}");
                        LogError(ex);
                        return(false, 0);
                    }

                    Console.WriteLine($"Verification succeeded for {Options.ComponentBuildAzdoUri}");
                }

                // ********************** Create dummy PR *****************************
                if (Options.CreateDummyPr)
                {
                    GitPullRequest dummyPR;
                    try
                    {
                        dummyPR = await CreatePlaceholderVSBranchAsync(cancellationToken);
                    }
                    catch (Exception ex)
                    {
                        LogError($"Unable to create placeholder PR for '{options.VisualStudioBranchName}'");
                        LogError(ex);
                        return(false, 0);
                    }

                    if (dummyPR == null)
                    {
                        LogError($"Unable to create placeholder PR for '{options.VisualStudioBranchName}'");
                        return(false, 0);
                    }

                    return(true, dummyPR.PullRequestId);
                }

                // ********************** Get Last Insertion *****************************
                cancellationToken.ThrowIfCancellationRequested();

                BuildVersion buildVersion;

                Build buildToInsert;
                Build latestBuild = null;
                bool  retainBuild = false;

                // Get the version from DevOps Pipelines queue, e.g. Roslyn-Main-Signed-Release.
                if (string.IsNullOrEmpty(Options.SpecificBuild))
                {
                    buildToInsert = await GetLatestPassedComponentBuildAsync(cancellationToken);

                    buildVersion = BuildVersion.FromTfsBuildNumber(buildToInsert.BuildNumber, Options.ComponentBuildQueueName);
                    Console.WriteLine("Found " + buildToInsert.Definition.Name + " build number " + buildVersion);

                    //  Get the latest build, whether passed or failed.  If the buildToInsert has already been inserted but
                    //  there is a later failing build, then send an error
                    latestBuild = await GetLatestComponentBuildAsync(cancellationToken);
                }
                else
                {
                    buildVersion  = BuildVersion.FromString(Options.SpecificBuild);
                    buildToInsert = await GetSpecificComponentBuildAsync(buildVersion, cancellationToken);
                }

                var insertionArtifacts = await GetInsertionArtifactsAsync(buildToInsert, cancellationToken);

                cancellationToken.ThrowIfCancellationRequested();

                // *********** Look up existing PR ********************
                var gitClient = VisualStudioRepoConnection.GetClient <GitHttpClient>();
                var branches  = await gitClient.GetRefsAsync(
                    VSRepoId,
                    filter : $"heads/{Options.VisualStudioBranchName}",
                    cancellationToken : cancellationToken);

                var baseBranch = branches.Single(b => b.Name == $"refs/heads/{Options.VisualStudioBranchName}");

                var pullRequestId = Options.UpdateExistingPr;
                var useExistingPr = pullRequestId != 0;

                GitPullRequest pullRequest;
                string         insertionBranchName;
                if (useExistingPr)
                {
                    pullRequest = await gitClient.GetPullRequestByIdAsync(pullRequestId, cancellationToken : cancellationToken);

                    insertionBranchName = pullRequest.SourceRefName.Substring("refs/heads/".Length);

                    var refs = await gitClient.GetRefsAsync(VSRepoId, filter : $"heads/{insertionBranchName}", cancellationToken : cancellationToken);

                    var insertionBranch = refs.Single(r => r.Name == $"refs/heads/{insertionBranchName}");

                    if (Options.OverwritePr)
                    {
                        // overwrite existing PR branch back to base before pushing new commit
                        var updateToBase = new GitRefUpdate
                        {
                            OldObjectId = insertionBranch.ObjectId,
                            NewObjectId = baseBranch.ObjectId,
                            Name        = $"refs/heads/{insertionBranchName}"
                        };
                        var results = await gitClient.UpdateRefsAsync(new[] { updateToBase }, VSRepoId, cancellationToken : cancellationToken);

                        foreach (var result in results)
                        {
                            if (!result.Success)
                            {
                                LogError("Failed to overwrite PR: " + result.CustomMessage);
                            }
                        }
                    }
                    else
                    {
                        // not overwriting PR, so the insertion branch is actually the base
                        baseBranch = insertionBranch;
                    }
                }
                else
                {
                    pullRequest         = null;
                    insertionBranchName = GetNewBranchName();
                }

                var allChanges = new List <GitChange>();

                var coreXT = await CoreXT.Load(gitClient, baseBranch.ObjectId);

                if (Options.InsertCoreXTPackages)
                {
                    // ************** Update Nuget Packages For Branch************************
                    cancellationToken.ThrowIfCancellationRequested();
                    Console.WriteLine($"Updating Nuget Packages");
                    bool success;
                    (success, newPackageFiles) = UpdatePackages(
                        buildVersion,
                        coreXT,
                        insertionArtifacts.GetPackagesDirectory(),
                        Options.SkipCoreXTPackages,
                        cancellationToken);
                    retainBuild |= success;

                    // *********** Copy OptimizationInputs.props file ***********************
                    foreach (var propsFile in insertionArtifacts.GetOptProfPropertyFiles())
                    {
                        var propsFilename = Path.GetFileName(propsFile);
                        if (propsFilename == "dotnet-roslyn.props")
                        {
                            // Since the propsFilename is based on repo name, during Roslyn's transition from inserting
                            // from GH dotnet/roslyn builds to inserting from dnceng dotnet-roslyn builds, this will
                            // ensure that we look for the proper props filename.
                            propsFilename = "dotnet.roslyn.props";
                        }

                        var targetFilePath = $"src/Tests/config/runsettings/Official/OptProf/External/{propsFilename}";

                        var version = new GitVersionDescriptor {
                            VersionType = GitVersionType.Commit, Version = baseBranch.ObjectId
                        };
                        var stream = await gitClient.GetItemContentAsync(VSRepoId, targetFilePath, download : true, versionDescriptor : version);

                        var originalContent = new StreamReader(stream).ReadToEnd();

                        var newContent = File.ReadAllText(propsFile);

                        if (GetChangeOpt(targetFilePath, originalContent, newContent) is GitChange change)
                        {
                            allChanges.Add(change);
                        }
                    }
                }

                if (Options.UpdateCoreXTLibraries || Options.UpdateAssemblyVersions)
                {
                    // ************** Update assembly versions ************************
                    cancellationToken.ThrowIfCancellationRequested();
                    Console.WriteLine($"Updating assembly versions");
                    if (await UpdateAssemblyVersionsOpt(gitClient, baseBranch.ObjectId, insertionArtifacts) is GitChange assemblyVersionChange)
                    {
                        allChanges.Add(assemblyVersionChange);
                    }

                    // if we got this far then we definitely need to retain this build
                    retainBuild = true;
                }

                // *********** Update toolset ********************
                if (Options.InsertToolset)
                {
                    UpdateToolsetPackage(coreXT, insertionArtifacts, buildVersion);
                    retainBuild = true;
                }

                // ************ Update .corext\Configs\default.config ********************
                cancellationToken.ThrowIfCancellationRequested();
                Console.WriteLine($"Updating CoreXT default.config and props files under src/ConfigData/Packages");
                foreach (var configChange in coreXT.SaveConfigs())
                {
                    if (configChange is not null)
                    {
                        allChanges.Add(configChange);
                    }
                }

                // *********** Update .corext\Configs\components.json ********************

                BuildVersion oldComponentVersion = default;
                if (Options.InsertWillowPackages)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    Console.WriteLine($"Updating CoreXT components file");

                    var components = GetLatestBuildComponents(buildToInsert, insertionArtifacts, cancellationToken);
                    var shouldSave = false;
                    foreach (var newComponent in components)
                    {
                        if (coreXT.TryGetComponentByName(newComponent.Name, out var oldComponent))
                        {
                            if (oldComponent.BuildVersion != default)
                            {
                                oldComponentVersion = oldComponent.BuildVersion;
                            }
                            coreXT.UpdateComponent(newComponent);
                            shouldSave = true;
                        }
                    }
                    if (shouldSave)
                    {
                        var allComponentChanges = coreXT.SaveComponents();
                        allChanges.AddRange(allComponentChanges);
                        retainBuild = true;
                    }
                }

                // ************* Ensure the build is retained on the servers *************
                if (Options.RetainInsertedBuild && retainBuild && !buildToInsert.KeepForever.GetValueOrDefault())
                {
                    await RetainComponentBuild(buildToInsert);
                }

                // ************* Bail out if there are no changes ************************
                if (!allChanges.Any() && options.CherryPick.IsDefaultOrEmpty)
                {
                    LogWarning("No meaningful changes since the last insertion was merged. PR will not be created or updated.");
                    return(true, 0);
                }

                // ********************* Create push *************************************
                var currentCommit = baseBranch.ObjectId;
                if (allChanges.Any())
                {
                    var insertionBranchUpdate = new GitRefUpdate
                    {
                        Name        = $"refs/heads/{insertionBranchName}",
                        OldObjectId = baseBranch.ObjectId
                    };

                    var commit = new GitCommitRef
                    {
                        Comment = $"Updating {Options.InsertionName} to {buildVersion}",
                        Changes = allChanges
                    };
                    var push = new GitPush
                    {
                        RefUpdates = new[] { insertionBranchUpdate },
                        Commits    = new[] { commit }
                    };
                    push = await gitClient.CreatePushAsync(push, VSRepoId, cancellationToken : cancellationToken);

                    currentCommit = push.Commits.Single().CommitId;
                }

                // ********************* Cherry-pick VS commits *****************************
                var cherryPickCommits = Options.CherryPick;
                if (!cherryPickCommits.IsDefaultOrEmpty)
                {
                    Console.WriteLine("Cherry-picking the following VS commits:");
                    foreach (var cherryPickCommit in cherryPickCommits)
                    {
                        var gc = await gitClient.GetCommitAsync(cherryPickCommit, VSRepoId, cancellationToken : cancellationToken);

                        Console.WriteLine("- " + gc.RemoteUrl);
                    }
                    var commitRefs = cherryPickCommits.Select(id => new GitCommitRef()
                    {
                        CommitId = id
                    }).ToArray();

                    var cherryPickBranchName = $"{insertionBranchName}-cherry-pick-{DateTime.Now:yyyyMMddHHmmss}";
                    var cherryPickArgs       = new GitAsyncRefOperationParameters()
                    {
                        Source = new GitAsyncRefOperationSource()
                        {
                            CommitList = commitRefs
                        },
                        OntoRefName      = $"refs/heads/{insertionBranchName}",
                        GeneratedRefName = $"refs/heads/{cherryPickBranchName}"
                    };
                    // Cherry-pick VS commits into insertion branch.
                    var cherryPick = await gitClient.CreateCherryPickAsync(cherryPickArgs, Options.VisualStudioRepoProjectName, VSRepoId, cancellationToken : cancellationToken);

                    while (cherryPick.Status < GitAsyncOperationStatus.Completed)
                    {
                        Console.WriteLine($"Cherry-pick progress: {cherryPick.DetailedStatus?.Progress ?? 0:P}");
                        await Task.Delay(5000);

                        cherryPick = await gitClient.GetCherryPickAsync(options.VisualStudioRepoProjectName, cherryPick.CherryPickId, VSRepoId, cancellationToken : cancellationToken);
                    }
                    Console.WriteLine($"Cherry-pick status: {cherryPick.Status}");

                    if (cherryPick.Status == GitAsyncOperationStatus.Completed)
                    {
                        var cherryPickBranch = await gitClient.GetBranchAsync(VSRepoId, cherryPickBranchName, cancellationToken : cancellationToken);

                        var addCherryPickedCommits = new GitRefUpdate
                        {
                            OldObjectId = currentCommit,
                            NewObjectId = cherryPickBranch.Commit.CommitId,
                            Name        = $"refs/heads/{insertionBranchName}"
                        };
                        var results = await gitClient.UpdateRefsAsync(new[] { addCherryPickedCommits }, VSRepoId, cancellationToken : cancellationToken);

                        foreach (var result in results)
                        {
                            if (!result.Success)
                            {
                                LogError("Failed to reset ref to cherry-pick branch: " + result.CustomMessage);
                            }
                        }
                    }
                    else
                    {
                        LogError("Cherry-picking failed: " + cherryPick.DetailedStatus.FailureMessage);
                    }
                }

                // ********************* Create pull request *****************************
                var oldBuild = await GetSpecificComponentBuildAsync(oldComponentVersion, cancellationToken);

                var prDescriptionMarkdown = CreatePullRequestDescription(oldBuild, buildToInsert, useMarkdown: true);

                if (buildToInsert.Result == BuildResult.PartiallySucceeded)
                {
                    prDescriptionMarkdown += Environment.NewLine + ":warning: The build being inserted has partially succeeded.";
                }

                if (!useExistingPr || Options.OverwritePr)
                {
                    try
                    {
                        var nl = Environment.NewLine;
                        if (oldBuild is null)
                        {
                            prDescriptionMarkdown += $"{nl}---{nl}Unable to find details for previous build ({oldComponentVersion}){nl}";
                        }
                        else
                        {
                            var(changes, diffLink) = await GetChangesBetweenBuildsAsync(oldBuild, buildToInsert, cancellationToken);

                            var diffDescription = changes.Any()
                                ? $"[View Complete Diff of Changes]({diffLink})"
                                : "No source changes since previous insertion";

                            prDescriptionMarkdown += nl + "---" + nl + diffDescription + nl;
                            prDescriptionMarkdown  = AppendChangesToDescription(prDescriptionMarkdown, oldBuild ?? buildToInsert, changes);
                        }
                    }
                    catch (Exception e)
                    {
                        LogWarning("Failed to create diff links.");
                        LogWarning(e.Message);
                    }
                }

                if (useExistingPr)
                {
                    try
                    {
                        if (Options.OverwritePr)
                        {
                            pullRequest = await OverwritePullRequestAsync(pullRequestId, prDescriptionMarkdown, buildVersion.ToString(), cancellationToken);
                        }
                        pullRequestId = pullRequest.PullRequestId;
                    }
                    catch (Exception ex)
                    {
                        LogError($"Unable to update pull request for '{pullRequest.SourceRefName}'");
                        LogError(ex);
                        return(false, 0);
                    }
                }
                else
                {
                    // create a new PR
                    Console.WriteLine($"Create Pull Request");
                    try
                    {
                        // If this insertion was queued for PR validation, for a dev branch, for a feature branch,
                        // or if no default reviewer is specified, then add the build queuer as a reviewer.
                        var  isPrValidation       = !string.IsNullOrEmpty(GetBuildPRNumber(buildToInsert));
                        var  isDevOrFeatureBranch = Options.ComponentBranchName.StartsWith("dev/") || Options.ComponentBranchName.StartsWith("features/");
                        bool hasReviewer          = !string.IsNullOrEmpty(Options.ReviewerGUID);

                        // Easiest way to get the reviewer GUIDs is to create a PR search in AzDo
                        // You'll get something like https://dev.azure.com/devdiv/DevDiv/_git/VS/pullrequests?_a=active&createdBy=GUID-here
                        var reviewerId = (isPrValidation || isDevOrFeatureBranch) || !hasReviewer
                            ? buildToInsert.RequestedBy.Id
                            : Options.ReviewerGUID;

                        pullRequest = await CreateVSPullRequestAsync(insertionBranchName, prDescriptionMarkdown, buildVersion.ToString(), reviewerId, cancellationToken);

                        if (pullRequest == null)
                        {
                            LogError($"Unable to create pull request for '{insertionBranchName}'");
                            return(false, 0);
                        }

                        pullRequestId = pullRequest.PullRequestId;
                    }
                    catch (Exception ex)
                    {
                        LogError($"Unable to create pull request for '{insertionBranchName}'");
                        LogError(ex);
                        return(false, 0);
                    }
                }

                // ********************* Create validation build *****************************
                if (Options.QueueValidationBuild)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    Console.WriteLine($"Create Validation Build");
                    try
                    {
                        if (Options.CreateDraftPr)
                        {
                            // When creating Draft PRs no policies are automatically started.
                            // If we do not queue a CloudBuild the Perf DDRITs request will
                            // spin waiting for a build to test against until it timesout.
                            await QueueVSBuildPolicy(pullRequest, "CloudBuild - PR");
                        }

                        await QueueVSBuildPolicy(pullRequest, "Request Perf DDRITs");
                    }
                    catch (Exception ex)
                    {
                        LogWarning($"Unable to create a CloudBuild validation build for '{insertionBranchName}'");
                        LogWarning(ex);
                    }

                    if (Options.CreateDraftPr)
                    {
                        // When creating Draft PRs no policies are automatically started.
                        await TryQueueVSBuildPolicy(pullRequest, "Insertion Hash Check", insertionBranchName);
                        await TryQueueVSBuildPolicy(pullRequest, "Insertion Sign Check", insertionBranchName);
                        await TryQueueVSBuildPolicy(pullRequest, "Insertion Symbol Check", insertionBranchName);
                    }
                }

                // ********************* Set PR to Auto-Complete *****************************
                if (Options.SetAutoComplete)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    Console.WriteLine($"Set PR to Auto-Complete");
                    try
                    {
                        var prDescriptionText = CreatePullRequestDescription(oldBuild, buildToInsert, useMarkdown: false);
                        await SetAutoCompleteAsync(pullRequest, prDescriptionText, cancellationToken);
                    }
                    catch (Exception ex)
                    {
                        LogWarning($"Unable to Set PR to Auto-Complete for '{insertionBranchName}'");
                        LogWarning(ex);
                    }
                }

                return(true, pullRequestId);
            }
            catch (Exception ex)
            {
                LogError(ex);
                return(false, 0);
            }
            finally
            {
                Options = null;
            }
        }