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); }
/// <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); }
/// <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); }
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)); }
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); }
/// <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 : ""); }
/// <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); } }
/// <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); } }
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); } }
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; } }
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(); }
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; } }