public async Task CreateBranch(string branchName, string sourceBranchName, Guid repositoryId)
        {
            var gitClient = _connection.GetClient <GitHttpClient>();

            if (!branchName.StartsWith("refs/heads/"))
            {
                branchName = $"refs/heads/{branchName}";
            }

            var sourceRef = await GetBranchRef(sourceBranchName, repositoryId);

            if (sourceRef == null)
            {
                throw new Exception("Source branch ref not found");
            }

            var gitRef = new GitRefUpdate
            {
                Name        = branchName,
                IsLocked    = false,
                OldObjectId = new string('0', 40),
                NewObjectId = sourceRef.ObjectId
            };

            var gitRefUpdate = await gitClient.UpdateRefsAsync(new[] { gitRef }, repositoryId);
        }
示例#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);
        }
示例#3
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);
        }
示例#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);
        }
示例#5
0
        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));
        }
示例#7
0
        public async Task CreateBranch(string projectName, string repositoryName, string branchName)
        {
            string        refId             = new string('0', 40);
            string        defaultBranchName = "heads/master";
            GitRepository repo = null;

            try
            {
                repo = await GetRepository(projectName, repositoryName);
            }
            catch (Exception ex)
            {
                if (repo == null)
                {
                    throw new Exception($"Repository does not exist: {repositoryName}", ex);
                }
            }

            try
            {
                List <GitRef> refs = await Git.GetRefsAsync(repo.Id, filter : defaultBranchName);

                if (refs.Count > 0)
                {
                    GitRef defaultBranch = refs.First();
                    refId = defaultBranch.ObjectId;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"Could not get reference to default branch; repositoryName = {repositoryName}, branchName = {defaultBranchName}", ex);
            }

            GitRefUpdate refUpdate = new GitRefUpdate()
            {
                Name         = $"refs/heads/{branchName}",
                NewObjectId  = refId,
                OldObjectId  = new string('0', 40),
                IsLocked     = false,
                RepositoryId = repo.Id
            };

            try
            {
                await Git.UpdateRefsAsync(new GitRefUpdate[] { refUpdate }, repositoryId : repo.Id);
            }
            catch (Exception ex)
            {
                throw new Exception($"Could not create new branch; repositoryName = {repositoryName}, branchName = {branchName}", ex);
            }
        }
        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);
        }
示例#9
0
        /// <summary>
        /// Lock or unlock branch
        /// </summary>
        /// <param name="teamProjectName"></param>
        /// <param name="gitRepoName"></param>
        /// <param name="targetBranch"></param>
        /// <param name="lockit"></param>
        private static void LockBranch(string teamProjectName, string gitRepoName, string targetBranch, bool lockit = true)
        {
            var gitBranches = GitClient.GetRefsAsync(teamProjectName, gitRepoName, "heads/" + targetBranch).Result;

            if (gitBranches.Count != 1)
            {
                return;
            }

            GitRefUpdate refUpdate = new GitRefUpdate();

            refUpdate.IsLocked = lockit;

            var lockResult = GitClient.UpdateRefAsync(refUpdate, project: teamProjectName, repositoryId: gitRepoName, filter: "heads/" + targetBranch).Result;

            Console.WriteLine("Branch {0} is {1} {2}",
                              lockResult.Name,
                              (lockResult.IsLocked) ? "locked" : "not locked",
                              (lockResult.IsLocked) ? "by " + lockResult.IsLockedBy.DisplayName : "");
        }
示例#10
0
        /// <summary>
        /// Remove tag
        /// </summary>
        /// <param name="teamProjectName"></param>
        /// <param name="gitRepoName"></param>
        /// <param name="tagName"></param>
        private static void RemoveTag(string teamProjectName, string gitRepoName, string tagName)
        {
            var tags = GitClient.GetRefsAsync(teamProjectName, gitRepoName, "tags/" + tagName).Result;

            if (tags.Count != 1)
            {
                return;
            }

            GitRefUpdate refUpdate = new GitRefUpdate();

            refUpdate.OldObjectId = tags[0].ObjectId;
            refUpdate.NewObjectId = "0000000000000000000000000000000000000000";
            refUpdate.Name        = "refs/tags/" + tagName;

            var updateResult = GitClient.UpdateRefsAsync(new GitRefUpdate[] { refUpdate }, project: teamProjectName, repositoryId: gitRepoName).Result;

            foreach (var update in updateResult)
            {
                Console.WriteLine("Tag was removed {0}", update.Name);
            }
        }
示例#11
0
        /// <summary>
        /// Remove branch
        /// </summary>
        /// <param name="teamProjectName"></param>
        /// <param name="gitRepoName"></param>
        /// <param name="targetBranch"></param>
        private static void RemoveBranch(string teamProjectName, string gitRepoName, string targetBranch)
        {
            var gitBranches = GitClient.GetRefsAsync(teamProjectName, gitRepoName, "heads/" + targetBranch).Result;

            if (gitBranches.Count != 1)
            {
                return;
            }

            GitRefUpdate refUpdate = new GitRefUpdate();

            refUpdate.OldObjectId = gitBranches[0].ObjectId;
            refUpdate.NewObjectId = "0000000000000000000000000000000000000000";
            refUpdate.Name        = "refs/heads/" + targetBranch;

            var updateResult = GitClient.UpdateRefsAsync(new GitRefUpdate[] { refUpdate }, project: teamProjectName, repositoryId: gitRepoName).Result;

            foreach (var update in updateResult)
            {
                Console.WriteLine("Branch was removed {0}", update.Name);
            }
        }
示例#12
0
        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);
        }
示例#13
0
        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);
            }
        }
示例#14
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;
            }
        }
示例#17
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();
        }
示例#18
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;
            }
        }