This is a simple plugin for interacting with Helm in gradle builds.
This plugin is different from the alternatives listed at the bottom.
- Focus on a single thing and do it good: build charts.
- Thus only limited support for uploads/publishing. Although chartmuseum and artifactory should work, I recommend to use different ways of helm chart publishing as there's no official spec on how to do it (Helm 3 has experimental support for publishing to OCI registries). For example use the artifactory gradle plugin if you're using artifactory.
- the only plugin which has a real notion of chart tests including some simple types of assertions and a junit compatible XML report.
- zero config because of sane defaults
- ready for CI/CD, no dependencies to build environment (downloads appropriate Helm version automatically)
- provides task types:
HelmInitTask
: client only helm init, usually done only once, skipped for v3+HelmBuildTask
: render the expansions, build deps and package the chartHelmTestTask
: test the packaged chart- executes
helm lint
with default values - for each test:
- executes
helm lint
for test values - executes
helm template
for test values - runs any given assertions against rendered output
- executes
- stores test XML report into
.${buildDir}/helm/test/helm-junit-report.xml
- executes
HelmDeployTask
: uploads the packaged chart
- preconfigures all tasks according to DSL (see below)
Tested with Gradle 6
plugins {
id 'com.kiwigrid.helm' version '1.5.1'
}
// everything is optional
helm {
version '3.0.0' // defaults to 2.17.0
architecture 'amd64' // auto-detected if not given
operatingSystem 'linux' // auto-detected if not given
helmDownloadUrl 'https://example.com/helm.tar.gz' // defaults to 'https://get.helm.sh/helm-v${version}-${operatingSystem}-${architecture}.tar.gz'
// will be added via: helm repo add <name> <url>, non-existent will be removed (but 'local' and 'stable')
repositories {
myHelmRepoName {
url "https://example.com"
user "happy-dev" // username used for basic auth (supported since helm v2.9.0-rc3)
password "1234" // password used for basic auth (supported since helm v2.9.0-rc3)
deployVia 'PUT' to 'https://example.de/' // also supports 'POST', filename will be appended if url ends with '/' and method is 'PUT'
// shortcut if url is the same:
// deployVia 'PUT' toFetchUrl()
}
}
// expansions are replaced in the chart files if found in the form ${path.to.value}
expansions = [
helm: [
chartName:'my-chart',
chartVersion: project.version
],
anotherParam: project.version,
path: [
to: [
value: 'foobar'
]
]
]
// this will upload the chart to the respective repo using the appropriate deploy spec
deployTo repositories.myHelmRepoName
}
helmChartBuild() {
// source folder for the charts manifest files. just an example here, provide your own as needed
// defaults to file('/src/main/helm')
source = file(project.projectDir.getAbsolutePath() + '/helm')
}
helmChartTest() {
// source folder for the tests files. just an example here, provide your own as needed
// defaults to file('/src/test/helm')
tests = file(project.projectDir.getAbsolutePath() + "/helm/test")
}
// Optional. You need to register new pair of tasks for each additional helm chart in your project
// outputDirectory must be same in both tasks and differs from helm.outputDirectory
tasks.register("helmSecondChartBuild", HelmBuildTask.class) {
dependsOn tasks.named("helmRepoSync")
expansions = helm.expansions
copyFrom helm
// custom configuration
// source folder for the charts manifest files. just an example here, provide your own as needed
// defaults to file('/src/main/helm')
source = file('src/main/secondchart')
// output folder for the compiled charts manifest files. just an example here, provide your own as needed
outputDirectory = file("$buildDir/helm/repo2")
}
tasks.register("helmSecondChartTest", HelmBuildTask.class) {
dependsOn tasks.named("helmSecondChartBuild")
copyFrom helm
// custom configuration
// source folder for the tests files. just an example here, provide your own as needed
tests = file('src/test/secondchart')
// output folder for the compiled charts manifest files. just an example here, provide your own as needed
// defaults to file('/src/test/helm')
outputDirectory = file("$buildDir/helm/repo2")
}
<project folder>
|-- src/main/helm
| |-- Chart.yml
| `-- templates
| `-- ...
`-- src/test/helm
|-- test-suite01
| |-- values_test1.yaml
| `-- values_test2.yaml
|-- value-config-1.yaml
|-- value-config-2.yaml
`-- value-config-3.yaml
- the plugin automatically applies the base plugin and attaches tasks as dependencies to the lifecycle tasks
- If you're using Helm >=
2.8.0
helmChartTest
is locally rendering all templates for each test value file intobuild/helm/test/<value-file-name>/
so you can test drive how your templates react to values - If you're using Helm >=
2.9.0-rc3
helmChartTest
is linting once with default values and once per test so you can test drive various value combinations.- authenticated repositories are supported (using basic auth)
The structure of a test yaml file can take 2 different forms.
If on the top level the key title
and values
are found this is
considered a structured test. Otherwise it's just a value test.
A tests name is determined by the relative path within src/test/helm
.
Provides a sample value file. The test case is named like the file name.
The value file is fed into helm template
and helm lint
.
If both succeed with exit code 0 the test is considered successful.
Create a yaml structure like this:
# a simple title for logging purposes
title: "Test title"
# everything under values is provided in a separate value file to helm
values: ~
# by default value files are expected to work, set succeed to false
# for negative testing (asserts are ignored in this case)
succeed: true
# any assertions to be made on the rendered files
assert:
- file: "<rendered file name relative to chart root>"
test: "<name-of-test>"
# ... test specific properties, see below
- ...
If and only if title
and values
is present, a structured test is assumed.
Supported tests are:
eq
: propertypath
is JSON-PATH'd out of file and has to equal properyvalue
match
: propertypath
is JSON-PATH'd out of file as YAML and has to match the regular expression given in propertypattern
Note:
- loading a manifest yaml is done such that it's always a list of yaml documents whereby the outermost list has to be respected in the path (e.g.
$[*][data]
) file
is a relative path to the chart (e.g.templates/configmap.yaml
)pattern
is a java regular expression which has to match the complete extracted fragment, you might want to use embedded modifiers (e.g.(?ms)
)
- more tests
- provenance files
- certificate based authentication
- auto-detect at least local chart dependencies to improve up-to-date checks
- support for kube score
When the plugin has been created, there hasn't been an alternative. These days there are numerous alternatives:
-
https://github.com/unbroken-dome/gradle-helm-plugin
This one does it all but requires a locally installed helm
-
https://github.com/rmee/gradle-plugins/tree/master/helm
Comes integrated with a
kubectl
plugin and also allows remote release management. -
https://github.com/wfhartford/gradle-helm
Extensive multi chart support.
-
https://github.com/frantic777/helmplugin
Yet another one.
-
https://plugins.gradle.org/plugin/nl.surfsara.sda.buildplugin
That one is also listed on the gradle plugin portal.