Skip to content

Commit

Permalink
Test ChartMuseum
Browse files Browse the repository at this point in the history
  • Loading branch information
rasmus committed Aug 2, 2022
1 parent ac56b7e commit c747112
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 15 deletions.
1 change: 1 addition & 0 deletions Bake.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".build", ".build", "{F11194
ProjectSection(SolutionItems) = preProject
docker-compose.yml = docker-compose.yml
.github\workflows\pull-requests.yml = .github\workflows\pull-requests.yml
README.md = README.md
.github\workflows\release.yml = .github\workflows\release.yml
RELEASE_NOTES.md = RELEASE_NOTES.md
EndProjectSection
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ Here are some examples of common used arguments to Bake
* `helm-chart>octopus@http://octopus.local/` - Sends Helm charts to the built-in
repository in [Octopus Deploy][octopus-repository]. Bake looks for the API-key
in an environment variable named `OCTOPUS_DEPLOY_APIKEY`
* `helm-chart>chart-museum@http://chart-museum.local/` - Sends Helm charts to an
instance of [ChartMuseum](https://chartmuseum.com/)
* **NuGet**
* `nuget` - An unnamed destination will send NuGet packages to the central
NuGet repository at [nuget.org](https://www.nuget.org/). Bake will look for
Expand Down
2 changes: 1 addition & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 0.16-beta

* *Nothing yet...*
* New: Ability to upload Helm charts to ChartMuseum

# 0.15-beta

Expand Down
17 changes: 17 additions & 0 deletions Source/Bake.Tests/IntegrationTests/BakeTests/HelmChartTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,22 @@ public async Task PushToOctopusDeploy(
returnCode.Should().Be(0);
octopusDeploy.ReceivedPackages.Should().HaveCount(1);
}

[Test]
public async Task PushToChartMuseum()
{
// Arrange
var version = SemVer.Random.ToString();

// Act
var returnCode = await ExecuteAsync(TestState.New(
"run",
"--convention=Release",
$"--destination=helm-chart>chart-museum@http://localhost:5556",
"--build-version", version));

// Assert
returnCode.Should().Be(0);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System;
using System.Threading;
using System.Threading.Tasks;
using Bake.Services;
Expand All @@ -46,11 +47,13 @@ protected override async Task<bool> CookAsync(
ChartMuseumUploadRecipe recipe,
CancellationToken cancellationToken)
{
var url = new Uri(recipe.Url, "/api/charts");

foreach (var packagePath in recipe.Packages)
{
await _uploader.UploadAsync(
packagePath,
recipe.Url,
url,
cancellationToken);
}

Expand Down
10 changes: 5 additions & 5 deletions Source/Bake/Services/DestinationParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class DestinationParser : IDestinationParser
@"^[a-z\-0-9]+$",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex TypedDestination = new(
"^(?<type>[a-z]+)@(?<rest>.+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
"^(?<type>[a-z-]+)@(?<rest>.+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private const char Separator = '>';

private readonly IDefaults _defaults;
Expand Down Expand Up @@ -101,11 +101,11 @@ public bool TryParse(string str, out Destination destination)

destination = typedMatch.Groups["type"].Value switch
{
"octopus" => Uri.TryCreate(typedMatch.Groups["rest"].Value, UriKind.Absolute, out var octopusDeployUrl)
? new OctopusDeployDestination(octopusDeployUrl.AbsoluteUri)
"octopus" => Uri.TryCreate(typedMatch.Groups["rest"].Value, UriKind.Absolute, out var u1)
? new OctopusDeployDestination(u1.AbsoluteUri)
: null,
Names.Destinations.OctopusDeploy => Uri.TryCreate(typedMatch.Groups["rest"].Value, UriKind.Absolute, out var octopusDeployUrl)
? new ChartMuseumDestination(octopusDeployUrl.AbsoluteUri)
Names.Destinations.ChartMuseum => Uri.TryCreate(typedMatch.Groups["rest"].Value, UriKind.Absolute, out var u2)
? new ChartMuseumDestination(u2.AbsoluteUri)
: null,
_ => null
};
Expand Down
17 changes: 14 additions & 3 deletions Source/Bake/Services/Uploader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
using System.Threading;
using System.Threading.Tasks;
using Bake.Core;
using Microsoft.Extensions.Logging;

namespace Bake.Services
{
Expand All @@ -42,17 +43,21 @@ public class Uploader : IUploader
["gz"] = "application/gzip",
["png"] = "image/png",
["zip"] = "application/zip",
["tgz"] = "application/gzip",
};

private const string DefaultMediaType = "application/octet-stream";

private readonly ILogger<Uploader> _logger;
private readonly IHttpClientFactory _httpClientFactory;
private readonly IFileSystem _fileSystem;

public Uploader(
ILogger<Uploader> logger,
IHttpClientFactory httpClientFactory,
IFileSystem fileSystem)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
_fileSystem = fileSystem;
}
Expand All @@ -64,23 +69,29 @@ public async Task UploadAsync(
{
var file = _fileSystem.Open(filePath);
var fileName = Path.GetFileName(filePath);
var mediaType = MediaTypes.TryGetValue(Path.GetExtension(filePath), out var t) ? t : DefaultMediaType;
var fileExtension = Path.GetExtension(filePath).Trim('.');
var mediaType = MediaTypes.TryGetValue(fileExtension, out var t) ? t : DefaultMediaType;
var httpClient = _httpClientFactory.CreateClient();

_logger.LogInformation(
"Uploading file {FileName} with extension {Extension} and MIME type {MIME} to URL {Url}",
fileName, fileExtension, mediaType, url);

await using var stream = await file.OpenReadAsync(cancellationToken);

using var multipartFormDataContent = new MultipartFormDataContent();

var fileStreamContent = new StreamContent(stream);
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue(mediaType);

multipartFormDataContent.Add(fileStreamContent, name: "file", fileName: fileName);
multipartFormDataContent.Add(fileStreamContent, name: "chart", fileName: fileName);

var response = await httpClient.PostAsync(url, multipartFormDataContent, cancellationToken);

if (!response.IsSuccessStatusCode)
{
throw new Exception($"POST {url} failed with {response.StatusCode}");
var content = await response.Content.ReadAsStringAsync(cancellationToken);
throw new Exception($"POST {url} failed with {response.StatusCode}{Environment.NewLine}{content[..(Math.Min(content.Length, 1024) - 1)]}");
}
}
}
Expand Down
18 changes: 13 additions & 5 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,18 @@ services:
registry:
image: registry:2
ports:
- 5000:5000
- 5000:5000
environment:
REGISTRY_AUTH: "htpasswd"
REGISTRY_AUTH_HTPASSWD_REALM: "Bake test registry"
REGISTRY_AUTH_HTPASSWD_PATH: "/auth/htpasswd"
REGISTRY_AUTH: "htpasswd"
REGISTRY_AUTH_HTPASSWD_REALM: "Bake test registry"
REGISTRY_AUTH_HTPASSWD_PATH: "/auth/htpasswd"
volumes:
- ./Services/Registry:/auth
- ./Services/Registry:/auth

chart-museum:
image: ghcr.io/helm/chartmuseum:v0.15.0
ports:
- 5556:8080
environment:
STORAGE: local
STORAGE_LOCAL_ROOTDIR: /tmp

0 comments on commit c747112

Please sign in to comment.