Nuke: Deploy Helm package locally (special guest, GitVersion)

Somebody who likes to code
Search for a command to run...

Somebody who likes to code
No comments yet. Be the first to comment.
Nuke is an open source, cross-platform build automation solution for .NET projects. Nuke prides itself on its simplicity and extensibility that makes build automation approachable for everyone.
Unit tests help to ensure functionality and provide a means of verification for refactoring efforts. Code coverage is a measurement of the amount of code that is run by unit tests - either lines, branches, or methods. In this post we will see how to...
Google processes tens of thousands of code changes every day across a codebase of hundreds of millions of lines. The secret isn't magic tooling — it's a documented, principled approach to code review

Amazon Simple Notification Service (SNS) looks straightforward on the surface — publish a message, deliver it to subscribers — but the gap between a topic that "works in dev" and one that is productio

Amazon Simple Queue Service (SQS) is deceptively simple to get started with, but surprisingly easy to misconfigure in ways that cause silent message loss, runaway costs, duplicate processing storms, o

HTTP API is the right default choice for the majority of .NET serverless workloads. At 70% less cost than REST API, lower latency, and native JWT authorization, it covers most production requirements

AWS Lambda has become a cornerstone of modern serverless architectures, but writing a function that "just works" is very different from writing one that is performant, cost-effective, secure, and read

Today, we will continue our journey with Nuke by adding new targets to the solution presented in Nuke: Deploy ASP.NET Web App to Azure. This time, we will deploy our app to a local Kubernetes cluster using Helm.
But first, we will need the following:
A standalone Kubernetes server and client.
Our first target will get the build number using GitVersion (we discussed it in Semantic Versioning with GitVersion). Let's start by adding the following NuGet package::
Next, add the following namespaces to access all gitversion commands:
using static Nuke.Common.Tools.GitVersion.GitVersionTasks;
using Nuke.Common.Tools.GitVersion;
Add a variable to store the generated build number:
private string BuildNumber;
And now, the target itself:
Target GetBuildNumber => _ => _
.Executes(() =>
{
var (result, _) = GitVersion();
BuildNumber = result.SemVer;
});
The first step is to create a Dockerfile in our project folder as follows:
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app
# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore "./nuke-sandbox-app/nuke-sandbox-app.csproj"
# Build and publish a release
RUN dotnet publish "./nuke-sandbox-app/nuke-sandbox-app.csproj" -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "nuke-sandbox-app.dll"]
Add the following namespaces to access all docker commands:
using static Nuke.Common.Tools.Docker.DockerTasks;
using Nuke.Common.Tools.Docker;
Add a variable to store the Docker image repository used in the project:
private readonly string Repository = "raulnq/nuke-sandbox-app";
And for the final step, add the target:
Target BuildImage => _ => _
.DependsOn(GetBuildNumber)
.Executes(() =>
{
var dockerFile = RootDirectory / "nuke-sandbox-app" / "Dockerfile";
var image = $"{Repository}:{BuildNumber}";
DockerBuild(s => s
.SetPath(RootDirectory)
.SetFile(dockerFile)
.SetTag(image)
);
});
And finally, here is the step to install the Helm package in the Kubernetes cluster. You can first check Useful commands for Helm. Go to your solution folder and run the following commands to create the Helm package:
mkdir helm
cd helm
helm create nuke-sandbox-app
Keep only these files in your Helm package:
helm\nuke-sandbox-app
|-- templates
| |-- _helpers.tpl
| |-- deployment.yaml
| `-- service.yaml
|-- .helmignore
|-- Chart.yaml
`-- values.yaml
Modify the deployment.yaml file as follows:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "nuke-sandbox-app.fullname" . }}
labels:
{{- include "nuke-sandbox-app.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "nuke-sandbox-app.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "nuke-sandbox-app.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 80
protocol: TCP
The service.yaml file:
apiVersion: v1
kind: Service
metadata:
name: {{ include "nuke-sandbox-app.fullname" . }}
labels:
{{- include "nuke-sandbox-app.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "nuke-sandbox-app.selectorLabels" . | nindent 4 }}
And the values.yaml file:
replicaCount: 1
image:
repository: raulnq/nuke-sandbox-app
pullPolicy: IfNotPresent
tag: "1.0"
nameOverride: ""
fullnameOverride: ""
service:
type: ClusterIP
port: 80
Go back to the build.cs file and add:
using static Nuke.Common.Tools.Helm.HelmTasks;
using Nuke.Common.Tools.Helm;
using System.Collections.Generic;
Add a variable to store the Helm release name used in the project:
private readonly string ReleaseName = "release-nuke-sandbox-app";
To wrap up, we will add two targets: one to install and the other to uninstall the Helm package:
Target HelmInstall => _ => _
.DependsOn(BuildImage)
.Executes(() =>
{
var chart = HelmDirectory / "nuke-sandbox-app";
HelmUpgrade(s => s
.SetRelease(ReleaseName)
.SetSet(new Dictionary<string, object>() { { "image.tag", BuildNumber }, { "image.repository", Repository } })
.SetChart(chart)
.EnableInstall()
);
});
Target HelmUninstall => _ => _
.Executes(() =>
{
HelmDelete(s => s
.SetReleaseNames(ReleaseName)
);
});
That's it! Now it's time to run our Nuke command:
nuke HelmInstall
We can check our deployment with kubectl get deployments:
NAME READY UP-TO-DATE AVAILABLE AGE
release-nuke-sandbox-app 1/1 1 1 18s
And uninstall when needed:
nuke HelmUninstall
You can find the updated solution here.