Skip to content

Commit

Permalink
Merge pull request #1216 from github/1094-reclaim-mannequin-commands
Browse files Browse the repository at this point in the history
Add `target-api-url` to reclaim mannequin and grant migrator commands
  • Loading branch information
brianaj authored Feb 3, 2024
2 parents dadf326 + 2f95e06 commit 02548b5
Show file tree
Hide file tree
Showing 19 changed files with 179 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ public class GenerateMannequinCsvCommandArgs : CommandArgs
public bool IncludeReclaimed { get; set; }
[Secret]
public string GithubPat { get; set; }
public string TargetApiUrl { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ public GenerateMannequinCsvCommandBase() : base(
{
Description = "Personal access token of the GitHub target. Overrides GH_PAT environment variable."
};
public Option<string> 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 GenerateMannequinCsvCommandHandler BuildHandler(GenerateMannequinCsvCommandArgs args, IServiceProvider sp)
{
Expand All @@ -52,7 +56,7 @@ public override GenerateMannequinCsvCommandHandler BuildHandler(GenerateMannequi

var log = sp.GetRequiredService<OctoLogger>();
var githubApiFactory = sp.GetRequiredService<ITargetGithubApiFactory>();
var githubApi = githubApiFactory.Create(targetPersonalAccessToken: args.GithubPat);
var githubApi = githubApiFactory.Create(args.TargetApiUrl, args.GithubPat);

return new GenerateMannequinCsvCommandHandler(log, githubApi);
}
Expand All @@ -63,6 +67,7 @@ protected void AddOptions()
AddOption(Output);
AddOption(IncludeReclaimed);
AddOption(GithubPat);
AddOption(TargetApiUrl);
AddOption(Verbose);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using OctoshiftCLI.Services;
using OctoshiftCLI.Extensions;
using OctoshiftCLI.Services;

namespace OctoshiftCLI.Commands.GrantMigratorRole;

Expand All @@ -10,6 +11,7 @@ public class GrantMigratorRoleCommandArgs : CommandArgs
[Secret]
public string GithubPat { get; set; }
public string GhesApiUrl { get; set; }
public string TargetApiUrl { get; set; }

public override void Validate(OctoLogger log)
{
Expand All @@ -23,5 +25,10 @@ public override void Validate(OctoLogger log)
{
throw new OctoshiftCliException("Actor type must be either TEAM or USER.");
}

if (GhesApiUrl.HasValue() && TargetApiUrl.HasValue())
{
throw new OctoshiftCliException("Only one of --ghes-api-url or --target-api-url can be set at a time.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,16 @@ public GrantMigratorRoleCommandBase() : base(
Description = "Personal access token of the GitHub target. Overrides GH_PAT environment variable."
};

public virtual Option<string> GhesApiUrl { get; } = new("--ghes-api-url") { IsRequired = false };
public virtual Option<string> GhesApiUrl { get; } = new("--ghes-api-url")
{
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<string> 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."
};

public virtual Option<bool> Verbose { get; } = new("--verbose") { IsRequired = false };

Expand All @@ -43,7 +52,8 @@ public override GrantMigratorRoleCommandHandler BuildHandler(GrantMigratorRoleCo

var log = sp.GetRequiredService<OctoLogger>();
var githubApiFactory = sp.GetRequiredService<ITargetGithubApiFactory>();
var githubApi = githubApiFactory.Create(args.GhesApiUrl, args.GithubPat);
var apiUrl = args.TargetApiUrl ?? args.GhesApiUrl;
var githubApi = githubApiFactory.Create(apiUrl, args.GithubPat);

return new GrantMigratorRoleCommandHandler(log, githubApi);
}
Expand All @@ -56,5 +66,6 @@ protected void AddOptions()
AddOption(GithubPat);
AddOption(Verbose);
AddOption(GhesApiUrl);
AddOption(TargetApiUrl);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class ReclaimMannequinCommandArgs : CommandArgs
[Secret]
public string GithubPat { get; set; }
public bool SkipInvitation { get; set; }

public string TargetApiUrl { get; set; }
public override void Validate(OctoLogger log)
{
if (string.IsNullOrEmpty(Csv) && (string.IsNullOrEmpty(MannequinUser) || string.IsNullOrEmpty(TargetUser)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ 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<string> 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 virtual Option<bool> Verbose { get; } = new("--verbose");

public override ReclaimMannequinCommandHandler BuildHandler(ReclaimMannequinCommandArgs args, IServiceProvider sp)
Expand All @@ -83,7 +88,7 @@ public override ReclaimMannequinCommandHandler BuildHandler(ReclaimMannequinComm

var log = sp.GetRequiredService<OctoLogger>();
var githubApiFactory = sp.GetRequiredService<ITargetGithubApiFactory>();
var githubApi = githubApiFactory.Create(targetPersonalAccessToken: args.GithubPat);
var githubApi = githubApiFactory.Create(args.TargetApiUrl, args.GithubPat);
var reclaimService = new ReclaimService(githubApi, log);
var confirmationService = sp.GetRequiredService<ConfirmationService>();

Expand All @@ -101,6 +106,7 @@ protected void AddOptions()
AddOption(NoPrompt);
AddOption(GithubPat);
AddOption(SkipInvitation);
AddOption(TargetApiUrl);
AddOption(Verbose);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Microsoft.Extensions.DependencyInjection;
using Moq;
using OctoshiftCLI.Commands.GenerateMannequinCsv;
using OctoshiftCLI.Contracts;
using OctoshiftCLI.Services;
using Xunit;

namespace OctoshiftCLI.Tests.Octoshift.Commands.GeneerateMannequinCsv;

public class GenerateMannequinCsvCommandBaseTests
{
private readonly Mock<OctoLogger> _mockOctoLogger = TestHelpers.CreateMock<OctoLogger>();
private readonly Mock<ITargetGithubApiFactory> _mockGithubApiFactory = new();
private readonly ServiceProvider _serviceProvider;
private readonly GenerateMannequinCsvCommandBase _command = new();
private const string GITHUB_ORG = "FooOrg";

public GenerateMannequinCsvCommandBaseTests()
{
var serviceCollection = new ServiceCollection();
serviceCollection
.AddSingleton(_mockOctoLogger.Object)
.AddSingleton(_mockGithubApiFactory.Object);

_serviceProvider = serviceCollection.BuildServiceProvider();
}

[Fact]
public void It_Uses_The_TargetApiUrl_When_Provided()
{
var targetApiUrl = "TARGET-API-URL";

var args = new GenerateMannequinCsvCommandArgs
{
GithubOrg = GITHUB_ORG,
IncludeReclaimed = false,
TargetApiUrl = targetApiUrl,
};

_command.BuildHandler(args, _serviceProvider);

_mockGithubApiFactory.Verify(m => m.Create(targetApiUrl, null));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,20 @@ public void Invalid_Actor_Type()
FluentActions.Invoking(() => args.Validate(_mockOctoLogger.Object))
.Should().Throw<OctoshiftCliException>();
}

[Fact]
public void It_Validates_GhesApiUrl_And_TargetApiUrl()
{
var args = new GrantMigratorRoleCommandArgs
{
GithubOrg = GITHUB_ORG,
Actor = ACTOR,
ActorType = "USER",
GhesApiUrl = "https://ghes.example.com",
TargetApiUrl = "https://api.github.com",
};

FluentActions.Invoking(() => args.Validate(_mockOctoLogger.Object))
.Should().Throw<OctoshiftCliException>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,22 @@ public void It_Uses_The_GhesApiUrl_When_Provided()

_mockGithubApiFactory.Verify(m => m.Create(ghesApiUrl, null));
}

[Fact]
public void It_Uses_The_TargetApiUrl_When_Provided()
{
var targetApiUrl = "TARGET-API-URL";

var args = new GrantMigratorRoleCommandArgs
{
GithubOrg = "foo",
Actor = "blah",
ActorType = "TEAM",
TargetApiUrl = targetApiUrl,
};

_command.BuildHandler(args, _serviceProvider);

_mockGithubApiFactory.Verify(m => m.Create(targetApiUrl, null));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Microsoft.Extensions.DependencyInjection;
using Moq;
using OctoshiftCLI.Commands.ReclaimMannequin;
using OctoshiftCLI.Contracts;
using OctoshiftCLI.Services;
using Xunit;

namespace OctoshiftCLI.Tests.Octoshift.Commands.ReclaimMannequin;

public class ReclaimMannequinCommandBaseTests
{
private readonly Mock<OctoLogger> _mockOctoLogger = TestHelpers.CreateMock<OctoLogger>();
private readonly Mock<ConfirmationService> _mockConfirmationService = TestHelpers.CreateMock<ConfirmationService>();
private readonly Mock<ITargetGithubApiFactory> _mockGithubApiFactory = new();
private readonly ServiceProvider _serviceProvider;
private readonly ReclaimMannequinCommandBase _command = new();

private const string GITHUB_ORG = "FooOrg";

public ReclaimMannequinCommandBaseTests()
{
var serviceCollection = new ServiceCollection();
serviceCollection
.AddSingleton(_mockOctoLogger.Object)
.AddSingleton(_mockGithubApiFactory.Object)
.AddSingleton(_mockConfirmationService.Object);

_serviceProvider = serviceCollection.BuildServiceProvider();
}

[Fact]
public void It_Uses_The_TargetApiUrl_When_Provided()
{
var targetApiUrl = "TARGET-API-URL";

var args = new ReclaimMannequinCommandArgs
{
GithubOrg = GITHUB_ORG,
Csv = "file.csv",
TargetApiUrl = targetApiUrl,
};

_command.BuildHandler(args, _serviceProvider);

_mockGithubApiFactory.Verify(m => m.Create(targetApiUrl, null));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ public void Should_Have_Options()
var command = new GenerateMannequinCsvCommand();
Assert.NotNull(command);
Assert.Equal("generate-mannequin-csv", command.Name);
Assert.Equal(5, command.Options.Count);
Assert.Equal(6, command.Options.Count);

TestHelpers.VerifyCommandOption(command.Options, "github-org", true);
TestHelpers.VerifyCommandOption(command.Options, "output", false);
TestHelpers.VerifyCommandOption(command.Options, "include-reclaimed", false);
TestHelpers.VerifyCommandOption(command.Options, "github-pat", false);
TestHelpers.VerifyCommandOption(command.Options, "verbose", false);
TestHelpers.VerifyCommandOption(command.Options, "target-api-url", false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ public void Should_Have_Options()
var command = new GrantMigratorRoleCommand();
Assert.NotNull(command);
Assert.Equal("grant-migrator-role", 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, "actor", true);
TestHelpers.VerifyCommandOption(command.Options, "actor-type", true);
TestHelpers.VerifyCommandOption(command.Options, "github-pat", false);
TestHelpers.VerifyCommandOption(command.Options, "verbose", false);
TestHelpers.VerifyCommandOption(command.Options, "ghes-api-url", false);
TestHelpers.VerifyCommandOption(command.Options, "target-api-url", false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public void Should_Have_Options()
var command = new ReclaimMannequinCommand();
Assert.NotNull(command);
Assert.Equal("reclaim-mannequin", command.Name);
Assert.Equal(10, command.Options.Count);
Assert.Equal(11, command.Options.Count);

TestHelpers.VerifyCommandOption(command.Options, "github-org", true);
TestHelpers.VerifyCommandOption(command.Options, "csv", false);
Expand All @@ -22,6 +22,7 @@ public void Should_Have_Options()
TestHelpers.VerifyCommandOption(command.Options, "no-prompt", false);
TestHelpers.VerifyCommandOption(command.Options, "github-pat", false);
TestHelpers.VerifyCommandOption(command.Options, "skip-invitation", false);
TestHelpers.VerifyCommandOption(command.Options, "target-api-url", false);
TestHelpers.VerifyCommandOption(command.Options, "verbose", false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ public void Should_Have_Options()
var command = new GenerateMannequinCsvCommand();
Assert.NotNull(command);
Assert.Equal("generate-mannequin-csv", command.Name);
Assert.Equal(5, command.Options.Count);
Assert.Equal(6, command.Options.Count);

TestHelpers.VerifyCommandOption(command.Options, "github-org", true);
TestHelpers.VerifyCommandOption(command.Options, "output", false);
TestHelpers.VerifyCommandOption(command.Options, "include-reclaimed", false);
TestHelpers.VerifyCommandOption(command.Options, "github-pat", false);
TestHelpers.VerifyCommandOption(command.Options, "verbose", false);
TestHelpers.VerifyCommandOption(command.Options, "target-api-url", false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ public void Should_Have_Options()
var command = new GrantMigratorRoleCommand();
Assert.NotNull(command);
Assert.Equal("grant-migrator-role", 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, "actor", true);
TestHelpers.VerifyCommandOption(command.Options, "actor-type", true);
TestHelpers.VerifyCommandOption(command.Options, "github-pat", false);
TestHelpers.VerifyCommandOption(command.Options, "verbose", false);
TestHelpers.VerifyCommandOption(command.Options, "ghes-api-url", false);
TestHelpers.VerifyCommandOption(command.Options, "target-api-url", false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public void Should_Have_Options()
var command = new ReclaimMannequinCommand();
Assert.NotNull(command);
Assert.Equal("reclaim-mannequin", command.Name);
Assert.Equal(10, command.Options.Count);
Assert.Equal(11, command.Options.Count);

TestHelpers.VerifyCommandOption(command.Options, "github-org", true);
TestHelpers.VerifyCommandOption(command.Options, "csv", false);
Expand All @@ -22,6 +22,7 @@ public void Should_Have_Options()
TestHelpers.VerifyCommandOption(command.Options, "no-prompt", false);
TestHelpers.VerifyCommandOption(command.Options, "github-pat", false);
TestHelpers.VerifyCommandOption(command.Options, "skip-invitation", false);
TestHelpers.VerifyCommandOption(command.Options, "target-api-url", false);
TestHelpers.VerifyCommandOption(command.Options, "verbose", false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ public void Should_Have_Options()
var command = new GenerateMannequinCsvCommand();
Assert.NotNull(command);
Assert.Equal("generate-mannequin-csv", command.Name);
Assert.Equal(5, command.Options.Count);
Assert.Equal(6, command.Options.Count);

TestHelpers.VerifyCommandOption(command.Options, "github-target-org", true);
TestHelpers.VerifyCommandOption(command.Options, "output", false);
TestHelpers.VerifyCommandOption(command.Options, "include-reclaimed", false);
TestHelpers.VerifyCommandOption(command.Options, "github-target-pat", false);
TestHelpers.VerifyCommandOption(command.Options, "verbose", false);
TestHelpers.VerifyCommandOption(command.Options, "target-api-url", false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ public void Should_Have_Options()
var command = new GrantMigratorRoleCommand();
Assert.NotNull(command);
Assert.Equal("grant-migrator-role", 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, "actor", true);
TestHelpers.VerifyCommandOption(command.Options, "actor-type", true);
TestHelpers.VerifyCommandOption(command.Options, "github-target-pat", false);
TestHelpers.VerifyCommandOption(command.Options, "verbose", false);
TestHelpers.VerifyCommandOption(command.Options, "ghes-api-url", false);
TestHelpers.VerifyCommandOption(command.Options, "target-api-url", false);
}
}
Loading

0 comments on commit 02548b5

Please sign in to comment.