Skip to content

Commit

Permalink
Merge pull request #980 from github/write-warnings-count-to-console-w…
Browse files Browse the repository at this point in the history
…hen-migration-completes

Display number of migration log warnings encountered after a migration completes
  • Loading branch information
gohana authored Aug 9, 2023
2 parents 8a2ea83 + bba1c1a commit 1a20ec6
Show file tree
Hide file tree
Showing 22 changed files with 380 additions and 73 deletions.
2 changes: 1 addition & 1 deletion RELEASENOTES.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@

- Log migration warnings count after a migration completes
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ public override WaitForMigrationCommandHandler BuildHandler(WaitForMigrationComm

var log = sp.GetRequiredService<OctoLogger>();
var githubApi = sp.GetRequiredService<ITargetGithubApiFactory>().Create(targetPersonalAccessToken: args.GithubPat);
var warningsCountLogger = sp.GetRequiredService<WarningsCountLogger>();

return new WaitForMigrationCommandHandler(log, githubApi);
return new WaitForMigrationCommandHandler(log, githubApi, warningsCountLogger);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ public class WaitForMigrationCommandHandler : ICommandHandler<WaitForMigrationCo

private readonly OctoLogger _log;
private readonly GithubApi _githubApi;
private readonly WarningsCountLogger _warningsCountLogger;


public WaitForMigrationCommandHandler(OctoLogger log, GithubApi githubApi)
public WaitForMigrationCommandHandler(OctoLogger log, GithubApi githubApi, WarningsCountLogger warningsCountLogger)
{
_log = log;
_githubApi = githubApi;
_warningsCountLogger = warningsCountLogger;
}

public async Task Handle(WaitForMigrationCommandArgs args)
Expand Down Expand Up @@ -77,7 +78,7 @@ private async Task WaitForRepositoryMigration(string migrationId, GithubApi gith
{
_log.LogInformation($"Waiting for migration (ID: {migrationId}) to finish...");

var (state, repositoryName, failureReason, migrationLogUrl) = await githubApi.GetMigration(migrationId);
var (state, repositoryName, warningsCount, failureReason, migrationLogUrl) = await githubApi.GetMigration(migrationId);

_log.LogInformation($"Waiting for migration of repository {repositoryName} to finish...");

Expand All @@ -86,13 +87,15 @@ private async Task WaitForRepositoryMigration(string migrationId, GithubApi gith
if (RepositoryMigrationStatus.IsSucceeded(state))
{
_log.LogSuccess($"Migration {migrationId} succeeded for {repositoryName}");
_warningsCountLogger.LogWarningsCount(warningsCount);
_log.LogInformation($"Migration log available at {migrationLogUrl} or by running `gh {CliContext.RootCommand} download-logs`");
return;
}

if (RepositoryMigrationStatus.IsFailed(state))
{
_log.LogError($"Migration {migrationId} failed for {repositoryName}");
_warningsCountLogger.LogWarningsCount(warningsCount);
_log.LogInformation($"Migration log available at {migrationLogUrl} or by running `gh {CliContext.RootCommand} download-logs`");
throw new OctoshiftCliException(failureReason);
}
Expand All @@ -101,7 +104,7 @@ private async Task WaitForRepositoryMigration(string migrationId, GithubApi gith
_log.LogInformation($"Waiting {WaitIntervalInSeconds} seconds...");
await Task.Delay(WaitIntervalInSeconds * 1000);

(state, repositoryName, failureReason, migrationLogUrl) = await githubApi.GetMigration(migrationId);
(state, repositoryName, warningsCount, failureReason, migrationLogUrl) = await githubApi.GetMigration(migrationId);
}
}
}
19 changes: 17 additions & 2 deletions src/Octoshift/Services/GithubApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -488,12 +488,26 @@ public virtual async Task<string> StartBbsMigration(string migrationSourceId, st
);
}

public virtual async Task<(string State, string RepositoryName, string FailureReason, string MigrationLogUrl)> GetMigration(string migrationId)
public virtual async Task<(string State, string RepositoryName, int WarningsCount, string FailureReason, string MigrationLogUrl)> GetMigration(string migrationId)
{
var url = $"{_apiUrl}/graphql";

var query = "query($id: ID!)";
var gql = "node(id: $id) { ... on Migration { id, sourceUrl, migrationLogUrl, migrationSource { name }, state, failureReason, repositoryName } }";
var gql = @"
node(id: $id) {
... on Migration {
id,
sourceUrl,
migrationLogUrl,
migrationSource {
name
},
state,
warningsCount,
failureReason,
repositoryName
}
}";

var payload = new { query = $"{query} {{ {gql} }}", variables = new { id = migrationId } };

Expand All @@ -506,6 +520,7 @@ public virtual async Task<string> StartBbsMigration(string migrationSourceId, st
return (
State: (string)data["data"]["node"]["state"],
RepositoryName: (string)data["data"]["node"]["repositoryName"],
WarningsCount: (int)data["data"]["node"]["warningsCount"],
FailureReason: (string)data["data"]["node"]["failureReason"],
MigrationLogUrl: (string)data["data"]["node"]["migrationLogUrl"]);
});
Expand Down
26 changes: 26 additions & 0 deletions src/Octoshift/Services/WarningsCountLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace OctoshiftCLI.Services;

public class WarningsCountLogger
{
private readonly OctoLogger _log;

public WarningsCountLogger(OctoLogger logger)
{
_log = logger;
}

public void LogWarningsCount(int warningsCount)
{
switch (warningsCount)
{
case 0:
break;
case 1:
_log.LogWarning("1 warning encountered during this migration");
break;
default:
_log.LogWarning($"{warningsCount} warnings encountered during this migration");
break;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class WaitForMigrationCommandHandlerTests
private readonly Mock<GithubApi> _mockGithubApi = TestHelpers.CreateMock<GithubApi>();
private readonly Mock<OctoLogger> _mockOctoLogger = TestHelpers.CreateMock<OctoLogger>();

private readonly WarningsCountLogger _warningsCountLogger;
private readonly WaitForMigrationCommandHandler _handler;

private const string REPO_MIGRATION_ID = "RM_MIGRATION_ID";
Expand All @@ -23,20 +24,21 @@ public class WaitForMigrationCommandHandlerTests

public WaitForMigrationCommandHandlerTests()
{
_handler = new WaitForMigrationCommandHandler(_mockOctoLogger.Object, _mockGithubApi.Object)
_warningsCountLogger = new WarningsCountLogger(_mockOctoLogger.Object);
_handler = new WaitForMigrationCommandHandler(_mockOctoLogger.Object, _mockGithubApi.Object, _warningsCountLogger)
{
WaitIntervalInSeconds = WAIT_INTERVAL
};
}

[Fact]
public async Task With_Migration_ID_That_Succeeds()
public async Task With_Migration_ID_That_Succeeds_With_No_Warnings()
{
// Arrange
_mockGithubApi.SetupSequence(x => x.GetMigration(REPO_MIGRATION_ID).Result)
.Returns((State: RepositoryMigrationStatus.InProgress, RepositoryName: TARGET_REPO, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.InProgress, RepositoryName: TARGET_REPO, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.Succeeded, RepositoryName: TARGET_REPO, FailureReason: null, MigrationLogUrl: MIGRATION_URL));
.Returns((State: RepositoryMigrationStatus.InProgress, RepositoryName: TARGET_REPO, WarningsCount: 0, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.InProgress, RepositoryName: TARGET_REPO, WarningsCount: 0, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.Succeeded, RepositoryName: TARGET_REPO, WarningsCount: 0, FailureReason: null, MigrationLogUrl: MIGRATION_URL));
_mockGithubApi.Setup(x => x.GetMigrationLogUrl(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync((MIGRATION_URL, REPO_MIGRATION_ID));

var actualLogOutput = new List<string>();
Expand Down Expand Up @@ -73,16 +75,110 @@ public async Task With_Migration_ID_That_Succeeds()
_mockGithubApi.VerifyNoOtherCalls();
}

[Fact]
public async Task With_Migration_ID_That_Succeeds_With_1_Warning()
{
// Arrange
_mockGithubApi.SetupSequence(x => x.GetMigration(REPO_MIGRATION_ID).Result)
.Returns((State: RepositoryMigrationStatus.InProgress, RepositoryName: TARGET_REPO, WarningsCount: 0, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.InProgress, RepositoryName: TARGET_REPO, WarningsCount: 1, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.Succeeded, RepositoryName: TARGET_REPO, WarningsCount: 1, FailureReason: null, MigrationLogUrl: MIGRATION_URL));
_mockGithubApi.Setup(x => x.GetMigrationLogUrl(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync((MIGRATION_URL, REPO_MIGRATION_ID));

var actualLogOutput = new List<string>();
_mockOctoLogger.Setup(m => m.LogInformation(It.IsAny<string>())).Callback<string>(s => actualLogOutput.Add(s));
_mockOctoLogger.Setup(m => m.LogWarning(It.IsAny<string>())).Callback<string>(s => actualLogOutput.Add(s));
_mockOctoLogger.Setup(m => m.LogSuccess(It.IsAny<string>())).Callback<string>(s => actualLogOutput.Add(s));

var expectedLogOutput = new List<string>
{
$"Waiting for migration (ID: {REPO_MIGRATION_ID}) to finish...",
$"Waiting for migration of repository {TARGET_REPO} to finish...",
$"Migration {REPO_MIGRATION_ID} for {TARGET_REPO} is {RepositoryMigrationStatus.InProgress}",
$"Waiting {WAIT_INTERVAL} seconds...",
$"Migration {REPO_MIGRATION_ID} for {TARGET_REPO} is {RepositoryMigrationStatus.InProgress}",
$"Waiting {WAIT_INTERVAL} seconds...",
$"Migration {REPO_MIGRATION_ID} succeeded for {TARGET_REPO}",
"1 warning encountered during this migration",
$"Migration log available at {MIGRATION_URL} or by running `gh {CliContext.RootCommand} download-logs`"
};

// Act
var args = new WaitForMigrationCommandArgs
{
MigrationId = REPO_MIGRATION_ID,
};
await _handler.Handle(args);

// Assert
_mockOctoLogger.Verify(m => m.LogInformation(It.IsAny<string>()), Times.Exactly(7));
_mockOctoLogger.Verify(m => m.LogWarning(It.IsAny<string>()), Times.Once);
_mockOctoLogger.Verify(m => m.LogSuccess(It.IsAny<string>()), Times.Once);

_mockGithubApi.Verify(m => m.GetMigration(REPO_MIGRATION_ID), Times.Exactly(3));

actualLogOutput.Should().Equal(expectedLogOutput);

_mockGithubApi.VerifyNoOtherCalls();
}

[Fact]
public async Task With_Migration_ID_That_Succeeds_With_4_Warnings()
{
// Arrange
_mockGithubApi.SetupSequence(x => x.GetMigration(REPO_MIGRATION_ID).Result)
.Returns((State: RepositoryMigrationStatus.InProgress, RepositoryName: TARGET_REPO, WarningsCount: 0, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.InProgress, RepositoryName: TARGET_REPO, WarningsCount: 2, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.Succeeded, RepositoryName: TARGET_REPO, WarningsCount: 4, FailureReason: null, MigrationLogUrl: MIGRATION_URL));
_mockGithubApi.Setup(x => x.GetMigrationLogUrl(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync((MIGRATION_URL, REPO_MIGRATION_ID));

var actualLogOutput = new List<string>();
_mockOctoLogger.Setup(m => m.LogInformation(It.IsAny<string>())).Callback<string>(s => actualLogOutput.Add(s));
_mockOctoLogger.Setup(m => m.LogWarning(It.IsAny<string>())).Callback<string>(s => actualLogOutput.Add(s));
_mockOctoLogger.Setup(m => m.LogSuccess(It.IsAny<string>())).Callback<string>(s => actualLogOutput.Add(s));

var expectedLogOutput = new List<string>
{
$"Waiting for migration (ID: {REPO_MIGRATION_ID}) to finish...",
$"Waiting for migration of repository {TARGET_REPO} to finish...",
$"Migration {REPO_MIGRATION_ID} for {TARGET_REPO} is {RepositoryMigrationStatus.InProgress}",
$"Waiting {WAIT_INTERVAL} seconds...",
$"Migration {REPO_MIGRATION_ID} for {TARGET_REPO} is {RepositoryMigrationStatus.InProgress}",
$"Waiting {WAIT_INTERVAL} seconds...",
$"Migration {REPO_MIGRATION_ID} succeeded for {TARGET_REPO}",
"4 warnings encountered during this migration",
$"Migration log available at {MIGRATION_URL} or by running `gh {CliContext.RootCommand} download-logs`"
};

// Act
var args = new WaitForMigrationCommandArgs
{
MigrationId = REPO_MIGRATION_ID,
};
await _handler.Handle(args);

// Assert
_mockOctoLogger.Verify(m => m.LogInformation(It.IsAny<string>()), Times.Exactly(7));
_mockOctoLogger.Verify(m => m.LogWarning(It.IsAny<string>()), Times.Once);
_mockOctoLogger.Verify(m => m.LogSuccess(It.IsAny<string>()), Times.Once);

_mockGithubApi.Verify(m => m.GetMigration(REPO_MIGRATION_ID), Times.Exactly(3));

actualLogOutput.Should().Equal(expectedLogOutput);

_mockGithubApi.VerifyNoOtherCalls();
}

[Fact]
public async Task With_Migration_ID_That_Fails()
{
// Arrange
const string failureReason = "FAILURE_REASON";

_mockGithubApi.SetupSequence(x => x.GetMigration(REPO_MIGRATION_ID).Result)
.Returns((State: RepositoryMigrationStatus.InProgress, RepositoryName: TARGET_REPO, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.InProgress, RepositoryName: TARGET_REPO, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.Failed, RepositoryName: TARGET_REPO, FailureReason: failureReason, MigrationLogUrl: MIGRATION_URL));
.Returns((State: RepositoryMigrationStatus.InProgress, RepositoryName: TARGET_REPO, WarningsCount: 0, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.InProgress, RepositoryName: TARGET_REPO, WarningsCount: 0, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.Failed, RepositoryName: TARGET_REPO, WarningsCount: 0, FailureReason: failureReason, MigrationLogUrl: MIGRATION_URL));
_mockGithubApi.Setup(x => x.GetMigrationLogUrl(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync((MIGRATION_URL, REPO_MIGRATION_ID));

var actualLogOutput = new List<string>();
Expand Down Expand Up @@ -130,9 +226,9 @@ public async Task With_Migration_ID_That_Fails_Validation()
const string failureReason = "FAILURE_REASON";

_mockGithubApi.SetupSequence(x => x.GetMigration(REPO_MIGRATION_ID).Result)
.Returns((State: RepositoryMigrationStatus.PendingValidation, RepositoryName: TARGET_REPO, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.PendingValidation, RepositoryName: TARGET_REPO, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.FailedValidation, RepositoryName: TARGET_REPO, FailureReason: failureReason, MigrationLogUrl: MIGRATION_URL));
.Returns((State: RepositoryMigrationStatus.PendingValidation, RepositoryName: TARGET_REPO, WarningsCount: 0, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.PendingValidation, RepositoryName: TARGET_REPO, WarningsCount: 0, FailureReason: null, MigrationLogUrl: MIGRATION_URL))
.Returns((State: RepositoryMigrationStatus.FailedValidation, RepositoryName: TARGET_REPO, WarningsCount: 0, FailureReason: failureReason, MigrationLogUrl: MIGRATION_URL));
_mockGithubApi.Setup(x => x.GetMigrationLogUrl(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync((MIGRATION_URL, REPO_MIGRATION_ID));

var actualLogOutput = new List<string>();
Expand Down
Loading

0 comments on commit 1a20ec6

Please sign in to comment.