Helm Chart Configuration

Each Java service packages its own Helm chart for Kubernetes deployment. Charts are embedded in the source repository under src/main/helm/ and built using the helm-maven-plugin.

Chart Directory Structure

src/main/helm/
├── Chart.yaml                      (1)
├── values.yaml                     (2)
└── templates/
    ├── config-map-application.yml  (3)
    └── ...                         (4)
1 Chart metadata — version and appVersion are overridden by the Maven plugin at build time
2 Default Helm values
3 Spring Boot application configuration rendered from Helm values
4 Additional Kubernetes resource templates (JHipster generates these)

Chart.yaml

The Chart.yaml contains placeholder versions that are overridden during build:

apiVersion: v2
name: membership-ui
description: Helm chart for the Membership UI.
type: application
version: 0.0.0    # Overridden by helm-maven-plugin
appVersion: 0.0.0 # Overridden by helm-maven-plugin

ConfigMap Template

The config-map-application.yml template renders Spring Boot configuration from Helm values. This is the key integration point between Helm and the application.

kind: ConfigMap
apiVersion: v1
metadata:
  name: {{ include "service-name.fullname" . }}
data:
  application.yaml: |-
    spring:
      datasource:
        url: {{ printf "jdbc:%s" .Values.config.db.url }}  (1)
        username: {{ .Values.config.db.username }}
1 Database URL uses printf "jdbc:%s" to prepend the JDBC prefix. ArgoCD manifests store URLs in mysql:// format (without jdbc: prefix).

Maven Plugin Configuration

The helm-maven-plugin is configured in the service POM:

<plugin>
    <groupId>io.kokuwa.maven</groupId>
    <artifactId>helm-maven-plugin</artifactId>
    <version>${helm-maven-plugin.version}</version>
    <configuration>
        <chartDirectory>${project.basedir}/src/main/helm</chartDirectory>
        <helmVersion>3.17.3</helmVersion>                          (1)
        <chartVersion>${project.version}-RELEASE</chartVersion>    (2)
        <appVersion>${project.version}</appVersion>
        <skipPushLogin>true</skipPushLogin>                        (3)
        <uploadRepoStable>
            <name>dockerhub-christhonie</name>
            <url>registry-1.docker.io/christhonie</url>
        </uploadRepoStable>
        <uploadRepoSnapshot>
            <name>dockerhub-christhonie</name>
            <url>registry-1.docker.io/christhonie</url>
        </uploadRepoSnapshot>
    </configuration>
</plugin>
1 Pinned to Helm 3.x — Helm 4 rejects registry URLs with paths, which the plugin passes to helm registry login
2 Chart version appends -RELEASE to the Maven version (e.g. 2.0.0-SNAPSHOT becomes 2.0.0-SNAPSHOT-RELEASE)
3 Login is handled via Helm CLI in CI; helm:registry-login is avoided due to a registry key bug (see below)

Version Convention

Maven Version Chart Version Image Tag

2.0.0-SNAPSHOT

2.0.0-SNAPSHOT-RELEASE

2.0.0-SNAPSHOT

2.3.9-SNAPSHOT

2.3.9-SNAPSHOT-RELEASE

2.3.9-SNAPSHOT

The -RELEASE suffix distinguishes chart artifacts from Docker image tags in the same OCI registry namespace.

Building Helm Charts

CI Build (GitHub Actions)

On every push to develop or main, the helm-build.yml reusable workflow runs. The chart is built on every push to keep it in lock-step with the Docker image.

The workflow first logs in using the Helm CLI:

echo "$DOCKER_PAT" | helm registry login registry-1.docker.io -u christhonie --password-stdin

Then runs the Maven Helm goals (without helm:registry-login):

mvn helm:init helm:package helm:push \
    --batch-mode --no-transfer-progress \
    -Pprod,webapp \
    -s /home/runner/.m2/docker/settings.xml
The helm:registry-login Maven goal is intentionally omitted in CI. It stores credentials under registry-1.docker.io/christhonie instead of registry-1.docker.io, causing 401 Unauthorized errors on push. The Helm CLI login stores credentials under the correct key.

The Helm push step uses continue-on-error: true to tolerate duplicate OCI tag pushes when SNAPSHOT versions are rebuilt.

Manual Build (Local)

To manually build and push a Helm chart from a local machine:

  1. Ensure ~/.m2/settings.xml has the Docker Hub credentials:

    <server>
        <id>dockerhub-christhonie</id>
        <username>christhonie</username>
        <password>YOUR_DOCKER_HUB_PAT</password>
    </server>
  2. Ensure ~/.m2/settings-security.xml exists (required by helm-maven-plugin 6.17.0):

    <settingsSecurity><master>placeholder</master></settingsSecurity>
  3. Run the Helm build:

    cd ~/dev/ems/<service-directory>
    mvn helm:init helm:registry-login helm:package helm:push -Pprod
  4. Verify the chart was published:

    helm pull oci://registry-1.docker.io/christhonie/<chart-name> \
        --version <project-version>-RELEASE

Prettier Warning

Prettier reformats Helm/Go template expressions {{ }} to { { } }, which breaks YAML parsing. Always add src/main/helm/templates/ to .prettierignore.
.prettierignore
src/main/helm/templates/