From 56cdd230e548ea129f799b6de2d4d19ab8f49e5a Mon Sep 17 00:00:00 2001 From: Briana J Date: Thu, 8 Feb 2024 00:55:57 +0000 Subject: [PATCH 01/14] prev PR feednacl use virtual in *CommandBase.cs --- src/Octoshift/Commands/CreateTeam/CreateTeamCommandBase.cs | 2 +- .../GenerateMannequinCsv/GenerateMannequinCsvCommandBase.cs | 2 +- .../Commands/GrantMigratorRole/GrantMigratorRoleCommandBase.cs | 2 +- .../Commands/ReclaimMannequin/ReclaimMannequinCommandBase.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Octoshift/Commands/CreateTeam/CreateTeamCommandBase.cs b/src/Octoshift/Commands/CreateTeam/CreateTeamCommandBase.cs index 3050b5200..1bcfe5416 100644 --- a/src/Octoshift/Commands/CreateTeam/CreateTeamCommandBase.cs +++ b/src/Octoshift/Commands/CreateTeam/CreateTeamCommandBase.cs @@ -22,7 +22,7 @@ public CreateTeamCommandBase() : base(name: "create-team", description: "Creates { Description = "Personal access token of the GitHub target. Overrides GH_PAT environment variable." }; - public Option TargetApiUrl { get; } = new("--target-api-url") + public virtual 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" }; diff --git a/src/Octoshift/Commands/GenerateMannequinCsv/GenerateMannequinCsvCommandBase.cs b/src/Octoshift/Commands/GenerateMannequinCsv/GenerateMannequinCsvCommandBase.cs index b6971166b..6c532b504 100644 --- a/src/Octoshift/Commands/GenerateMannequinCsv/GenerateMannequinCsvCommandBase.cs +++ b/src/Octoshift/Commands/GenerateMannequinCsv/GenerateMannequinCsvCommandBase.cs @@ -37,7 +37,7 @@ public GenerateMannequinCsvCommandBase() : base( { Description = "Personal access token of the GitHub target. Overrides GH_PAT environment variable." }; - public Option TargetApiUrl { get; } = new("--target-api-url") + public virtual 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" }; diff --git a/src/Octoshift/Commands/GrantMigratorRole/GrantMigratorRoleCommandBase.cs b/src/Octoshift/Commands/GrantMigratorRole/GrantMigratorRoleCommandBase.cs index c33e85349..c7f6bf42f 100644 --- a/src/Octoshift/Commands/GrantMigratorRole/GrantMigratorRoleCommandBase.cs +++ b/src/Octoshift/Commands/GrantMigratorRole/GrantMigratorRoleCommandBase.cs @@ -30,7 +30,7 @@ public GrantMigratorRoleCommandBase() : base( IsRequired = false, Description = "The URL of the GitHub Enterprise Server instance, if migrating from GHES. Supports granting access for exports. Can only configure one of --ghes-api-url or --target-api-url at a time." }; - public Option TargetApiUrl { get; } = new("--target-api-url") + public virtual Option TargetApiUrl { get; } = new("--target-api-url") { IsRequired = false, Description = "The URL of the target API, if not migrating to github.com. Defaults to https://api.github.com. Can only configure one of --ghes-api-url or --target-api-url at a time." diff --git a/src/Octoshift/Commands/ReclaimMannequin/ReclaimMannequinCommandBase.cs b/src/Octoshift/Commands/ReclaimMannequin/ReclaimMannequinCommandBase.cs index 145b66e2c..6e8542ef6 100644 --- a/src/Octoshift/Commands/ReclaimMannequin/ReclaimMannequinCommandBase.cs +++ b/src/Octoshift/Commands/ReclaimMannequin/ReclaimMannequinCommandBase.cs @@ -67,7 +67,7 @@ public ReclaimMannequinCommandBase() : base( Description = "Reclaim mannequins immediately without sending an invitation to the user. Only available for Enterprise Managed Users (EMU) organizations. Warning: this is irreversible!" }; - public Option TargetApiUrl { get; } = new("--target-api-url") + public virtual 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" }; From 9749624529a7ac1c390b30a23003a896dd715290 Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 04:57:28 +0000 Subject: [PATCH 02/14] generate script command changes --- .../GenerateScriptCommandHandlerTests.cs | 28 +++++++++++ .../GenerateScriptCommandHandlerTests.cs | 35 ++++++++++++++ .../GenerateScriptCommandHandlerTests.cs | 27 +++++++++++ .../GenerateScript/GenerateScriptCommand.cs | 5 ++ .../GenerateScriptCommandArgs.cs | 1 + .../GenerateScriptCommandHandler.cs | 48 +++++++++---------- .../GenerateScript/GenerateScriptCommand.cs | 5 ++ .../GenerateScriptCommandArgs.cs | 1 + .../GenerateScriptCommandHandler.cs | 3 +- .../GenerateScript/GenerateScriptCommand.cs | 5 ++ .../GenerateScriptCommandArgs.cs | 1 + .../GenerateScriptCommandHandler.cs | 32 ++++++------- 12 files changed, 150 insertions(+), 41 deletions(-) diff --git a/src/OctoshiftCLI.Tests/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs b/src/OctoshiftCLI.Tests/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs index 47327898b..223a0eba0 100644 --- a/src/OctoshiftCLI.Tests/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs +++ b/src/OctoshiftCLI.Tests/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs @@ -102,6 +102,34 @@ public async Task SequentialScript_Single_Repo_No_Options() _scriptOutput.Should().Be(expected); } + [Fact] + public async Task SequentialScript_Single_Repo_With_TargetApiUrl() + { + // Arrange + _mockAdoInspector.Setup(m => m.GetRepoCount()).ReturnsAsync(1); + _mockAdoInspector.Setup(m => m.GetOrgs()).ReturnsAsync(ADO_ORGS); + _mockAdoInspector.Setup(m => m.GetTeamProjects(ADO_ORG)).ReturnsAsync(ADO_TEAM_PROJECTS); + _mockAdoInspector.Setup(m => m.GetRepos(ADO_ORG, ADO_TEAM_PROJECT)).ReturnsAsync(ADO_REPOS); + var targetApiUrl = "https://foo.com/api/v3"; + + // Act + var args = new GenerateScriptCommandArgs + { + GithubOrg = GITHUB_ORG, + AdoOrg = ADO_ORG, + Sequential = true, + Output = new FileInfo("unit-test-output"), + TargetApiUrl = targetApiUrl + }; + await _handler.Handle(args); + + _scriptOutput = TrimNonExecutableLines(_scriptOutput); + var expected = $"Exec {{ gh ado2gh migrate-repo --target-api-url \"{targetApiUrl}\" --ado-org \"{ADO_ORG}\" --ado-team-project \"{ADO_TEAM_PROJECT}\" --ado-repo \"{FOO_REPO}\" --github-org \"{GITHUB_ORG}\" --github-repo \"{ADO_TEAM_PROJECT}-{FOO_REPO}\" --target-repo-visibility private }}"; + + // Assert + _scriptOutput.Should().Be(expected); + } + [Fact] public async Task SequentialScript_Single_Repo_AdoServer() { diff --git a/src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs b/src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs index b8da1b556..1f3be44d6 100644 --- a/src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs +++ b/src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs @@ -517,6 +517,41 @@ public async Task One_Repo_With_Smb() _mockFileSystemProvider.Verify(m => m.WriteAllTextAsync(It.IsAny(), It.Is(script => script.Contains(migrateRepoCommand)))); } +[Fact] + public async Task One_Repo_With_Smb_And_TargetApiUrl() + { + // Arrange + _mockBbsApi.Setup(m => m.GetProjects()).ReturnsAsync(new[] + { + (Id: 1, Key: BBS_FOO_PROJECT_KEY, Name: BBS_FOO_PROJECT_NAME), + }); + _mockBbsApi.Setup(m => m.GetRepos(BBS_FOO_PROJECT_KEY)).ReturnsAsync(new[] + { + (Id: 1, Slug: BBS_FOO_REPO_1_SLUG, Name: BBS_FOO_REPO_1_NAME), + }); + var targetApiUrl = "https://foo.com/api/v3"; + var migrateRepoCommand = $"Exec {{ gh bbs2gh migrate-repo --target-api-url \"{targetApiUrl}\" --bbs-server-url \"{BBS_SERVER_URL}\" --bbs-username \"{BBS_USERNAME}\" --bbs-shared-home \"{BBS_SHARED_HOME}\" --bbs-project \"{BBS_FOO_PROJECT_KEY}\" --bbs-repo \"{BBS_FOO_REPO_1_SLUG}\" --smb-user \"{SMB_USER}\" --smb-domain {SMB_DOMAIN} --github-org \"{GITHUB_ORG}\" --github-repo \"{BBS_FOO_PROJECT_KEY}-{BBS_FOO_REPO_1_SLUG}\" --verbose --target-repo-visibility private }}"; + + // Act + var args = new GenerateScriptCommandArgs + { + BbsServerUrl = BBS_SERVER_URL, + GithubOrg = GITHUB_ORG, + BbsUsername = BBS_USERNAME, + BbsPassword = BBS_PASSWORD, + BbsSharedHome = BBS_SHARED_HOME, + SmbUser = SMB_USER, + SmbDomain = SMB_DOMAIN, + Output = new FileInfo(OUTPUT), + Verbose = true, + TargetApiUrl = targetApiUrl + }; + await _handler.Handle(args); + + // Assert + _mockFileSystemProvider.Verify(m => m.WriteAllTextAsync(It.IsAny(), It.Is(script => script.Contains(migrateRepoCommand)))); + } + [Fact] public async Task One_Repo_With_Smb_And_Archive_Download_Host() { diff --git a/src/OctoshiftCLI.Tests/gei/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs b/src/OctoshiftCLI.Tests/gei/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs index a08c6453e..31ce841eb 100644 --- a/src/OctoshiftCLI.Tests/gei/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs +++ b/src/OctoshiftCLI.Tests/gei/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs @@ -153,6 +153,33 @@ public async Task Sequential_Github_Single_Repo() _script.Should().Be(expected); } + [Fact] + public async Task Sequential_Github_Single_Repo_With_TargetApiUrl() + { + // Arrange + _mockGithubApi + .Setup(m => m.GetRepos(SOURCE_ORG)) + .ReturnsAsync(new[] { (REPO, "private") }); + var targetApiUrl = "https://foo.com/api/v3"; + var expected = $"Exec {{ gh gei migrate-repo --target-api-url \"{targetApiUrl}\" --github-source-org \"{SOURCE_ORG}\" --source-repo \"{REPO}\" --github-target-org \"{TARGET_ORG}\" --target-repo \"{REPO}\" --target-repo-visibility private }}"; + + // Act + var args = new GenerateScriptCommandArgs + { + GithubSourceOrg = SOURCE_ORG, + GithubTargetOrg = TARGET_ORG, + Output = new FileInfo("unit-test-output"), + Sequential = true, + TargetApiUrl = targetApiUrl + }; + await _handler.Handle(args); + + _script = TrimNonExecutableLines(_script); + + // Assert + _script.Should().Be(expected); + } + [Fact] public async Task Sequential_Github_Multiple_Repos() { diff --git a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommand.cs b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommand.cs index d2ebc7dca..9047ffd2f 100644 --- a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommand.cs +++ b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommand.cs @@ -18,6 +18,7 @@ public GenerateScriptCommand() : base( "Note: Expects ADO_PAT env variable or --ado-pat option to be set.") { AddOption(GithubOrg); + AddOption(TargetApiUrl); AddOption(AdoOrg); AddOption(AdoTeamProject); AddOption(AdoServerUrl); @@ -91,6 +92,10 @@ public GenerateScriptCommand() : base( { Description = "Path to a csv file that contains a list of repos to generate a script for. The CSV file should be generated using the inventory-report command." }; + 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 GenerateScriptCommandHandler BuildHandler(GenerateScriptCommandArgs args, IServiceProvider sp) { diff --git a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandArgs.cs b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandArgs.cs index 94e615d08..67581356a 100644 --- a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandArgs.cs +++ b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandArgs.cs @@ -22,5 +22,6 @@ public class GenerateScriptCommandArgs : CommandArgs public bool RewirePipelines { get; set; } public bool All { get; set; } public FileInfo RepoList { get; set; } + public string TargetApiUrl { get; set; } } } diff --git a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs index dee9ebee4..10269b397 100644 --- a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -67,8 +67,8 @@ public async Task Handle(GenerateScriptCommandArgs args) var appIds = _generateScriptOptions.RewirePipelines ? await GetAppIds(_adoApi, args.GithubOrg) : new Dictionary(); var script = args.Sequential - ? await GenerateSequentialScript(appIds, args.GithubOrg, args.AdoServerUrl) - : await GenerateParallelScript(appIds, args.GithubOrg, args.AdoServerUrl); + ? await GenerateSequentialScript(appIds, args.GithubOrg, args.AdoServerUrl, args.TargetApiUrl) + : await GenerateParallelScript(appIds, args.GithubOrg, args.AdoServerUrl, args.TargetApiUrl); _adoInspectorService.OutputRepoListToLog(); @@ -125,7 +125,7 @@ private async Task CheckForDuplicateRepoNames() private string GetRepoMigrationKey(string adoOrg, string githubRepoName) => $"{adoOrg}/{githubRepoName}"; - private async Task GenerateSequentialScript(IDictionary appIds, string githubOrg, string adoServerUrl) + private async Task GenerateSequentialScript(IDictionary appIds, string githubOrg, string adoServerUrl, string targetApiUrl) { var content = new StringBuilder(); @@ -157,8 +157,8 @@ private async Task GenerateSequentialScript(IDictionary continue; } - AppendLine(content, Exec(CreateGithubMaintainersTeamScript(adoTeamProject, githubOrg, _generateScriptOptions.LinkIdpGroups))); - AppendLine(content, Exec(CreateGithubAdminsTeamScript(adoTeamProject, githubOrg, _generateScriptOptions.LinkIdpGroups))); + AppendLine(content, Exec(CreateGithubMaintainersTeamScript(adoTeamProject, githubOrg, _generateScriptOptions.LinkIdpGroups, targetApiUrl))); + AppendLine(content, Exec(CreateGithubAdminsTeamScript(adoTeamProject, githubOrg, _generateScriptOptions.LinkIdpGroups, targetApiUrl))); AppendLine(content, Exec(ShareServiceConnectionScript(adoOrg, adoTeamProject, appId))); foreach (var adoRepo in await _adoInspectorService.GetRepos(adoOrg, adoTeamProject)) @@ -167,13 +167,13 @@ private async Task GenerateSequentialScript(IDictionary AppendLine(content); AppendLine(content, Exec(LockAdoRepoScript(adoOrg, adoTeamProject, adoRepo.Name))); - AppendLine(content, Exec(MigrateRepoScript(adoOrg, adoTeamProject, adoRepo.Name, githubOrg, githubRepo, true, adoServerUrl))); + AppendLine(content, Exec(MigrateRepoScript(adoOrg, adoTeamProject, adoRepo.Name, githubOrg, githubRepo, true, adoServerUrl, targetApiUrl))); AppendLine(content, Exec(DisableAdoRepoScript(adoOrg, adoTeamProject, adoRepo.Name))); AppendLine(content, Exec(ConfigureAutolinkScript(githubOrg, githubRepo, adoOrg, adoTeamProject))); AppendLine(content, Exec(AddMaintainersToGithubRepoScript(adoTeamProject, githubOrg, githubRepo))); AppendLine(content, Exec(AddAdminsToGithubRepoScript(adoTeamProject, githubOrg, githubRepo))); AppendLine(content, Exec(BoardsIntegrationScript(adoOrg, adoTeamProject, githubOrg, githubRepo))); - AppendLine(content, Exec(DownloadMigrationLogScript(githubOrg, githubRepo))); + AppendLine(content, Exec(DownloadMigrationLogScript(githubOrg, githubRepo, targetApiUrl))); foreach (var adoPipeline in await _adoInspectorService.GetPipelines(adoOrg, adoTeamProject, adoRepo.Name)) { @@ -189,7 +189,7 @@ private async Task GenerateSequentialScript(IDictionary return content.ToString(); } - private async Task GenerateParallelScript(IDictionary appIds, string githubOrg, string adoServerUrl) + private async Task GenerateParallelScript(IDictionary appIds, string githubOrg, string adoServerUrl, string targetApiUrl) { var content = new StringBuilder(); AppendLine(content, PWSH_SHEBANG); @@ -230,8 +230,8 @@ private async Task GenerateParallelScript(IDictionary ap continue; } - AppendLine(content, Exec(CreateGithubMaintainersTeamScript(adoTeamProject, githubOrg, _generateScriptOptions.LinkIdpGroups))); - AppendLine(content, Exec(CreateGithubAdminsTeamScript(adoTeamProject, githubOrg, _generateScriptOptions.LinkIdpGroups))); + AppendLine(content, Exec(CreateGithubMaintainersTeamScript(adoTeamProject, githubOrg, _generateScriptOptions.LinkIdpGroups, targetApiUrl))); + AppendLine(content, Exec(CreateGithubAdminsTeamScript(adoTeamProject, githubOrg, _generateScriptOptions.LinkIdpGroups, targetApiUrl))); AppendLine(content, Exec(ShareServiceConnectionScript(adoOrg, adoTeamProject, appId))); // queue up repo migration for each ADO repo @@ -242,7 +242,7 @@ private async Task GenerateParallelScript(IDictionary ap AppendLine(content); AppendLine(content, Exec(LockAdoRepoScript(adoOrg, adoTeamProject, adoRepo.Name))); - AppendLine(content, QueueMigrateRepoScript(adoOrg, adoTeamProject, adoRepo.Name, githubOrg, githubRepo, adoServerUrl)); + AppendLine(content, QueueMigrateRepoScript(adoOrg, adoTeamProject, adoRepo.Name, githubOrg, githubRepo, adoServerUrl, targetApiUrl)); AppendLine(content, $"$RepoMigrations[\"{GetRepoMigrationKey(adoOrg, githubRepo)}\"] = $MigrationID"); } } @@ -266,7 +266,7 @@ private async Task GenerateParallelScript(IDictionary ap AppendLine(content, "$CanExecuteBatch = $false"); AppendLine(content, $"if ($null -ne $RepoMigrations[\"{repoMigrationKey}\"]) {{"); - AppendLine(content, " " + WaitForMigrationScript(repoMigrationKey)); + AppendLine(content, " " + WaitForMigrationScript(repoMigrationKey, targetApiUrl)); AppendLine(content, " $CanExecuteBatch = ($lastexitcode -eq 0)"); AppendLine(content, "}"); @@ -285,7 +285,7 @@ private async Task GenerateParallelScript(IDictionary ap AppendLine(content, " " + Wrap(AddMaintainersToGithubRepoScript(adoTeamProject, githubOrg, githubRepo))); AppendLine(content, " " + Wrap(AddAdminsToGithubRepoScript(adoTeamProject, githubOrg, githubRepo))); AppendLine(content, " " + Wrap(BoardsIntegrationScript(adoOrg, adoTeamProject, githubOrg, githubRepo))); - AppendLine(content, " " + Wrap(DownloadMigrationLogScript(githubOrg, githubRepo))); + AppendLine(content, " " + Wrap(DownloadMigrationLogScript(githubOrg, githubRepo, targetApiUrl))); appIds.TryGetValue(adoOrg, out var appId); foreach (var adoPipeline in await _adoInspectorService.GetPipelines(adoOrg, adoTeamProject, adoRepo.Name)) @@ -357,20 +357,20 @@ private string ConfigureAutolinkScript(string githubOrg, string githubRepo, stri ? $"gh ado2gh configure-autolink --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\" --ado-org \"{adoOrg}\" --ado-team-project \"{adoTeamProject}\"{(_log.Verbose ? " --verbose" : string.Empty)}" : null; - private string MigrateRepoScript(string adoOrg, string adoTeamProject, string adoRepo, string githubOrg, string githubRepo, bool wait, string adoServerUrl) => - $"gh ado2gh migrate-repo --ado-org \"{adoOrg}\" --ado-team-project \"{adoTeamProject}\" --ado-repo \"{adoRepo}\" --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\"{(_log.Verbose ? " --verbose" : string.Empty)}{(wait ? string.Empty : " --queue-only")} --target-repo-visibility private{(adoServerUrl.IsNullOrWhiteSpace() ? string.Empty : $" --ado-server-url \"{adoServerUrl}\"")}"; + private string MigrateRepoScript(string adoOrg, string adoTeamProject, string adoRepo, string githubOrg, string githubRepo, bool wait, string adoServerUrl, string targetApiUrl) => + $"gh ado2gh migrate-repo{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --ado-org \"{adoOrg}\" --ado-team-project \"{adoTeamProject}\" --ado-repo \"{adoRepo}\" --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\"{(_log.Verbose ? " --verbose" : string.Empty)}{(wait ? string.Empty : " --queue-only")} --target-repo-visibility private{(adoServerUrl.IsNullOrWhiteSpace() ? string.Empty : $" --ado-server-url \"{adoServerUrl}\"")}"; - private string QueueMigrateRepoScript(string adoOrg, string adoTeamProject, string adoRepo, string githubOrg, string githubRepo, string adoServerUrl) => - $"$MigrationID = {ExecAndGetMigrationId(MigrateRepoScript(adoOrg, adoTeamProject, adoRepo, githubOrg, githubRepo, false, adoServerUrl))}"; + private string QueueMigrateRepoScript(string adoOrg, string adoTeamProject, string adoRepo, string githubOrg, string githubRepo, string adoServerUrl, string targetApiUrl) => + $"$MigrationID = {ExecAndGetMigrationId(MigrateRepoScript(adoOrg, adoTeamProject, adoRepo, githubOrg, githubRepo, false, adoServerUrl, targetApiUrl))}"; - private string CreateGithubMaintainersTeamScript(string adoTeamProject, string githubOrg, bool linkIdpGroups) => + private string CreateGithubMaintainersTeamScript(string adoTeamProject, string githubOrg, bool linkIdpGroups, string targetApiUrl) => _generateScriptOptions.CreateTeams - ? $"gh ado2gh create-team --github-org \"{githubOrg}\" --team-name \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Maintainers\"{(_log.Verbose ? " --verbose" : string.Empty)}{(linkIdpGroups ? $" --idp-group \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Maintainers\"" : string.Empty)}" + ? $"gh ado2gh create-team{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-org \"{githubOrg}\" --team-name \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Maintainers\"{(_log.Verbose ? " --verbose" : string.Empty)}{(linkIdpGroups ? $" --idp-group \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Maintainers\"" : string.Empty)}" : null; - private string CreateGithubAdminsTeamScript(string adoTeamProject, string githubOrg, bool linkIdpGroups) => + private string CreateGithubAdminsTeamScript(string adoTeamProject, string githubOrg, bool linkIdpGroups, string targetApiUrl) => _generateScriptOptions.CreateTeams - ? $"gh ado2gh create-team --github-org \"{githubOrg}\" --team-name \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Admins\"{(_log.Verbose ? " --verbose" : string.Empty)}{(linkIdpGroups ? $" --idp-group \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Admins\"" : string.Empty)}" + ? $"gh ado2gh create-team{(!string.IsNullOrEmpty(targetApiUrl) ? $" --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) => @@ -393,11 +393,11 @@ private string BoardsIntegrationScript(string adoOrg, string adoTeamProject, str ? $"gh ado2gh integrate-boards --ado-org \"{adoOrg}\" --ado-team-project \"{adoTeamProject}\" --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\"{(_log.Verbose ? " --verbose" : string.Empty)}" : null; - private string WaitForMigrationScript(string repoMigrationKey) => $"gh ado2gh wait-for-migration --migration-id $RepoMigrations[\"{repoMigrationKey}\"]"; + private string WaitForMigrationScript(string repoMigrationKey, string targetApiUrl) => $"gh ado2gh wait-for-migration{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --migration-id $RepoMigrations[\"{repoMigrationKey}\"]"; - private string DownloadMigrationLogScript(string githubOrg, string githubRepo) => + private string DownloadMigrationLogScript(string githubOrg, string githubRepo, string targetApiUrl) => _generateScriptOptions.DownloadMigrationLogs - ? $"gh ado2gh download-logs --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\"" + ? $"gh ado2gh download-logs{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\"" : null; private string Exec(string script) => Wrap(script, "Exec"); diff --git a/src/bbs2gh/Commands/GenerateScript/GenerateScriptCommand.cs b/src/bbs2gh/Commands/GenerateScript/GenerateScriptCommand.cs index 00861b1c6..b5016f6af 100644 --- a/src/bbs2gh/Commands/GenerateScript/GenerateScriptCommand.cs +++ b/src/bbs2gh/Commands/GenerateScript/GenerateScriptCommand.cs @@ -17,6 +17,7 @@ public GenerateScriptCommand() : base( { AddOption(BbsServerUrl); AddOption(GithubOrg); + AddOption(TargetApiUrl); AddOption(BbsUsername); AddOption(BbsPassword); AddOption(BbsProject); @@ -118,6 +119,10 @@ public GenerateScriptCommand() : base( name: "--no-ssl-verify", description: "Disables SSL verification when communicating with your Bitbucket Server/Data Center instance. All other migration steps will continue to verify SSL. " + "If your Bitbucket instance has a self-signed SSL certificate then setting this flag will allow the migration archive to be exported."); + 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 GenerateScriptCommandHandler BuildHandler(GenerateScriptCommandArgs args, IServiceProvider sp) { diff --git a/src/bbs2gh/Commands/GenerateScript/GenerateScriptCommandArgs.cs b/src/bbs2gh/Commands/GenerateScript/GenerateScriptCommandArgs.cs index caefad809..2e2c6c93f 100644 --- a/src/bbs2gh/Commands/GenerateScript/GenerateScriptCommandArgs.cs +++ b/src/bbs2gh/Commands/GenerateScript/GenerateScriptCommandArgs.cs @@ -26,6 +26,7 @@ public class GenerateScriptCommandArgs : CommandArgs public string AwsRegion { get; set; } public bool KeepArchive { get; set; } public bool NoSslVerify { get; set; } + public string TargetApiUrl { get; set; } public override void Validate(OctoLogger log) { diff --git a/src/bbs2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/bbs2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs index d0c5232dc..68be3956b 100644 --- a/src/bbs2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/bbs2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -134,8 +134,9 @@ private string MigrateGithubRepoScript(GenerateScriptCommandArgs args, string bb var keepArchive = args.KeepArchive ? " --keep-archive" : ""; var noSslVerify = args.NoSslVerify ? " --no-ssl-verify" : ""; var targetRepoVisibility = " --target-repo-visibility private"; + var targetApiUrlOption = args.TargetApiUrl.HasValue() ? $" --target-api-url \"{args.TargetApiUrl}\"" : ""; - return $"gh bbs2gh migrate-repo{bbsServerUrlOption}{bbsUsernameOption}{bbsSharedHomeOption}{bbsProjectOption}{bbsRepoOption}{sshArchiveDownloadOptions}" + + return $"gh bbs2gh migrate-repo{targetApiUrlOption}{bbsServerUrlOption}{bbsUsernameOption}{bbsSharedHomeOption}{bbsProjectOption}{bbsRepoOption}{sshArchiveDownloadOptions}" + $"{smbArchiveDownloadOptions}{githubOrgOption}{githubRepoOption}{verboseOption}{waitOption}{kerberosOption}{awsBucketNameOption}{awsRegionOption}{keepArchive}{noSslVerify}{targetRepoVisibility}"; } diff --git a/src/gei/Commands/GenerateScript/GenerateScriptCommand.cs b/src/gei/Commands/GenerateScript/GenerateScriptCommand.cs index 265bf622a..2e20eae87 100644 --- a/src/gei/Commands/GenerateScript/GenerateScriptCommand.cs +++ b/src/gei/Commands/GenerateScript/GenerateScriptCommand.cs @@ -21,6 +21,7 @@ public GenerateScriptCommand() : base( AddOption(GithubSourceOrg); AddOption(GithubTargetOrg); + AddOption(TargetApiUrl); AddOption(GhesApiUrl); AddOption(AwsBucketName); AddOption(AwsRegion); @@ -94,6 +95,10 @@ public GenerateScriptCommand() : base( { Description = "Keeps the archive on this machine after uploading to the blob storage account. Only applicable for migrations from GitHub Enterprise Server versions before 3.8.0." }; + 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 GenerateScriptCommandHandler BuildHandler(GenerateScriptCommandArgs args, IServiceProvider sp) { diff --git a/src/gei/Commands/GenerateScript/GenerateScriptCommandArgs.cs b/src/gei/Commands/GenerateScript/GenerateScriptCommandArgs.cs index 378b4d265..d1f64956a 100644 --- a/src/gei/Commands/GenerateScript/GenerateScriptCommandArgs.cs +++ b/src/gei/Commands/GenerateScript/GenerateScriptCommandArgs.cs @@ -22,6 +22,7 @@ public class GenerateScriptCommandArgs : CommandArgs [Secret] public string GithubSourcePat { get; set; } public bool KeepArchive { get; set; } + public string TargetApiUrl { get; set; } public override void Validate(OctoLogger log) { diff --git a/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs index 5e7020253..4948cb782 100644 --- a/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -44,7 +44,7 @@ public async Task Handle(GenerateScriptCommandArgs args) _log.LogInformation("Generating Script..."); - var script = await GenerateScript(args.GithubSourceOrg, args.GithubTargetOrg, args.GhesApiUrl, args.AwsBucketName, args.AwsRegion, args.NoSslVerify, args.Sequential, args.SkipReleases, args.LockSourceRepo, args.DownloadMigrationLogs, args.KeepArchive); + var script = await GenerateScript(args.GithubSourceOrg, args.GithubTargetOrg, args.GhesApiUrl, args.AwsBucketName, args.AwsRegion, args.NoSslVerify, args.Sequential, args.SkipReleases, args.LockSourceRepo, args.DownloadMigrationLogs, args.KeepArchive, args.TargetApiUrl); if (script.HasValue() && args.Output.HasValue()) { @@ -52,7 +52,7 @@ public async Task Handle(GenerateScriptCommandArgs args) } } - private async Task GenerateScript(string githubSourceOrg, string githubTargetOrg, string ghesApiUrl, string awsBucketName, string awsRegion, bool noSslVerify, bool sequential, bool skipReleases, bool lockSourceRepo, bool downloadMigrationLogs, bool keepArchive) + private async Task GenerateScript(string githubSourceOrg, string githubTargetOrg, string ghesApiUrl, string awsBucketName, string awsRegion, bool noSslVerify, bool sequential, bool skipReleases, bool lockSourceRepo, bool downloadMigrationLogs, bool keepArchive, string targetApiUrl) { var repos = await GetGithubRepos(_sourceGithubApi, githubSourceOrg); if (!repos.Any()) @@ -62,8 +62,8 @@ private async Task GenerateScript(string githubSourceOrg, string githubT } return sequential - ? await GenerateSequentialGithubScript(repos, githubSourceOrg, githubTargetOrg, ghesApiUrl, awsBucketName, awsRegion, noSslVerify, skipReleases, lockSourceRepo, downloadMigrationLogs, keepArchive) - : await GenerateParallelGithubScript(repos, githubSourceOrg, githubTargetOrg, ghesApiUrl, awsBucketName, awsRegion, noSslVerify, skipReleases, lockSourceRepo, downloadMigrationLogs, keepArchive); + ? await GenerateSequentialGithubScript(repos, githubSourceOrg, githubTargetOrg, ghesApiUrl, awsBucketName, awsRegion, noSslVerify, skipReleases, lockSourceRepo, downloadMigrationLogs, keepArchive, targetApiUrl) + : await GenerateParallelGithubScript(repos, githubSourceOrg, githubTargetOrg, ghesApiUrl, awsBucketName, awsRegion, noSslVerify, skipReleases, lockSourceRepo, downloadMigrationLogs, keepArchive, targetApiUrl); } private async Task> GetGithubRepos(GithubApi github, string githubOrg) @@ -83,7 +83,7 @@ private async Task GenerateScript(string githubSourceOrg, string githubT return repos; } - private async Task GenerateSequentialGithubScript(IEnumerable<(string Name, string Visibility)> repos, string githubSourceOrg, string githubTargetOrg, string ghesApiUrl, string awsBucketName, string awsRegion, bool noSslVerify, bool skipReleases, bool lockSourceRepo, bool downloadMigrationLogs, bool keepArchive) + private async Task GenerateSequentialGithubScript(IEnumerable<(string Name, string Visibility)> repos, string githubSourceOrg, string githubTargetOrg, string ghesApiUrl, string awsBucketName, string awsRegion, bool noSslVerify, bool skipReleases, bool lockSourceRepo, bool downloadMigrationLogs, bool keepArchive, string targetApiUrl) { var content = new StringBuilder(); @@ -110,18 +110,18 @@ private async Task GenerateSequentialGithubScript(IEnumerable<(string Na foreach (var (name, visibility) in repos) { - content.AppendLine(Exec(MigrateGithubRepoScript(githubSourceOrg, githubTargetOrg, name, ghesApiUrl, awsBucketName, awsRegion, noSslVerify, true, skipReleases, lockSourceRepo, keepArchive, visibility))); + content.AppendLine(Exec(MigrateGithubRepoScript(githubSourceOrg, githubTargetOrg, name, ghesApiUrl, awsBucketName, awsRegion, noSslVerify, true, skipReleases, lockSourceRepo, keepArchive, visibility, targetApiUrl))); if (downloadMigrationLogs) { - content.AppendLine(Exec(DownloadMigrationLogScript(githubTargetOrg, name))); + content.AppendLine(Exec(DownloadMigrationLogScript(githubTargetOrg, name, targetApiUrl))); } } return content.ToString(); } - private async Task GenerateParallelGithubScript(IEnumerable<(string Name, string Visibility)> repos, string githubSourceOrg, string githubTargetOrg, string ghesApiUrl, string awsBucketName, string awsRegion, bool noSslVerify, bool skipReleases, bool lockSourceRepo, bool downloadMigrationLogs, bool keepArchive) + private async Task GenerateParallelGithubScript(IEnumerable<(string Name, string Visibility)> repos, string githubSourceOrg, string githubTargetOrg, string ghesApiUrl, string awsBucketName, string awsRegion, bool noSslVerify, bool skipReleases, bool lockSourceRepo, bool downloadMigrationLogs, bool keepArchive, string targetApiUrl) { var content = new StringBuilder(); @@ -158,7 +158,7 @@ private async Task GenerateParallelGithubScript(IEnumerable<(string Name // Queuing migrations foreach (var (name, visibility) in repos) { - content.AppendLine($"$MigrationID = {ExecAndGetMigrationId(MigrateGithubRepoScript(githubSourceOrg, githubTargetOrg, name, ghesApiUrl, awsBucketName, awsRegion, noSslVerify, false, skipReleases, lockSourceRepo, keepArchive, visibility))}"); + content.AppendLine($"$MigrationID = {ExecAndGetMigrationId(MigrateGithubRepoScript(githubSourceOrg, githubTargetOrg, name, ghesApiUrl, awsBucketName, awsRegion, noSslVerify, false, skipReleases, lockSourceRepo, keepArchive, visibility, targetApiUrl))}"); content.AppendLine($"$RepoMigrations[\"{name}\"] = $MigrationID"); content.AppendLine(); } @@ -171,12 +171,12 @@ private async Task GenerateParallelGithubScript(IEnumerable<(string Name // Query each migration's status foreach (var (name, _) in repos) { - content.AppendLine(Wrap(WaitForMigrationScript(name), $"if ($RepoMigrations[\"{name}\"])")); + content.AppendLine(Wrap(WaitForMigrationScript(targetApiUrl, name), $"if ($RepoMigrations[\"{name}\"])")); content.AppendLine($"if ($RepoMigrations[\"{name}\"] -and $lastexitcode -eq 0) {{ $Succeeded++ }} else {{ $Failed++ }}"); if (downloadMigrationLogs) { - content.AppendLine(DownloadMigrationLogScript(githubTargetOrg, name)); + content.AppendLine(DownloadMigrationLogScript(githubTargetOrg, name, targetApiUrl)); } content.AppendLine(); @@ -199,11 +199,11 @@ exit 1 return content.ToString(); } - private string MigrateGithubRepoScript(string githubSourceOrg, string githubTargetOrg, string repo, string ghesApiUrl, string awsBucketName, string awsRegion, bool noSslVerify, bool wait, bool skipReleases, bool lockSourceRepo, bool keepArchive, string repoVisibility) + private string MigrateGithubRepoScript(string githubSourceOrg, string githubTargetOrg, string repo, string ghesApiUrl, string awsBucketName, string awsRegion, bool noSslVerify, bool wait, bool skipReleases, bool lockSourceRepo, bool keepArchive, string repoVisibility, string targetApiUrl) { var ghesRepoOptions = ghesApiUrl.HasValue() ? GetGhesRepoOptions(ghesApiUrl, awsBucketName, awsRegion, noSslVerify, keepArchive) : null; - return $"gh gei migrate-repo --github-source-org \"{githubSourceOrg}\" --source-repo \"{repo}\" --github-target-org \"{githubTargetOrg}\" --target-repo \"{repo}\"{(!string.IsNullOrEmpty(ghesRepoOptions) ? $" {ghesRepoOptions}" : string.Empty)}{(_log.Verbose ? " --verbose" : string.Empty)}{(wait ? string.Empty : " --queue-only")}{(skipReleases ? " --skip-releases" : string.Empty)}{(lockSourceRepo ? " --lock-source-repo" : string.Empty)} --target-repo-visibility {repoVisibility}"; + return $"gh gei migrate-repo{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-source-org \"{githubSourceOrg}\" --source-repo \"{repo}\" --github-target-org \"{githubTargetOrg}\" --target-repo \"{repo}\"{(!string.IsNullOrEmpty(ghesRepoOptions) ? $" {ghesRepoOptions}" : string.Empty)}{(_log.Verbose ? " --verbose" : string.Empty)}{(wait ? string.Empty : " --queue-only")}{(skipReleases ? " --skip-releases" : string.Empty)}{(lockSourceRepo ? " --lock-source-repo" : string.Empty)} --target-repo-visibility {repoVisibility}"; } private string GetGhesRepoOptions(string ghesApiUrl, string awsBucketName, string awsRegion, bool noSslVerify, bool keepArchive) @@ -211,11 +211,11 @@ private string GetGhesRepoOptions(string ghesApiUrl, string awsBucketName, strin return $"--ghes-api-url \"{ghesApiUrl}\"{(awsBucketName.HasValue() ? $" --aws-bucket-name \"{awsBucketName}\"" : "")}{(awsRegion.HasValue() ? $" --aws-region \"{awsRegion}\"" : "")}{(noSslVerify ? " --no-ssl-verify" : string.Empty)}{(keepArchive ? " --keep-archive" : string.Empty)}"; } - private string WaitForMigrationScript(string repoMigrationKey = null) => $"gh gei wait-for-migration --migration-id $RepoMigrations[\"{repoMigrationKey}\"]"; + private string WaitForMigrationScript(string targetApiUrl, string repoMigrationKey = null) => $"gh gei wait-for-migration{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --migration-id $RepoMigrations[\"{repoMigrationKey}\"]"; - private string DownloadMigrationLogScript(string githubTargetOrg, string targetRepo) + private string DownloadMigrationLogScript(string githubTargetOrg, string targetRepo, string targetApiUrl) { - return $"gh gei download-logs --github-target-org \"{githubTargetOrg}\" --target-repo \"{targetRepo}\""; + return $"gh gei download-logs{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-target-org \"{githubTargetOrg}\" --target-repo \"{targetRepo}\""; } private string Exec(string script) => Wrap(script, "Exec"); From 4f9e79c69b3129f8b8727513147109fc08beabd4 Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 05:06:42 +0000 Subject: [PATCH 03/14] fix spacing --- .../GenerateScript/GenerateScriptCommandHandlerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs b/src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs index 1f3be44d6..211306a5b 100644 --- a/src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs +++ b/src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScript/GenerateScriptCommandHandlerTests.cs @@ -517,7 +517,7 @@ public async Task One_Repo_With_Smb() _mockFileSystemProvider.Verify(m => m.WriteAllTextAsync(It.IsAny(), It.Is(script => script.Contains(migrateRepoCommand)))); } -[Fact] + [Fact] public async Task One_Repo_With_Smb_And_TargetApiUrl() { // Arrange From 17dabe2c0401be4a1e626d54a4a47dd14998279c Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 05:15:42 +0000 Subject: [PATCH 04/14] fix tests --- .../Commands/GenerateScript/GenerateScriptCommandTests.cs | 3 ++- .../Commands/GenerateScript/GenerateScriptCommandTests.cs | 3 ++- .../gei/Commands/GenerateScript/GenerateScriptCommandTests.cs | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/OctoshiftCLI.Tests/ado2gh/Commands/GenerateScript/GenerateScriptCommandTests.cs b/src/OctoshiftCLI.Tests/ado2gh/Commands/GenerateScript/GenerateScriptCommandTests.cs index 52555eb54..b06d0d323 100644 --- a/src/OctoshiftCLI.Tests/ado2gh/Commands/GenerateScript/GenerateScriptCommandTests.cs +++ b/src/OctoshiftCLI.Tests/ado2gh/Commands/GenerateScript/GenerateScriptCommandTests.cs @@ -38,7 +38,7 @@ public void Should_Have_Options() var command = new GenerateScriptCommand(); command.Should().NotBeNull(); command.Name.Should().Be("generate-script"); - command.Options.Count.Should().Be(17); + command.Options.Count.Should().Be(18); TestHelpers.VerifyCommandOption(command.Options, "github-org", true); TestHelpers.VerifyCommandOption(command.Options, "ado-org", false); @@ -57,6 +57,7 @@ public void Should_Have_Options() TestHelpers.VerifyCommandOption(command.Options, "rewire-pipelines", false); TestHelpers.VerifyCommandOption(command.Options, "all", false); TestHelpers.VerifyCommandOption(command.Options, "repo-list", false); + TestHelpers.VerifyCommandOption(command.Options, "target-api-url", false); } [Fact] diff --git a/src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScript/GenerateScriptCommandTests.cs b/src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScript/GenerateScriptCommandTests.cs index a268930e9..db247883e 100644 --- a/src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScript/GenerateScriptCommandTests.cs +++ b/src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScript/GenerateScriptCommandTests.cs @@ -36,7 +36,7 @@ public void Should_Have_Options() { _command.Should().NotBeNull(); _command.Name.Should().Be("generate-script"); - _command.Options.Count.Should().Be(19); + _command.Options.Count.Should().Be(20); TestHelpers.VerifyCommandOption(_command.Options, "bbs-server-url", true); TestHelpers.VerifyCommandOption(_command.Options, "github-org", true); @@ -57,6 +57,7 @@ public void Should_Have_Options() TestHelpers.VerifyCommandOption(_command.Options, "aws-region", false); TestHelpers.VerifyCommandOption(_command.Options, "keep-archive", false); TestHelpers.VerifyCommandOption(_command.Options, "no-ssl-verify", false); + TestHelpers.VerifyCommandOption(_command.Options, "target-api-url", false); } [Fact] diff --git a/src/OctoshiftCLI.Tests/gei/Commands/GenerateScript/GenerateScriptCommandTests.cs b/src/OctoshiftCLI.Tests/gei/Commands/GenerateScript/GenerateScriptCommandTests.cs index b7b1f9173..a24ff8de7 100644 --- a/src/OctoshiftCLI.Tests/gei/Commands/GenerateScript/GenerateScriptCommandTests.cs +++ b/src/OctoshiftCLI.Tests/gei/Commands/GenerateScript/GenerateScriptCommandTests.cs @@ -39,7 +39,7 @@ public void Should_Have_Options() var command = new GenerateScriptCommand(); command.Should().NotBeNull(); command.Name.Should().Be("generate-script"); - command.Options.Count.Should().Be(14); + command.Options.Count.Should().Be(15); TestHelpers.VerifyCommandOption(command.Options, "github-source-org", true); TestHelpers.VerifyCommandOption(command.Options, "github-target-org", true); @@ -55,6 +55,7 @@ public void Should_Have_Options() TestHelpers.VerifyCommandOption(command.Options, "aws-bucket-name", false); TestHelpers.VerifyCommandOption(command.Options, "aws-region", false); TestHelpers.VerifyCommandOption(command.Options, "keep-archive", false); + TestHelpers.VerifyCommandOption(command.Options, "target-api-url", false); } [Fact] From 6cb5c45293da7920226bb5c75257e4345c0e01b9 Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 05:37:06 +0000 Subject: [PATCH 05/14] update release notes --- RELEASENOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6bd248fa0..d9e85a03d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,2 +1,2 @@ -- Add `--target-api-url` to `gh ado2gh migrate-repo`, `gh bbs2gh migrate-repo`, and `gh gei migrate-org` to support newer GitHub migration paths. +- Add `--target-api-url` to commonly used commands to support newer GitHub migration paths. - Fixed `gh ado2gh rewire-pipeline` command for ADO Team Projects with more than 10,000 Build Definitions. From 62620f6423dd51ee1dd74fae9f00e37d0cafd7ef Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 13:14:52 -0800 Subject: [PATCH 06/14] Update src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs Co-authored-by: Arin Ghazarian --- src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs index 4948cb782..bc4183d79 100644 --- a/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -215,7 +215,7 @@ private string GetGhesRepoOptions(string ghesApiUrl, string awsBucketName, strin private string DownloadMigrationLogScript(string githubTargetOrg, string targetRepo, string targetApiUrl) { - return $"gh gei download-logs{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-target-org \"{githubTargetOrg}\" --target-repo \"{targetRepo}\""; + return $"gh gei download-logs{(targetApiUrl.HasValue() ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-target-org \"{githubTargetOrg}\" --target-repo \"{targetRepo}\""; } private string Exec(string script) => Wrap(script, "Exec"); From 7cf94010cbe87e615c63e4ccf26f591eeb4b590c Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 13:15:12 -0800 Subject: [PATCH 07/14] Update src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs Co-authored-by: Arin Ghazarian --- src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs index bc4183d79..3adfdd92d 100644 --- a/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -211,7 +211,7 @@ private string GetGhesRepoOptions(string ghesApiUrl, string awsBucketName, strin return $"--ghes-api-url \"{ghesApiUrl}\"{(awsBucketName.HasValue() ? $" --aws-bucket-name \"{awsBucketName}\"" : "")}{(awsRegion.HasValue() ? $" --aws-region \"{awsRegion}\"" : "")}{(noSslVerify ? " --no-ssl-verify" : string.Empty)}{(keepArchive ? " --keep-archive" : string.Empty)}"; } - private string WaitForMigrationScript(string targetApiUrl, string repoMigrationKey = null) => $"gh gei wait-for-migration{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --migration-id $RepoMigrations[\"{repoMigrationKey}\"]"; + private string WaitForMigrationScript(string targetApiUrl, string repoMigrationKey = null) => $"gh gei wait-for-migration{(targetApiUrl.HasValue() ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --migration-id $RepoMigrations[\"{repoMigrationKey}\"]"; private string DownloadMigrationLogScript(string githubTargetOrg, string targetRepo, string targetApiUrl) { From 6cc97ecd3638604fab71e1a0dda30e7e719352f9 Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 13:15:22 -0800 Subject: [PATCH 08/14] Update src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs Co-authored-by: Arin Ghazarian --- src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs index 3adfdd92d..39f8b7aee 100644 --- a/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/gei/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -203,7 +203,7 @@ private string MigrateGithubRepoScript(string githubSourceOrg, string githubTarg { var ghesRepoOptions = ghesApiUrl.HasValue() ? GetGhesRepoOptions(ghesApiUrl, awsBucketName, awsRegion, noSslVerify, keepArchive) : null; - return $"gh gei migrate-repo{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-source-org \"{githubSourceOrg}\" --source-repo \"{repo}\" --github-target-org \"{githubTargetOrg}\" --target-repo \"{repo}\"{(!string.IsNullOrEmpty(ghesRepoOptions) ? $" {ghesRepoOptions}" : string.Empty)}{(_log.Verbose ? " --verbose" : string.Empty)}{(wait ? string.Empty : " --queue-only")}{(skipReleases ? " --skip-releases" : string.Empty)}{(lockSourceRepo ? " --lock-source-repo" : string.Empty)} --target-repo-visibility {repoVisibility}"; + return $"gh gei migrate-repo{(targetApiUrl.HasValue() ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-source-org \"{githubSourceOrg}\" --source-repo \"{repo}\" --github-target-org \"{githubTargetOrg}\" --target-repo \"{repo}\"{(!string.IsNullOrEmpty(ghesRepoOptions) ? $" {ghesRepoOptions}" : string.Empty)}{(_log.Verbose ? " --verbose" : string.Empty)}{(wait ? string.Empty : " --queue-only")}{(skipReleases ? " --skip-releases" : string.Empty)}{(lockSourceRepo ? " --lock-source-repo" : string.Empty)} --target-repo-visibility {repoVisibility}"; } private string GetGhesRepoOptions(string ghesApiUrl, string awsBucketName, string awsRegion, bool noSslVerify, bool keepArchive) From 416a814a3c0b6949a78c74ee696d63fb5ed628c1 Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 13:15:32 -0800 Subject: [PATCH 09/14] Update src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs Co-authored-by: Arin Ghazarian --- .../Commands/GenerateScript/GenerateScriptCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs index 10269b397..755f9562d 100644 --- a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -397,7 +397,7 @@ private string BoardsIntegrationScript(string adoOrg, string adoTeamProject, str private string DownloadMigrationLogScript(string githubOrg, string githubRepo, string targetApiUrl) => _generateScriptOptions.DownloadMigrationLogs - ? $"gh ado2gh download-logs{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\"" + ? $"gh ado2gh download-logs{(targetApiUrl.HasValue() ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\"" : null; private string Exec(string script) => Wrap(script, "Exec"); From e761f92b22c0cad91a2ed426f11349e100e766f3 Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 13:15:45 -0800 Subject: [PATCH 10/14] Update src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs Co-authored-by: Arin Ghazarian --- .../Commands/GenerateScript/GenerateScriptCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs index 755f9562d..2bca3afd2 100644 --- a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -393,7 +393,7 @@ private string BoardsIntegrationScript(string adoOrg, string adoTeamProject, str ? $"gh ado2gh integrate-boards --ado-org \"{adoOrg}\" --ado-team-project \"{adoTeamProject}\" --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\"{(_log.Verbose ? " --verbose" : string.Empty)}" : null; - private string WaitForMigrationScript(string repoMigrationKey, string targetApiUrl) => $"gh ado2gh wait-for-migration{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --migration-id $RepoMigrations[\"{repoMigrationKey}\"]"; + private string WaitForMigrationScript(string repoMigrationKey, string targetApiUrl) => $"gh ado2gh wait-for-migration{(targetApiUrl.HasValue() ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --migration-id $RepoMigrations[\"{repoMigrationKey}\"]"; private string DownloadMigrationLogScript(string githubOrg, string githubRepo, string targetApiUrl) => _generateScriptOptions.DownloadMigrationLogs From 82131129fda057d897b0c9799c42874e2b2a00de Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 13:16:00 -0800 Subject: [PATCH 11/14] Update src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs Co-authored-by: Arin Ghazarian --- .../Commands/GenerateScript/GenerateScriptCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs index 2bca3afd2..95031f4cd 100644 --- a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -370,7 +370,7 @@ private string CreateGithubMaintainersTeamScript(string adoTeamProject, string g private string CreateGithubAdminsTeamScript(string adoTeamProject, string githubOrg, bool linkIdpGroups, string targetApiUrl) => _generateScriptOptions.CreateTeams - ? $"gh ado2gh create-team{(!string.IsNullOrEmpty(targetApiUrl) ? $" --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)}" + ? $"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) => From f376e680dbb3a6422beab64e809f6ac31def6e75 Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 13:16:08 -0800 Subject: [PATCH 12/14] Update src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs Co-authored-by: Arin Ghazarian --- .../Commands/GenerateScript/GenerateScriptCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs index 95031f4cd..b59027fed 100644 --- a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -365,7 +365,7 @@ private string QueueMigrateRepoScript(string adoOrg, string adoTeamProject, stri private string CreateGithubMaintainersTeamScript(string adoTeamProject, string githubOrg, bool linkIdpGroups, string targetApiUrl) => _generateScriptOptions.CreateTeams - ? $"gh ado2gh create-team{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-org \"{githubOrg}\" --team-name \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Maintainers\"{(_log.Verbose ? " --verbose" : string.Empty)}{(linkIdpGroups ? $" --idp-group \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Maintainers\"" : string.Empty)}" + ? $"gh ado2gh create-team{(targetApiUrl.HasValue() ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --github-org \"{githubOrg}\" --team-name \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Maintainers\"{(_log.Verbose ? " --verbose" : string.Empty)}{(linkIdpGroups ? $" --idp-group \"{adoTeamProject.ReplaceInvalidCharactersWithDash()}-Maintainers\"" : string.Empty)}" : null; private string CreateGithubAdminsTeamScript(string adoTeamProject, string githubOrg, bool linkIdpGroups, string targetApiUrl) => From 6a4d0e5686b31126aa3933073643fd92217fccb2 Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 13:16:14 -0800 Subject: [PATCH 13/14] Update src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs Co-authored-by: Arin Ghazarian --- .../Commands/GenerateScript/GenerateScriptCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs index b59027fed..c1d511691 100644 --- a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -358,7 +358,7 @@ private string ConfigureAutolinkScript(string githubOrg, string githubRepo, stri : null; private string MigrateRepoScript(string adoOrg, string adoTeamProject, string adoRepo, string githubOrg, string githubRepo, bool wait, string adoServerUrl, string targetApiUrl) => - $"gh ado2gh migrate-repo{(!string.IsNullOrEmpty(targetApiUrl) ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --ado-org \"{adoOrg}\" --ado-team-project \"{adoTeamProject}\" --ado-repo \"{adoRepo}\" --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\"{(_log.Verbose ? " --verbose" : string.Empty)}{(wait ? string.Empty : " --queue-only")} --target-repo-visibility private{(adoServerUrl.IsNullOrWhiteSpace() ? string.Empty : $" --ado-server-url \"{adoServerUrl}\"")}"; + $"gh ado2gh migrate-repo{(targetApiUrl.HasValue() ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --ado-org \"{adoOrg}\" --ado-team-project \"{adoTeamProject}\" --ado-repo \"{adoRepo}\" --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\"{(_log.Verbose ? " --verbose" : string.Empty)}{(wait ? string.Empty : " --queue-only")} --target-repo-visibility private{(adoServerUrl.IsNullOrWhiteSpace() ? string.Empty : $" --ado-server-url \"{adoServerUrl}\"")}"; private string QueueMigrateRepoScript(string adoOrg, string adoTeamProject, string adoRepo, string githubOrg, string githubRepo, string adoServerUrl, string targetApiUrl) => $"$MigrationID = {ExecAndGetMigrationId(MigrateRepoScript(adoOrg, adoTeamProject, adoRepo, githubOrg, githubRepo, false, adoServerUrl, targetApiUrl))}"; From 54158a7bb6d1048f2257ebe85d3d8693f16cdc45 Mon Sep 17 00:00:00 2001 From: Briana J Date: Fri, 9 Feb 2024 21:22:47 +0000 Subject: [PATCH 14/14] use hasvalue --- .../Commands/GenerateScript/GenerateScriptCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs index c1d511691..87ba7f063 100644 --- a/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs +++ b/src/ado2gh/Commands/GenerateScript/GenerateScriptCommandHandler.cs @@ -358,7 +358,7 @@ private string ConfigureAutolinkScript(string githubOrg, string githubRepo, stri : null; private string MigrateRepoScript(string adoOrg, string adoTeamProject, string adoRepo, string githubOrg, string githubRepo, bool wait, string adoServerUrl, string targetApiUrl) => - $"gh ado2gh migrate-repo{(targetApiUrl.HasValue() ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --ado-org \"{adoOrg}\" --ado-team-project \"{adoTeamProject}\" --ado-repo \"{adoRepo}\" --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\"{(_log.Verbose ? " --verbose" : string.Empty)}{(wait ? string.Empty : " --queue-only")} --target-repo-visibility private{(adoServerUrl.IsNullOrWhiteSpace() ? string.Empty : $" --ado-server-url \"{adoServerUrl}\"")}"; + $"gh ado2gh migrate-repo{(targetApiUrl.HasValue() ? $" --target-api-url \"{targetApiUrl}\"" : string.Empty)} --ado-org \"{adoOrg}\" --ado-team-project \"{adoTeamProject}\" --ado-repo \"{adoRepo}\" --github-org \"{githubOrg}\" --github-repo \"{githubRepo}\"{(_log.Verbose ? " --verbose" : string.Empty)}{(wait ? string.Empty : " --queue-only")} --target-repo-visibility private{(adoServerUrl.HasValue() ? $" --ado-server-url \"{adoServerUrl}\"" : string.Empty)}"; private string QueueMigrateRepoScript(string adoOrg, string adoTeamProject, string adoRepo, string githubOrg, string githubRepo, string adoServerUrl, string targetApiUrl) => $"$MigrationID = {ExecAndGetMigrationId(MigrateRepoScript(adoOrg, adoTeamProject, adoRepo, githubOrg, githubRepo, false, adoServerUrl, targetApiUrl))}";