Skip to content

Commit

Permalink
Helm charts (#59)
Browse files Browse the repository at this point in the history
* Started on packing Helm charts

* Pack Helm charts
  • Loading branch information
rasmus authored Dec 20, 2021
1 parent c321df9 commit 189765e
Show file tree
Hide file tree
Showing 30 changed files with 1,022 additions and 2 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# 0.6-beta

* New: Containers and their tags are now listed on GitHub releases
* New: Helm charts are now linted and packaged

# 0.5-beta

Expand Down
55 changes: 55 additions & 0 deletions Source/Bake.Tests/IntegrationTests/BakeTests/HelmChart.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// MIT License
//
// Copyright (c) 2021 Rasmus Mikkelsen
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System.Threading.Tasks;
using Bake.Core;
using Bake.Tests.Helpers;
using FluentAssertions;
using NUnit.Framework;

// ReSharper disable StringLiteralTypo

namespace Bake.Tests.IntegrationTests.BakeTests
{
public class HelmChart : BakeTest
{
public HelmChart() : base("helm-chart")
{
}

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

// Act
var returnCode = await ExecuteAsync(TestState.New(
"run",
"--convention=Release",
"--build-version", version));

// Assert
returnCode.Should().Be(0);
}
}
}
5 changes: 5 additions & 0 deletions Source/Bake/Cooking/Composers/DockerComposer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ public override async Task<IReadOnlyCollection<Recipe>> ComposeAsync(
}
}

if (!recipes.Any())
{
return new Recipe[] { };
}

