Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PART 3: Add UploadArchiveToGithubStorageWithMultiPart method #1271

Merged
merged 8 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/Octoshift/Services/GithubApi.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
Expand Down Expand Up @@ -1047,6 +1048,33 @@ mutation abortRepositoryMigration(
}
}

public virtual async Task<string> UploadArchiveToGithubStorage(string org, bool isMultipart, string archiveName, Stream archiveContent)
{
using var httpContent = new StreamContent(archiveContent);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I would call this variable streamContent for clarity as both stream and multipart from data are technically HttpContent"

Suggested change
using var httpContent = new StreamContent(archiveContent);
using var streamContent = 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 }
};
Comment on lines +1084 to +1087
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initializing a using variable with an object initializer might lead to problems if an exception is thrown during the initialization and the using variable may never get disposed so here it's better to add the content with the Add() method:

Suggested change
using var content = new MultipartFormDataContent
{
{ httpContent, "archive", archiveName }
};
using var content = new MultipartFormDataContent();
content.Add(streamContent, "archive", archiveName);


response = await _client.PostAsync(url, content);
begonaguereca marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
var url = $"https://uploads.github.com/organizations/{org.EscapeDataString()}/gei/archive\\?name\\={archiveName}";
begonaguereca marked this conversation as resolved.
Show resolved Hide resolved

response = await _client.PostAsync(url, httpContent);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renaming httpContent to streamContent:

Suggested change
response = await _client.PostAsync(url, httpContent);
response = await _client.PostAsync(url, streamContent);

}

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)";
Expand Down
110 changes: 101 additions & 9 deletions src/OctoshiftCLI.Tests/Octoshift/Services/GithubApiTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
Expand Down Expand Up @@ -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()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public async Task UploadArchiveToGithubStorage()
public async Task UploadArchiveToGithubStorage_Should_Upload_Stream_Content()

{
//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}";
Fixed Show fixed Hide fixed

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<HttpContent>()))
.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()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use snaked cased test names throughout the project:

Suggested change
public async Task UploadArchiveToGithubStorageWithMultiPart()
public async Task UploadArchiveToGithubStorage_Should_Upload_Multipart_Content()

{
//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}";
Fixed Show fixed Hide fixed

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
}
}
}
};
Fixed Show fixed Hide fixed

_githubClientMock
.Setup(m => m.PostAsync(url, It.IsAny<HttpContent>()))
.ReturnsAsync(jsonResponse);

var expectedStringResponse = "gei://archive/" + expectedArchiveId;

// Act
var actualStringResponse = await _githubApi.UploadArchiveToGithubStorage(org, isMultipart, archiveName, archiveContent);

// Assert
expectedStringResponse.Should().Be(actualStringResponse);

}
}
Loading