From be9e0671c042aad3dc977cb91f88f27f7bcc8af5 Mon Sep 17 00:00:00 2001 From: ksacek Date: Mon, 28 Jul 2025 15:06:12 +0200 Subject: [PATCH 01/11] Update the AddTeamToRepo command to support GHEC Data Residency --- src/Octoshift/Services/GithubApi.cs | 2 +- .../AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs | 2 +- .../Commands/AddTeamToRepo/AddTeamToRepoCommandTests.cs | 3 ++- src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommand.cs | 8 ++++++-- .../Commands/AddTeamToRepo/AddTeamToRepoCommandArgs.cs | 1 + .../Commands/AddTeamToRepo/AddTeamToRepoCommandHandler.cs | 2 +- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Octoshift/Services/GithubApi.cs b/src/Octoshift/Services/GithubApi.cs index bd10cf540..2e7a726c3 100644 --- a/src/Octoshift/Services/GithubApi.cs +++ b/src/Octoshift/Services/GithubApi.cs @@ -213,7 +213,7 @@ public virtual async Task AddTeamSync(string org, string teamName, string groupI await _client.PatchAsync(url, payload); } - public virtual async Task AddTeamToRepo(string org, string repo, string teamSlug, string role) + public virtual async Task AddTeamToRepo(string org, string repo, string teamSlug, string role, string targetApiUrl = null) { var url = $"{_apiUrl}/orgs/{org.EscapeDataString()}/teams/{teamSlug.EscapeDataString()}/repos/{org.EscapeDataString()}/{repo.EscapeDataString()}"; var payload = new { permission = role }; diff --git a/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs b/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs index d61ddb33c..186ac867b 100644 --- a/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs +++ b/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs @@ -39,6 +39,6 @@ public async Task Happy_Path() }; await _handler.Handle(args); - _mockGithubApi.Verify(x => x.AddTeamToRepo(GITHUB_ORG, GITHUB_REPO, teamSlug, role)); + _mockGithubApi.Verify(x => x.AddTeamToRepo(GITHUB_ORG, GITHUB_REPO, teamSlug, role,null)); } } diff --git a/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandTests.cs b/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandTests.cs index a0f421e12..ac9dae6dd 100644 --- a/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandTests.cs +++ b/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandTests.cs @@ -33,7 +33,7 @@ public void Should_Have_Options() var command = new AddTeamToRepoCommand(); Assert.NotNull(command); Assert.Equal("add-team-to-repo", command.Name); - Assert.Equal(6, command.Options.Count); + Assert.Equal(7, command.Options.Count); TestHelpers.VerifyCommandOption(command.Options, "github-org", true); TestHelpers.VerifyCommandOption(command.Options, "github-repo", true); @@ -41,6 +41,7 @@ public void Should_Have_Options() TestHelpers.VerifyCommandOption(command.Options, "role", true); TestHelpers.VerifyCommandOption(command.Options, "github-pat", false); TestHelpers.VerifyCommandOption(command.Options, "verbose", false); + TestHelpers.VerifyCommandOption(_command.Options, "target-api-url", false); } [Fact] diff --git a/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommand.cs b/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommand.cs index 3afa0563a..d45e89f45 100644 --- a/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommand.cs +++ b/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommand.cs @@ -21,6 +21,7 @@ public AddTeamToRepoCommand() : base( AddOption(Role.FromAmong("pull", "push", "admin", "maintain", "triage")); AddOption(GithubPat); AddOption(Verbose); + AddOption(TargetApiUrl); } public Option GithubOrg { get; } = new("--github-org") @@ -42,7 +43,10 @@ public AddTeamToRepoCommand() : base( }; public Option GithubPat { get; } = new("--github-pat"); public Option Verbose { get; } = new("--verbose"); - + public Option TargetApiUrl { get; } = new("--target-api-url") + { + Description = "The URL of the target API, if not migrating to github.com. Defaults to https://api.github.com" + }; public override AddTeamToRepoCommandHandler BuildHandler(AddTeamToRepoCommandArgs args, IServiceProvider sp) { if (args is null) @@ -57,7 +61,7 @@ public override AddTeamToRepoCommandHandler BuildHandler(AddTeamToRepoCommandArg var log = sp.GetRequiredService(); var targetGithubApiFactory = sp.GetRequiredService(); - var githubApi = targetGithubApiFactory.Create(targetPersonalAccessToken: args.GithubPat); + var githubApi = targetGithubApiFactory.Create(apiUrl: args.TargetApiUrl,targetPersonalAccessToken: args.GithubPat); return new AddTeamToRepoCommandHandler(log, githubApi); } diff --git a/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandArgs.cs b/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandArgs.cs index a230c54ae..57b8ebebb 100644 --- a/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandArgs.cs +++ b/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandArgs.cs @@ -10,5 +10,6 @@ public class AddTeamToRepoCommandArgs : CommandArgs public string Role { get; set; } [Secret] public string GithubPat { get; set; } + public string TargetApiUrl { get; set; } } } diff --git a/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandler.cs b/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandler.cs index 04c00549a..0eb5a65cc 100644 --- a/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandler.cs +++ b/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandler.cs @@ -26,7 +26,7 @@ public async Task Handle(AddTeamToRepoCommandArgs args) _log.LogInformation("Adding team to repo..."); var teamSlug = await _githubApi.GetTeamSlug(args.GithubOrg, args.Team); - await _githubApi.AddTeamToRepo(args.GithubOrg, args.GithubRepo, teamSlug, args.Role); + await _githubApi.AddTeamToRepo(args.GithubOrg, args.GithubRepo, teamSlug, args.Role, args.TargetApiUrl); _log.LogSuccess("Successfully added team to repo"); } From 7d71f7fdeac3cb59268749b229ef25d4ccbd9cf3 Mon Sep 17 00:00:00 2001 From: ksacek Date: Mon, 28 Jul 2025 15:14:56 +0200 Subject: [PATCH 02/11] Added release notes info --- RELEASENOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8b1378917..3f39febe2 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1 +1 @@ - +- Added `--ghes-api-url` as an optional arg to the `add-team-to-repo` From 7bc7ceed7a0e8bd98253627a9d6609564e22db1a Mon Sep 17 00:00:00 2001 From: ksacek Date: Mon, 28 Jul 2025 15:19:01 +0200 Subject: [PATCH 03/11] Add target-api-url to add-team-to-repo into generate-script action --- .../GenerateScript/GenerateScriptCommandHandler.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs index 335993d0a..f99709ed1 100644 --- a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -166,8 +166,8 @@ private async Task GenerateSequentialScript(IDictionary AppendLine(content, Exec(LockAdoRepoScript(adoOrg, adoTeamProject, adoRepo.Name))); AppendLine(content, Exec(MigrateRepoScript(adoOrg, adoTeamProject, adoRepo.Name, githubOrg, githubRepo, true, adoServerUrl, targetApiUrl))); AppendLine(content, Exec(DisableAdoRepoScript(adoOrg, adoTeamProject, adoRepo.Name))); - AppendLine(content, Exec(AddMaintainersToGithubRepoScript(adoTeamProject, githubOrg, githubRepo))); - AppendLine(content, Exec(AddAdminsToGithubRepoScript(adoTeamProject, githubOrg, githubRepo))); + AppendLine(content, Exec(AddMaintainersToGithubRepoScript(adoTeamProject, githubOrg, githubRepo, targetApiUrl))); + AppendLine(content, Exec(AddAdminsToGithubRepoScript(adoTeamProject, githubOrg, githubRepo, targetApiUrl))); AppendLine(content, Exec(DownloadMigrationLogScript(githubOrg, githubRepo, targetApiUrl))); foreach (var adoPipeline in await _adoInspectorService.GetPipelines(adoOrg, adoTeamProject, adoRepo.Name)) @@ -360,14 +360,14 @@ private string CreateGithubAdminsTeamScript(string adoTeamProject, string github ? $"gh ado2gh create-team{(targetApiUrl.HasValue() ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-org \"{githubOrg}\" --team-name \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Admins\"{(_log.Verbose ? " --verbose" : string.Empty)}{(linkIdpGroups ? $" --idp-group \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Admins\"" : string.Empty)}" : null; - private string AddMaintainersToGithubRepoScript(string adoTeamProject, string githubOrg, string githubRepo) => + private string AddMaintainersToGithubRepoScript(string adoTeamProject, string githubOrg, string githubRepo, string targetApiUrl) => _generateScriptOptions.CreateTeams - ? $"gh ado2gh add-team-to-repo --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\" --team \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Maintainers\" --role \"maintain\"{(_log.Verbose ? " --verbose" : string.Empty)}" + ? $"gh ado2gh add-team-to-repo{(targetApiUrl.HasValue() ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\" --team \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Maintainers\" --role \"maintain\"{(_log.Verbose ? " --verbose" : string.Empty)}" : null; - private string AddAdminsToGithubRepoScript(string adoTeamProject, string githubOrg, string githubRepo) => + private string AddAdminsToGithubRepoScript(string adoTeamProject, string githubOrg, string githubRepo, string targetApiUrl) => _generateScriptOptions.CreateTeams - ? $"gh ado2gh add-team-to-repo --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\" --team \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Admins\" --role \"admin\"{(_log.Verbose ? " --verbose" : string.Empty)}" + ? $"gh ado2gh add-team-to-repo{(targetApiUrl.HasValue() ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\" --team \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Admins\" --role \"admin\"{(_log.Verbose ? " --verbose" : string.Empty)}" : null; private string RewireAzurePipelineScript(string adoOrg, string adoTeamProject, string adoPipeline, string githubOrg, string githubRepo, string appId) => From ea5cf7dab6c8b21ce61c6ddc8a3d5c29b9f8c555 Mon Sep 17 00:00:00 2001 From: Kamil Sacek Date: Mon, 28 Jul 2025 15:23:11 +0200 Subject: [PATCH 04/11] Update src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommand.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommand.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommand.cs b/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommand.cs index d45e89f45..9c86d9553 100644 --- a/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommand.cs +++ b/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommand.cs @@ -61,7 +61,7 @@ public override AddTeamToRepoCommandHandler BuildHandler(AddTeamToRepoCommandArg var log = sp.GetRequiredService(); var targetGithubApiFactory = sp.GetRequiredService(); - var githubApi = targetGithubApiFactory.Create(apiUrl: args.TargetApiUrl,targetPersonalAccessToken: args.GithubPat); + var githubApi = targetGithubApiFactory.Create(apiUrl: args.TargetApiUrl, targetPersonalAccessToken: args.GithubPat); return new AddTeamToRepoCommandHandler(log, githubApi); } From 1c999a62821f8a3c95bb2de44c0727796ba73aa4 Mon Sep 17 00:00:00 2001 From: Kamil Sacek Date: Mon, 28 Jul 2025 15:23:30 +0200 Subject: [PATCH 05/11] Update src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandTests.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandTests.cs b/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandTests.cs index ac9dae6dd..d3f38687e 100644 --- a/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandTests.cs +++ b/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandTests.cs @@ -41,7 +41,7 @@ public void Should_Have_Options() TestHelpers.VerifyCommandOption(command.Options, "role", true); TestHelpers.VerifyCommandOption(command.Options, "github-pat", false); TestHelpers.VerifyCommandOption(command.Options, "verbose", false); - TestHelpers.VerifyCommandOption(_command.Options, "target-api-url", false); + TestHelpers.VerifyCommandOption(command.Options, "target-api-url", false); } [Fact] From a6946491c1c8ae099977a255e787d1b68ebb7b7f Mon Sep 17 00:00:00 2001 From: Kamil Sacek Date: Mon, 28 Jul 2025 15:23:41 +0200 Subject: [PATCH 06/11] Update src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs b/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs index 186ac867b..a6a204f44 100644 --- a/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs +++ b/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs @@ -39,6 +39,6 @@ public async Task Happy_Path() }; await _handler.Handle(args); - _mockGithubApi.Verify(x => x.AddTeamToRepo(GITHUB_ORG, GITHUB_REPO, teamSlug, role,null)); + _mockGithubApi.Verify(x => x.AddTeamToRepo(GITHUB_ORG, GITHUB_REPO, teamSlug, role, null)); } } From 413bd7456dbbe82b94522022b9b038d6719cf74f Mon Sep 17 00:00:00 2001 From: ksacek Date: Mon, 28 Jul 2025 15:25:42 +0200 Subject: [PATCH 07/11] Remove unneeded param --- src/Octoshift/Services/GithubApi.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Octoshift/Services/GithubApi.cs b/src/Octoshift/Services/GithubApi.cs index 2e7a726c3..bd10cf540 100644 --- a/src/Octoshift/Services/GithubApi.cs +++ b/src/Octoshift/Services/GithubApi.cs @@ -213,7 +213,7 @@ public virtual async Task AddTeamSync(string org, string teamName, string groupI await _client.PatchAsync(url, payload); } - public virtual async Task AddTeamToRepo(string org, string repo, string teamSlug, string role, string targetApiUrl = null) + public virtual async Task AddTeamToRepo(string org, string repo, string teamSlug, string role) { var url = $"{_apiUrl}/orgs/{org.EscapeDataString()}/teams/{teamSlug.EscapeDataString()}/repos/{org.EscapeDataString()}/{repo.EscapeDataString()}"; var payload = new { permission = role }; From d5ff81bd79daaca7466cd320c15789947ddf31a5 Mon Sep 17 00:00:00 2001 From: ksacek Date: Mon, 28 Jul 2025 15:28:01 +0200 Subject: [PATCH 08/11] Remove param in call --- .../Commands/AddTeamToRepo/AddTeamToRepoCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandler.cs b/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandler.cs index 0eb5a65cc..04c00549a 100644 --- a/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandler.cs +++ b/src/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandler.cs @@ -26,7 +26,7 @@ public async Task Handle(AddTeamToRepoCommandArgs args) _log.LogInformation("Adding team to repo..."); var teamSlug = await _githubApi.GetTeamSlug(args.GithubOrg, args.Team); - await _githubApi.AddTeamToRepo(args.GithubOrg, args.GithubRepo, teamSlug, args.Role, args.TargetApiUrl); + await _githubApi.AddTeamToRepo(args.GithubOrg, args.GithubRepo, teamSlug, args.Role); _log.LogSuccess("Successfully added team to repo"); } From 7663e3fec19a95917b4aba65633eea1084d1ddd0 Mon Sep 17 00:00:00 2001 From: ksacek Date: Mon, 28 Jul 2025 15:32:55 +0200 Subject: [PATCH 09/11] Update script calls to include targetApiUrl parameter --- .../Commands/GenerateScript/GenerateScriptCommandHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs index f99709ed1..874dc4615 100644 --- a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -275,8 +275,8 @@ private async Task GenerateParallelScript(IDictionary ap { AppendLine(content, " ExecBatch @("); AppendLine(content, " " + Wrap(DisableAdoRepoScript(adoOrg, adoTeamProject, adoRepo.Name))); - AppendLine(content, " " + Wrap(AddMaintainersToGithubRepoScript(adoTeamProject, githubOrg, githubRepo))); - AppendLine(content, " " + Wrap(AddAdminsToGithubRepoScript(adoTeamProject, githubOrg, githubRepo))); + AppendLine(content, " " + Wrap(AddMaintainersToGithubRepoScript(adoTeamProject, githubOrg, githubRepo, targetApiUrl))); + AppendLine(content, " " + Wrap(AddAdminsToGithubRepoScript(adoTeamProject, githubOrg, githubRepo, targetApiUrl))); AppendLine(content, " " + Wrap(DownloadMigrationLogScript(githubOrg, githubRepo, targetApiUrl))); appIds.TryGetValue(adoOrg, out var appId); From f1dc0cfde0949912953ecd9f943eb6d5fcf22e0a Mon Sep 17 00:00:00 2001 From: ksacek Date: Mon, 28 Jul 2025 15:35:50 +0200 Subject: [PATCH 10/11] Rmove unneeded param in test --- .../Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs b/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs index a6a204f44..d61ddb33c 100644 --- a/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs +++ b/src/OctoshiftCLI.Tests/ado2gh/Commands/AddTeamToRepo/AddTeamToRepoCommandHandlerTests.cs @@ -39,6 +39,6 @@ public async Task Happy_Path() }; await _handler.Handle(args); - _mockGithubApi.Verify(x => x.AddTeamToRepo(GITHUB_ORG, GITHUB_REPO, teamSlug, role, null)); + _mockGithubApi.Verify(x => x.AddTeamToRepo(GITHUB_ORG, GITHUB_REPO, teamSlug, role)); } } From 21f02649871bea7d303926085fbda4312da88989 Mon Sep 17 00:00:00 2001 From: ksacek Date: Mon, 28 Jul 2025 15:58:16 +0200 Subject: [PATCH 11/11] Fix param name in releasenotes --- RELEASENOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 3f39febe2..dde66af18 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1 +1 @@ -- Added `--ghes-api-url` as an optional arg to the `add-team-to-repo` +- Added `--target-api-url` as an optional arg to the `add-team-to-repo`