if (_conventionInterpreter.ShouldArtifactsBePublished(ingredients.Convention))
{
var tags = recipes
Expand Down
105 changes: 105 additions & 0 deletions Source/Bake/Cooking/Composers/HelmComposer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// MIT License
//
// Copyright (c) 2021 Rasmus Mikkelsen
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Bake.Core;
using Bake.ValueObjects.Artifacts;
using Bake.ValueObjects.Recipes;
using Bake.ValueObjects.Recipes.Helm;
using YamlDotNet.Serialization;

namespace Bake.Cooking.Composers
{
public class HelmComposer : Composer
{
private readonly IFileSystem _fileSystem;
private readonly IYaml _yaml;

public override IReadOnlyCollection<ArtifactType> Produces { get; } = new[]
{
ArtifactType.HelmChart
};

public HelmComposer(
IFileSystem fileSystem,
IYaml yaml)
{
_fileSystem = fileSystem;
_yaml = yaml;
}

public override async Task<IReadOnlyCollection<Recipe>> ComposeAsync(
IContext context,
CancellationToken cancellationToken)
{
var chartFiles = await _fileSystem.FindFilesAsync(
context.Ingredients.WorkingDirectory,
"Chart.yaml",
cancellationToken);

var ingredients = context.Ingredients;

return (await Task.WhenAll(chartFiles
.Select(p => CreateRecipes(p, ingredients, cancellationToken))))
.SelectMany(r => r)
.ToArray();
}

private async Task<IReadOnlyCollection<Recipe>> CreateRecipes(
string chartFilePath,
ValueObjects.Ingredients ingredients,
CancellationToken cancellationToken)
{
var recipes = new List<Recipe>();

var yaml = await _fileSystem.ReadAllTextAsync(chartFilePath, cancellationToken);
var chart = await _yaml.DeserializeAsync<HelmChart>(
yaml,
cancellationToken);

var chartDirectory = Path.GetDirectoryName(chartFilePath);
var chartFileName = $"{chart.Name}-{ingredients.Version}.tgz";
var parentDirectory = Path.GetDirectoryName(chartDirectory);

recipes.Add(new HelmLintRecipe(
chartDirectory));
recipes.Add(new HelmPackageRecipe(
chartDirectory,
parentDirectory,
ingredients.Version,
new HelmChartArtifact(
Path.Combine(parentDirectory, chartFileName))));

return recipes;
}

private class HelmChart
{
[YamlMember(Alias = "name")]
public string Name { get; set; }
}
}
}
56 changes: 56 additions & 0 deletions Source/Bake/Cooking/Cooks/Helm/HelmLintCook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// MIT License
//
// Copyright (c) 2021 Rasmus Mikkelsen
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System.Threading;
using System.Threading.Tasks;
using Bake.Services.Tools;
using Bake.Services.Tools.HelmArguments;
using Bake.ValueObjects.Recipes.Helm;

namespace Bake.Cooking.Cooks.Helm
{
public class HelmLintCook : Cook<HelmLintRecipe>
{
private readonly IHelm _helm;

public HelmLintCook(
IHelm helm)
{
_helm = helm;
}

protected override async Task<bool> CookAsync(
IContext context,
HelmLintRecipe recipe,
CancellationToken cancellationToken)
{
var argument = new HelmLintArgument(
recipe.ChartDirectory);

var toolResult = await _helm.LintAsync(
argument,
cancellationToken);

return toolResult.WasSuccessful;
}
}
}
58 changes: 58 additions & 0 deletions Source/Bake/Cooking/Cooks/Helm/HelmPackageCook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// MIT License
//
// Copyright (c) 2021 Rasmus Mikkelsen
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System.Threading;
using System.Threading.Tasks;
using Bake.Services.Tools;
using Bake.Services.Tools.HelmArguments;
using Bake.ValueObjects.Recipes.Helm;

namespace Bake.Cooking.Cooks.Helm
{
public class HelmPackageCook : Cook<HelmPackageRecipe>
{
private readonly IHelm _helm;

public HelmPackageCook(
IHelm helm)
{
_helm = helm;
}

protected override async Task<bool> CookAsync(
IContext context,
HelmPackageRecipe recipe,
CancellationToken cancellationToken)
{
var argument = new HelmPackageArgument(
recipe.ChartDirectory,
recipe.OutputDirectory,
recipe.Version);

var toolResult = await _helm.PackageAsync(
argument,
cancellationToken);

return toolResult.WasSuccessful;
}
}
}
2 changes: 1 addition & 1 deletion Source/Bake/Core/FileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public async Task<IFile> CompressAsync(

public async Task<string> ReadAllTextAsync(
string filePath,
CancellationToken _)
CancellationToken cancellationToken)
{
await using var file = System.IO.File.Open(
filePath,
Expand Down
2 changes: 1 addition & 1 deletion Source/Bake/Core/IFileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Task<IReadOnlyCollection<string>> FindFilesAsync(

Task<string> ReadAllTextAsync(
string filePath,
CancellationToken _);
CancellationToken cancellationToken);

IFile Open(string filePath);

Expand Down
1 change: 1 addition & 0 deletions Source/Bake/Core/Yaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ static Yaml()
(b, a) => b.WithTagMapping(a.tag, a.type))
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.WithTypeConverter(new SemVerYamlTypeConverter())
.IgnoreUnmatchedProperties()
.Build();
Serializer = recipeTypes.Aggregate(
new SerializerBuilder(),
Expand Down
6 changes: 6 additions & 0 deletions Source/Bake/Extensions/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
using Bake.Cooking.Cooks.DotNet;
using Bake.Cooking.Cooks.GitHub;
using Bake.Cooking.Cooks.Go;
using Bake.Cooking.Cooks.Helm;
using Bake.Cooking.Cooks.MkDocs;
using Bake.Cooking.Cooks.Pip;
using Bake.Cooking.Ingredients.Gathers;
Expand Down Expand Up @@ -75,6 +76,7 @@ public static IServiceCollection AddBake(
.AddTransient<IPlatformParser, PlatformParser>()
.AddTransient<IMkDocs, MkDocs>()
.AddTransient<IComposerOrdering, ComposerOrdering>()
.AddTransient<IHelm, Helm>()

// Gathers
.AddTransient<IGather, GitGather>()
Expand All @@ -93,6 +95,7 @@ public static IServiceCollection AddBake(
.AddTransient<IComposer, DockerComposer>()
.AddTransient<IComposer, GoComposer>()
.AddTransient<IComposer, MkDocsComposer>()
.AddTransient<IComposer, HelmComposer>()
.AddTransient<IComposer, ReleaseComposer>()

// Cooks - .NET
Expand All @@ -113,6 +116,9 @@ public static IServiceCollection AddBake(
.AddTransient<ICook, GoDockerFileCook>()
// Cooks - Pip
.AddTransient<ICook, PipInstallRequirementsCook>()
// Cooks - Helm
.AddTransient<ICook, HelmLintCook>()
.AddTransient<ICook, HelmPackageCook>()
// Cooks - GitHub
.AddTransient<ICook, GitHubReleaseCook>()
// Cooks - MkDocs
Expand Down
7 changes: 7 additions & 0 deletions Source/Bake/Names.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public static class Artifacts
public const string NuGetArtifact = "nuget-artifact";
public const string DirectoryArtifact = "directory-artifact";
public const string DocumentationSiteArtifact = "documentation-site-artifact";
public const string HelmChartArtifact = "helm-chart-artifact";
}

public static class ArtifactTypes
Expand Down Expand Up @@ -113,6 +114,12 @@ public static class GitHub
public const string Release = "github-release";
}

public static class Helm
{
public const string Lint = "helm-lint";
public const string Package = "helm-package";
}

public static class MkDocs
{
public const string Release = "mkdocs-build";
Expand Down
Loading

0 comments on commit 189765e

Please sign in to comment.