From aab0557e9eff67317a54565e228b689b4e90c367 Mon Sep 17 00:00:00 2001 From: Begona Guereca Date: Wed, 25 Sep 2024 14:00:56 -0700 Subject: [PATCH 1/7] Add UploadArchiveToGithubStorageWithMultiPart method --- src/Octoshift/Services/GithubApi.cs | 28 +++++ .../Octoshift/Services/GithubApiTests.cs | 110 ++++++++++++++++-- 2 files changed, 129 insertions(+), 9 deletions(-) diff --git a/src/Octoshift/Services/GithubApi.cs b/src/Octoshift/Services/GithubApi.cs index baca7a80f..ec4ea6321 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; @@ -1047,6 +1048,33 @@ mutation abortRepositoryMigration( } } + public virtual async Task UploadArchiveToGithubStorage(string org, bool isMultipart, string archiveName, Stream archiveContent) + { + using var httpContent = new StreamContent(archiveContent); + string response; + + if (isMultipart) + { + var url = $"https://uploads.github.com/organizations/{org.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/{org.EscapeDataString()}/gei/archive\\?name\\={archiveName}"; + + 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/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs b/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs index 962922ded..6b8df2bcb 100644 --- a/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs +++ b/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -3392,14 +3393,105 @@ await _githubApi.Invoking(api => api.AbortMigration(migrationId)) .WithMessage(expectedErrorMessage); } - private string Compact(string source) => - source - .Replace("\r", "") - .Replace("\n", "") - .Replace("\t", "") - .Replace("\\r", "") - .Replace("\\n", "") - .Replace("\\t", "") - .Replace(" ", ""); + [Fact] + public async Task UploadArchiveToGithubStorage() + { + //Arange + const string org = "org"; + 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 url = $"https://uploads.github.com/organizations/{org.EscapeDataString()}/gei/archive\\?name\\={archiveName}"; + + var expectedArchiveId = "123456"; + var jsonResponse = $"{{ \"archiveId\": \"{expectedArchiveId}\" }}"; + var payload = new + { + token = $"repoV2/{123}/{123}", + merge = true, + accessControlEntries = new[] + { + new + { + descriptor = "", + allow = 0, + deny = 56828, + extendedInfo = new + { + effectiveAllow = 0, + effectiveDeny = 56828, + inheritedAllow = 0, + inheritedDeny = 56828 + } + } + } + }; + + _githubClientMock + .Setup(m => m.PostAsync(url, It.IsAny())) + .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 = "org"; + 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 url = $"https://uploads.github.com/organizations/{org.EscapeDataString()}/gei/archive\\?name\\={archiveName}"; + + var expectedArchiveId = "123456"; + var jsonResponse = $"{{ \"archiveId\": \"{expectedArchiveId}\" }}"; + var payload = new + { + token = $"repoV2/{123}/{123}", + merge = true, + accessControlEntries = new[] + { + new + { + descriptor = "", + allow = 0, + deny = 56828, + extendedInfo = new + { + effectiveAllow = 0, + effectiveDeny = 56828, + inheritedAllow = 0, + inheritedDeny = 56828 + } + } + } + }; + + _githubClientMock + .Setup(m => m.PostAsync(url, It.IsAny())) + .ReturnsAsync(jsonResponse); + + var expectedStringResponse = "gei://archive/" + expectedArchiveId; + + // Act + var actualStringResponse = await _githubApi.UploadArchiveToGithubStorage(org, isMultipart, archiveName, archiveContent); + + // Assert + expectedStringResponse.Should().Be(actualStringResponse); + + } } From 1fca83d5d51251e9d3ee5f6cccaa09f87a358dac Mon Sep 17 00:00:00 2001 From: Begona Guereca Date: Tue, 8 Oct 2024 08:35:52 -0700 Subject: [PATCH 2/7] Make changes to SendAsync command --- src/Octoshift/Services/GithubClient.cs | 9 +++++++-- .../Octoshift/Services/GithubApiTests.cs | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Octoshift/Services/GithubClient.cs b/src/Octoshift/Services/GithubClient.cs index 2cae6402d..99099eee5 100644 --- a/src/Octoshift/Services/GithubClient.cs +++ b/src/Octoshift/Services/GithubClient.cs @@ -151,9 +151,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 6b8df2bcb..ae4310860 100644 --- a/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs +++ b/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs @@ -3408,6 +3408,7 @@ public async Task UploadArchiveToGithubStorage() var expectedArchiveId = "123456"; var jsonResponse = $"{{ \"archiveId\": \"{expectedArchiveId}\" }}"; + var payload = new { token = $"repoV2/{123}/{123}", @@ -3431,7 +3432,7 @@ public async Task UploadArchiveToGithubStorage() }; _githubClientMock - .Setup(m => m.PostAsync(url, It.IsAny())) + .Setup(m => m.PostAsync(It.IsAny(), It.IsAny(), null)) .ReturnsAsync(jsonResponse); var expectedStringResponse = "gei://archive/" + expectedArchiveId; @@ -3444,6 +3445,8 @@ public async Task UploadArchiveToGithubStorage() } + + [Fact] public async Task UploadArchiveToGithubStorageWithMultiPart() { @@ -3482,7 +3485,7 @@ public async Task UploadArchiveToGithubStorageWithMultiPart() }; _githubClientMock - .Setup(m => m.PostAsync(url, It.IsAny())) + .Setup(m => m.PostAsync(url, It.Is(x => x.ToJson() == payload.ToJson()), null)) .ReturnsAsync(jsonResponse); var expectedStringResponse = "gei://archive/" + expectedArchiveId; @@ -3494,4 +3497,13 @@ public async Task UploadArchiveToGithubStorageWithMultiPart() expectedStringResponse.Should().Be(actualStringResponse); } + private string Compact(string source) => + source + .Replace("\r", "") + .Replace("\n", "") + .Replace("\t", "") + .Replace("\\r", "") + .Replace("\\n", "") + .Replace("\\t", "") + .Replace(" ", ""); } From f81e02a84eeda5a53dac5a0ebfbd23d5a56977ab Mon Sep 17 00:00:00 2001 From: Begona Guereca Date: Tue, 8 Oct 2024 09:03:11 -0700 Subject: [PATCH 3/7] remove backslashed --- src/Octoshift/Services/GithubApi.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Octoshift/Services/GithubApi.cs b/src/Octoshift/Services/GithubApi.cs index ec4ea6321..35cf8b9ee 100644 --- a/src/Octoshift/Services/GithubApi.cs +++ b/src/Octoshift/Services/GithubApi.cs @@ -1066,7 +1066,7 @@ public virtual async Task UploadArchiveToGithubStorage(string org, bool } else { - var url = $"https://uploads.github.com/organizations/{org.EscapeDataString()}/gei/archive\\?name\\={archiveName}"; + var url = $"https://uploads.github.com/organizations/{org.EscapeDataString()}/gei/archive?name={archiveName}"; response = await _client.PostAsync(url, httpContent); } From 2c8de4ad4210de28b7fad506b9200520b56e01ab Mon Sep 17 00:00:00 2001 From: Begona Guereca Date: Tue, 8 Oct 2024 09:06:52 -0700 Subject: [PATCH 4/7] Escape string --- src/Octoshift/Services/GithubApi.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Octoshift/Services/GithubApi.cs b/src/Octoshift/Services/GithubApi.cs index 35cf8b9ee..acdb2962a 100644 --- a/src/Octoshift/Services/GithubApi.cs +++ b/src/Octoshift/Services/GithubApi.cs @@ -1066,7 +1066,7 @@ public virtual async Task UploadArchiveToGithubStorage(string org, bool } else { - var url = $"https://uploads.github.com/organizations/{org.EscapeDataString()}/gei/archive?name={archiveName}"; + var url = $"https://uploads.github.com/organizations/{org.EscapeDataString()}/gei/archive?name={archiveName.EscapeDataString()}"; response = await _client.PostAsync(url, httpContent); } From bf5eef2ad6c80c5cc5325e35d55b3bef8fe9239c Mon Sep 17 00:00:00 2001 From: Begona Guereca Date: Tue, 8 Oct 2024 10:16:53 -0700 Subject: [PATCH 5/7] Fixing unit tests --- src/Octoshift/Services/GithubApi.cs | 6 ++-- .../Octoshift/Services/GithubApiTests.cs | 30 +++---------------- 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/src/Octoshift/Services/GithubApi.cs b/src/Octoshift/Services/GithubApi.cs index 9482212ad..a3e13caac 100644 --- a/src/Octoshift/Services/GithubApi.cs +++ b/src/Octoshift/Services/GithubApi.cs @@ -1072,14 +1072,14 @@ mutation abortRepositoryMigration( } } - public virtual async Task UploadArchiveToGithubStorage(string org, bool isMultipart, string archiveName, Stream archiveContent) + 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/{org.EscapeDataString()}/gei/archive/blobs/uploads"; + var url = $"https://uploads.github.com/organizations/{orgDatabaseId.EscapeDataString()}/gei/archive/blobs/uploads"; using var content = new MultipartFormDataContent { @@ -1090,7 +1090,7 @@ public virtual async Task UploadArchiveToGithubStorage(string org, bool } else { - var url = $"https://uploads.github.com/organizations/{org.EscapeDataString()}/gei/archive?name={archiveName.EscapeDataString()}"; + var url = $"https://uploads.github.com/organizations/{orgDatabaseId.EscapeDataString()}/gei/archive?name={archiveName.EscapeDataString()}"; response = await _client.PostAsync(url, httpContent); } diff --git a/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs b/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs index 922d1129d..da101c1eb 100644 --- a/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs +++ b/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs @@ -3467,7 +3467,7 @@ await _githubApi.Invoking(api => api.AbortMigration(migrationId)) public async Task UploadArchiveToGithubStorage() { //Arange - const string org = "org"; + const string org = "1234"; const bool isMultipart = false; const string archiveName = "archiveName"; @@ -3479,28 +3479,6 @@ public async Task UploadArchiveToGithubStorage() var expectedArchiveId = "123456"; var jsonResponse = $"{{ \"archiveId\": \"{expectedArchiveId}\" }}"; - var payload = new - { - token = $"repoV2/{123}/{123}", - merge = true, - accessControlEntries = new[] - { - new - { - descriptor = "", - allow = 0, - deny = 56828, - extendedInfo = new - { - effectiveAllow = 0, - effectiveDeny = 56828, - inheritedAllow = 0, - inheritedDeny = 56828 - } - } - } - }; - _githubClientMock .Setup(m => m.PostAsync(It.IsAny(), It.IsAny(), null)) .ReturnsAsync(jsonResponse); @@ -3516,12 +3494,11 @@ public async Task UploadArchiveToGithubStorage() } - [Fact] public async Task UploadArchiveToGithubStorageWithMultiPart() { //Arange - const string org = "org"; + const string org = "123455"; const bool isMultipart = true; const string archiveName = "archiveName"; @@ -3555,7 +3532,7 @@ public async Task UploadArchiveToGithubStorageWithMultiPart() }; _githubClientMock - .Setup(m => m.PostAsync(url, It.Is(x => x.ToJson() == payload.ToJson()), null)) + .Setup(m => m.PostAsync(It.IsAny(), It.IsAny(), null)) .ReturnsAsync(jsonResponse); var expectedStringResponse = "gei://archive/" + expectedArchiveId; @@ -3567,6 +3544,7 @@ public async Task UploadArchiveToGithubStorageWithMultiPart() expectedStringResponse.Should().Be(actualStringResponse); } + private string Compact(string source) => source .Replace("\r", "") From 60e9ed1d26de72088f60e7d8b771fdb90d75ca1b Mon Sep 17 00:00:00 2001 From: Begona Guereca Date: Tue, 8 Oct 2024 10:22:39 -0700 Subject: [PATCH 6/7] alphabetical order --- src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs b/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs index da101c1eb..f8c83ae77 100644 --- a/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs +++ b/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs @@ -1,7 +1,7 @@ using System; -using System.IO; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.IO; using System.Linq; using System.Net; using System.Net.Http; From cd88309fb526667a21da786fec11334409071e87 Mon Sep 17 00:00:00 2001 From: Begona Guereca Date: Tue, 8 Oct 2024 10:28:21 -0700 Subject: [PATCH 7/7] clean up --- .../Octoshift/Services/GithubApiTests.cs | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs b/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs index f8c83ae77..a3696ff20 100644 --- a/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs +++ b/src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs @@ -3473,9 +3473,6 @@ public async Task UploadArchiveToGithubStorage() // Using a MemoryStream as a valid stream implementation using var archiveContent = new MemoryStream(new byte[] { 1, 2, 3 }); - - var url = $"https://uploads.github.com/organizations/{org.EscapeDataString()}/gei/archive\\?name\\={archiveName}"; - var expectedArchiveId = "123456"; var jsonResponse = $"{{ \"archiveId\": \"{expectedArchiveId}\" }}"; @@ -3505,31 +3502,8 @@ public async Task UploadArchiveToGithubStorageWithMultiPart() // Using a MemoryStream as a valid stream implementation using var archiveContent = new MemoryStream(new byte[] { 1, 2, 3 }); - var url = $"https://uploads.github.com/organizations/{org.EscapeDataString()}/gei/archive\\?name\\={archiveName}"; - var expectedArchiveId = "123456"; var jsonResponse = $"{{ \"archiveId\": \"{expectedArchiveId}\" }}"; - var payload = new - { - token = $"repoV2/{123}/{123}", - merge = true, - accessControlEntries = new[] - { - new - { - descriptor = "", - allow = 0, - deny = 56828, - extendedInfo = new - { - effectiveAllow = 0, - effectiveDeny = 56828, - inheritedAllow = 0, - inheritedDeny = 56828 - } - } - } - }; _githubClientMock .Setup(m => m.PostAsync(It.IsAny(), It.IsAny(), null))