diff --git a/README.md b/README.md
index fb6ca1bf04f8824a9c82dc3ef4632cb02db79ee0..3acded2193ea9fa4a3581209e38b1ddd603ae7b8 100644
--- a/README.md
+++ b/README.md
@@ -407,7 +407,7 @@ This job publishes the packaged chart to a [chart repository](https://helm.sh/do
 | :lock: `HELM_PUBLISH_USER`          | Helm registry username                       | `$CI_REGISTRY_USER`     |
 | :lock: `HELM_PUBLISH_PASSWORD`      | Helm registry password                       | `$CI_REGISTRY_PASSWORD` |
 | `HELM_PUBLISH_URL`                  | The URL of the Helm repository to publish your Helm package.<br/>Supports both [chart repository](https://helm.sh/docs/topics/chart_repository/) or [OCI-based registry](https://helm.sh/docs/topics/registries/) (url must be prefixed with `oci://`) | `oci://$CI_REGISTRY/$CI_PROJECT_PATH/charts` ([GitLab's container registry](https://docs.gitlab.com/ee/user/packages/container_registry/)) |
-| `HELM_PUBLISH_ON`                   | Defines on which branch(es) the publish job shall be enabled (`prod` to enable on production branch only, `protected` to enable on protected references and `all` to enable on all Git references) | `prod`                  |
+| `HELM_PUBLISH_ON`                   | Defines on which Git reference(s) the publish job shall be enabled.<br/>`prod` to enable on production branch only, `protected` to enable on protected references, `all` to enable on all Git branches and `tag` on Git release tags (always auto, superseeds `HELM_PUBLISH_STRATEGY`) | `prod` |
 | `HELM_PUBLISH_STRATEGY`             | Defines the publish strategy. One of `manual` (i.e. _one-click_), `auto` or `none` (disabled). | `manual` |
 | `HELM_CM_PUSH_PLUGIN_VERSION`       | cm-push plugin version to install (only when using `push` method with a regular chart [repository](https://helm.sh/docs/topics/chart_repository/)) | _none_ (latest) |
 
diff --git a/kicker.json b/kicker.json
index c774fae22c5dc3d23e98ceeedf142bd09e5fc838..9465a6d4ee34ecfd59d7ec035b71671e55768283 100644
--- a/kicker.json
+++ b/kicker.json
@@ -218,10 +218,10 @@
         },
         {
           "name": "HELM_PUBLISH_ON",
-          "description": "Defines on which branch(es) the publish job shall be enabled",
+          "description": "Defines on which Git reference(s) the publish job shall be enabled\n\n`prod` to enable on production branch only, `protected` to enable on protected references, `all` to enable on all Git branches and `tag` on Git release tags (always auto, superseeds `HELM_PUBLISH_STRATEGY`)",
           "default": "prod",
           "type": "enum",
-          "values": ["prod", "protected", "all"]
+          "values": ["prod", "protected", "all", "tag"]
         },
         {
           "name": "HELM_PUBLISH_STRATEGY",
diff --git a/templates/gitlab-ci-helm.yml b/templates/gitlab-ci-helm.yml
index 28b0db672c4b201ef1957213a4b9190a8c272d3b..06ba3dcac30e2fe97f823d6f893b23e255e67889 100644
--- a/templates/gitlab-ci-helm.yml
+++ b/templates/gitlab-ci-helm.yml
@@ -131,6 +131,8 @@ variables:
   PROD_REF: '/^(master|main)$/'
   # default integration ref name (pattern)
   INTEG_REF: '/^develop$/'
+  # default release tag name (pattern)
+  RELEASE_REF: '/^v?[0-9]+\.[0-9]+\.[0-9]+$/'
 
 stages:
   - test
@@ -596,8 +598,14 @@ stages:
     # extract version from chart
     base_version=$(awk -F':' '/^version:/ {print $2}' "$HELM_CHART_DIR/Chart.yaml")
     base_version=${base_version// /}
-    # override version if semantic-release integration is enabled
-    if [[ "${SEMREL_INFO_ON}" ]] && [[ "${HELM_SEMREL_RELEASE_DISABLED}" != "true" ]]
+    # override version if:
+    # - on tag (release)
+    # - semantic-release integration is enabled & next version is defined
+    if [[ "${CI_COMMIT_TAG}" ]]
+    then
+      base_version="${CI_COMMIT_TAG}"
+      log_info "[release] use Git tag as version: \\e[33;1m${base_version}\\e[0m"
+    elif [[ "${SEMREL_INFO_ON}" ]] && [[ "${HELM_SEMREL_RELEASE_DISABLED}" != "true" ]]
     then
       if [[ -z "${SEMREL_INFO_NEXT_VERSION}" ]]
       then
@@ -610,14 +618,15 @@ stages:
     chart_name=$(awk -F':' '/^name:/ {print $2}' "$HELM_CHART_DIR/Chart.yaml")
     chart_name=${chart_name// /}
 
-    # also determine version label
-    prod_ref_expr=${PROD_REF#/}
-    prod_ref_expr=${prod_ref_expr%/}
-    if [[ "$CI_COMMIT_REF_NAME" =~ $prod_ref_expr ]]
+    # if on non-prod branch: also append branch slug as version label
+    if [[ -z "${CI_COMMIT_TAG}" ]]
     then
-      version_label=""
-    else
-      version_label="-$CI_COMMIT_REF_SLUG"
+      prod_ref_expr=${PROD_REF#/}
+      prod_ref_expr=${prod_ref_expr%/}
+      if [[ ! "$CI_COMMIT_REF_NAME" =~ $prod_ref_expr ]]
+      then
+        version_label="-$CI_COMMIT_REF_SLUG"
+      fi
     fi
 
     # helm package
@@ -628,7 +637,8 @@ stages:
     helm_package=$(ls -1 ./helm_packages/*.tgz 2>/dev/null || echo "")
     echo -e "helm_package_file=${helm_package}\\nhelm_package_version=${base_version}${version_label}\\nhelm_package_name=${chart_name}" > helm-package.env
 
-    if [[ "$HELM_PUBLISH_SNAPSHOT_ENABLED" == "true" ]]
+    # publish snapshot version if enabled (but not on tag pipeline)
+    if [[ "${HELM_PUBLISH_SNAPSHOT_ENABLED}" == "true" ]] && [[ -z "${CI_COMMIT_TAG}" ]]
     then
       log_info "snapshot enabled: also package and publish chart with version: \\e[33;1m${base_version}${version_label}-snapshot\\e[0m"
       mkdir -p /tmp/helm_snapshot
@@ -905,7 +915,7 @@ helm-publish:
   script:
     # skip if semantic-release integration enabled and no release is required
     - |
-      if [[ "${SEMREL_INFO_ON}" ]] && [[ "${HELM_SEMREL_RELEASE_DISABLED}" != "true" ]] && [[ -z "${SEMREL_INFO_NEXT_VERSION}" ]]
+      if [[ -z "${CI_COMMIT_TAG}" ]] && [[ "${SEMREL_INFO_ON}" ]] && [[ "${HELM_SEMREL_RELEASE_DISABLED}" != "true" ]] && [[ -z "${SEMREL_INFO_NEXT_VERSION}" ]]
       then
         log_warn "[semantic-release] no new version to release: skip"
         exit 0
@@ -914,6 +924,10 @@ helm-publish:
   rules:
     - if: '$HELM_PUBLISH_URL == null || $HELM_PUBLISH_URL == "" || $HELM_PUBLISH_METHOD == "disabled"'
       when: never
+    # auto on tag if matching release pattern
+    - if: '$HELM_PUBLISH_ON == "tag" && $CI_COMMIT_TAG =~ $RELEASE_REF'
+      exists:
+        - "**/Chart.yaml"
     - if: '$HELM_PUBLISH_ON == "prod" && $CI_COMMIT_REF_NAME !~ $PROD_REF'
       when: never
     - if: '$HELM_PUBLISH_ON == "protected" && $CI_COMMIT_REF_PROTECTED != "true"'