diff --git a/src/Octoshift/Services/GithubApi.cs b/src/Octoshift/Services/GithubApi.cs index 498edb77..a3e13caa 100644 --- a/src/Octoshift/Services/GithubApi.cs +++ b/src/Octoshift/Services/GithubApi.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; using System.Net.Http; @@ -1071,6 +1072,33 @@ mutation abortRepositoryMigration( } } + public virtual async Task UploadArchiveToGithubStorage(string orgDatabaseId, bool isMultipart, string archiveName, Stream archiveContent) + { + using var httpContent = new StreamContent(archiveContent); + string response; + + if (isMultipart) + { + var url = $"https://uploads.github.com/organizations/{orgDatabaseId.EscapeDataString()}/gei/archive/blobs/uploads"; + + using var content = new MultipartFormDataContent + { + { httpContent, "archive", archiveName } + }; + + response = await _client.PostAsync(url, content); + } + else + { + var url = $"https://uploads.github.com/organizations/{orgDatabaseId.EscapeDataString()}/gei/archive?name={archiveName.EscapeDataString()}"; + + response = await _client.PostAsync(url, httpContent); + } + + var data = JObject.Parse(response); + return "gei://archive/" + (string)data["archiveId"]; + } + private static object GetMannequinsPayload(string orgId) { var query = "query($id: ID!, $first: Int, $after: String)"; diff --git a/src/Octoshift/Services/GithubClient.cs b/src/Octoshift/Services/GithubClient.cs index 10c52390..a038c223 100644 --- a/src/Octoshift/Services/GithubClient.cs +++ b/src/Octoshift/Services/GithubClient.cs @@ -162,9 +162,14 @@ public virtual async Task PatchAsync(string url, object body, Dictionary if (body != null) { - _log.LogVerbose($"HTTP BODY: {body.ToJson()}"); + _log.LogVerbose(body is MultipartFormDataContent or StreamContent ? "HTTP BODY: BLOB" : $"HTTP BODY: {body.ToJson()}"); - request.Content = body.ToJson().ToStringContent(); + request.Content = body switch + { + MultipartFormDataContent multipartFormDataContent => multipartFormDataContent, + StreamContent streamContent => streamContent, + _ => body.ToJson().ToStringContent() + }; } using var response = await _httpClient.SendAsync(request); diff --git a/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs b/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs index 56d93ae6..a3696ff2 100644 --- a/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs +++ b/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.IO; using System.Linq; using System.Net; using System.Net.Http; @@ -3462,6 +3463,62 @@ await _githubApi.Invoking(api => api.AbortMigration(migrationId)) .WithMessage(expectedErrorMessage); } + [Fact] + public async Task UploadArchiveToGithubStorage() + { + //Arange + const string org = "1234"; + const bool isMultipart = false; + const string archiveName = "archiveName"; + + // Using a MemoryStream as a valid stream implementation + using var archiveContent = new MemoryStream(new byte[] { 1, 2, 3 }); + var expectedArchiveId = "123456"; + var jsonResponse = $"{{ \"archiveId\": \"{expectedArchiveId}\" }}"; + + _githubClientMock + .Setup(m => m.PostAsync(It.IsAny(), It.IsAny(), null)) + .ReturnsAsync(jsonResponse); + + var expectedStringResponse = "gei://archive/" + expectedArchiveId; + + // Act + var actualStringResponse = await _githubApi.UploadArchiveToGithubStorage(org, isMultipart, archiveName, archiveContent); + + // Assert + expectedStringResponse.Should().Be(actualStringResponse); + + } + + + [Fact] + public async Task UploadArchiveToGithubStorageWithMultiPart() + { + //Arange + const string org = "123455"; + const bool isMultipart = true; + const string archiveName = "archiveName"; + + // Using a MemoryStream as a valid stream implementation + using var archiveContent = new MemoryStream(new byte[] { 1, 2, 3 }); + + var expectedArchiveId = "123456"; + var jsonResponse = $"{{ \"archiveId\": \"{expectedArchiveId}\" }}"; + + _githubClientMock + .Setup(m => m.PostAsync(It.IsAny(), It.IsAny(), null)) + .ReturnsAsync(jsonResponse); + + var expectedStringResponse = "gei://archive/" + expectedArchiveId; + + // Act + var actualStringResponse = await _githubApi.UploadArchiveToGithubStorage(org, isMultipart, archiveName, archiveContent); + + // Assert + expectedStringResponse.Should().Be(actualStringResponse); + + } + private string Compact(string source) => source .Replace("\r", "") @@ -3471,5 +3528,4 @@ private string Compact(string source) => .Replace("\\n", "") .Replace("\\t", "") .Replace(" ", ""); - }