Skip to content
Snippets Groups Projects
Commit 676c41cb authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

feat: support various publish methods (push, post, put, custom) with auto detection

BREAKING CHANGE: default publish URL uses GitLab registry
parent 6d7bc432
No related branches found
No related tags found
No related merge requests found
...@@ -311,14 +311,49 @@ Note: You can disable the `semantic-release` integration described herebefore th ...@@ -311,14 +311,49 @@ Note: You can disable the `semantic-release` integration described herebefore th
### `helm-publish` job ### `helm-publish` job
This job publishes the packaged chart to a release repository or registry. It uses the following variables: This job publishes the packaged chart to a [chart repository](https://helm.sh/docs/topics/chart_repository/) or [OCI-based registry](https://helm.sh/docs/topics/registries/). It uses the following variables:
| Name | description | default value | | Name | description | default value |
| ----------------------------------- | --------------------------------------------- | --------------------------------- | | ----------------------------------- | --------------------------------------------- | --------------------------------- |
| `HELM_PUBLISH_METHOD` | HTTP method to use to push the package | `POST` | | `HELM_PUBLISH_METHOD` | Method to use to publish the packaged chart (one of `auto`, `push`, `post`, `put`, `custom`, `disabled`) | `auto` |
| :lock: `HELM_PUBLISH_USER` | Helm registry username | `$CI_REGISTRY_USER` | | :lock: `HELM_PUBLISH_USER` | Helm registry username | `$CI_REGISTRY_USER` |
| :lock: `HELM_PUBLISH_PASSWORD` | Helm registry password | `$CI_REGISTRY_PASSWORD` | | :lock: `HELM_PUBLISH_PASSWORD` | Helm registry password | `$CI_REGISTRY_PASSWORD` |
| `HELM_PUBLISH_URL` | The URL of the Helm repository to publish your Helm package | `${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/api/release/charts` ([Helm chart registry for GitLab](https://docs.gitlab.com/ee/user/packages/helm_repository/#publish-a-package) on _release_ channel) | | `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_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) |
#### Supported publish methods
The Helm publish supports several methods, configurable with the `$HELM_PUBLISH_URL` variable:
| Value | description |
| --------------- | --------------------------------------------- |
|`auto` (default) | tries to auto-detect the most appropriate method |
|`disabled` | disables the `helm-publish` job |
|`push` | if publishing to an [OCI-based registry](https://helm.sh/docs/topics/registries/), publishes with [helm push](https://helm.sh/docs/helm/helm_push/) command; else uses the [cm-push plugin](https://github.com/chartmuseum/helm-push) |
|`post` | publishes the package using http `POST` method (compatible with [GitLab packages repository](https://docs.gitlab.com/ee/user/packages/helm_repository/)) |
|`put` | publishes the package using http `PUT` method |
|`custom` | forces the use of a [custom publish script](#custom-publish-script) |
> :information_source: The default configuration will use [GitLab's container registry](https://docs.gitlab.com/ee/user/packages/container_registry/) to publish your charts
>
> If you wish to use [GitLab's Helm package repository](https://docs.gitlab.com/ee/user/packages/helm_repository/) instead, simply override:
>
> ```yaml
> variables:
> # use channel 'release' (can be changed)
> HELM_PUBLISH_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/release"
> ```
>
> and leave default `$HELM_PUBLISH_USER`/`$HELM_PUBLISH_PASSWORD` values.
#### Custom publish script
If supported methods don't fit your needs, you may provide a `helm-publish.sh` script (with execution permissions) in your `$HELM_SCRIPTS_DIR` directory to implement the required publish method.
This script may use the following variables:
* `$helm_package`: the packaged chart to publish,
* `$HELM_PUBLISH_USER`, `$HELM_PUBLISH_PASSWORD` and `$HELM_PUBLISH_URL` (see above).
### `helm-test` job ### `helm-test` job
...@@ -327,7 +362,7 @@ You are welcome to nest your test suite under a `tests/` directory like `$HELM_C ...@@ -327,7 +362,7 @@ You are welcome to nest your test suite under a `tests/` directory like `$HELM_C
It is **disabled by default** and can be enabled by setting the ``HELM_TEST_ENABLED`` variable (see below). It is **disabled by default** and can be enabled by setting the ``HELM_TEST_ENABLED`` variable (see below).
It uses the following variables: It uses the following variables:
| Name | description | default value | | Name | description | default value |
| --------------------- | ---------------------------------------- | ----------------- | | --------------------- | ---------------------------------------- | ----------------- |
......
...@@ -178,12 +178,19 @@ ...@@ -178,12 +178,19 @@
{ {
"id": "publish", "id": "publish",
"name": "Publish your chart", "name": "Publish your chart",
"description": "Publish your Helm chart", "description": "Publishes the chart to a [Helm repository](https://helm.sh/docs/topics/chart_repository/) or [OCI-based registry](https://helm.sh/docs/topics/registries/)",
"variables": [ "variables": [
{ {
"name": "HELM_PUBLISH_URL", "name": "HELM_PUBLISH_URL",
"description": "The URL of the Helm repository to publish your Helm package", "description": "The URL of the Helm repository to publish your Helm package",
"default": "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/api/release/charts", "default": "oci://$CI_REGISTRY/$CI_PROJECT_PATH/charts"
},
{
"name": "HELM_PUBLISH_METHOD",
"description": "HTTP method to use to push the package",
"default": "auto",
"type": "enum",
"values": ["auto", "push", "post", "put", "custom", "disabled"],
"advanced": true "advanced": true
}, },
{ {
...@@ -199,9 +206,8 @@ ...@@ -199,9 +206,8 @@
"secret": true "secret": true
}, },
{ {
"name": "HELM_PUBLISH_METHOD", "name": "HELM_CM_PUSH_PLUGIN_VERSION",
"description": "HTTP method to use to push the package", "description": "cm-push plugin version to install (only when using `push` method with a regular chart [repository](https://helm.sh/docs/topics/chart_repository/)",
"default": "POST",
"advanced": true "advanced": true
} }
] ]
......
...@@ -58,8 +58,12 @@ variables: ...@@ -58,8 +58,12 @@ variables:
HELM_CHART_DIR: "." HELM_CHART_DIR: "."
HELM_SCRIPTS_DIR: "." HELM_SCRIPTS_DIR: "."
HELM_PACKAGE_ARGS: "package --dependency-update" HELM_PACKAGE_ARGS: "package --dependency-update"
HELM_PUBLISH_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/api/release/charts" # to GitLab's container registry (OCI-compliant)
HELM_PUBLISH_METHOD: "POST" HELM_PUBLISH_URL: "oci://$CI_REGISTRY/$CI_PROJECT_PATH/charts"
# to GitLab's packages repository
# HELM_PUBLISH_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/release"
# HELM_PUBLISH_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/release"
HELM_PUBLISH_METHOD: "auto"
HELM_REPOS: "stable@https://charts.helm.sh/stable bitnami@https://charts.bitnami.com/bitnami" HELM_REPOS: "stable@https://charts.helm.sh/stable bitnami@https://charts.bitnami.com/bitnami"
...@@ -542,12 +546,102 @@ stages: ...@@ -542,12 +546,102 @@ stages:
helm ${TRACE+--debug} $helm_opts $HELM_TEST_ARGS $environment_name helm ${TRACE+--debug} $helm_opts $HELM_TEST_ARGS $environment_name
} }
function maybe_install_curl() { function helm_package() {
if ! command -v curl > /dev/null # semantic-release integration
if [[ "${SEMREL_INFO_ON}" && "${DOCKER_SEMREL_RELEASE_DISABLED}" != "true" ]]
then then
log_info "--- installing curl (required to publish Helm charts)..." if [[ -z "${SEMREL_INFO_NEXT_VERSION}" ]]
apk add --no-cache curl then
log_warn "[semantic-release] no new version to release: skip"
exit 0
else
log_info "[semantic-release] use computed next version: \\e[1;94m${SEMREL_INFO_NEXT_VERSION}\\e[0m"
helm_version_opts="--app-version ${SEMREL_INFO_NEXT_VERSION} --version ${SEMREL_INFO_NEXT_VERSION}"
fi
fi fi
add_helm_repositories
helm_opts=$(get_helm_config_opt)
# helm package
# shellcheck disable=SC2086
helm ${TRACE+--debug} $helm_opts $HELM_PACKAGE_ARGS $helm_version_opts $HELM_CHART_DIR --destination helm_packages
}
function helm_publish() {
helm_opts=$(get_helm_config_opt)
helm_package=$(ls -1 ./helm_packages/*.tgz 2>/dev/null || echo "")
if [[ -z "$helm_package" ]]; then
log_error "No package found to deploy"
exit 1
fi
helm_package_name=$(basename "$helm_package")
log_info "--- Publishing Helm package ${helm_package_name} to: ${HELM_PUBLISH_URL}..."
# method to lowercase
HELM_PUBLISH_METHOD=$(echo "$HELM_PUBLISH_METHOD" | tr '[:upper:]' '[:lower:]')
# auto-detect method
if [[ "$HELM_PUBLISH_METHOD" == "auto" ]]
then
log_info "--- trying to auto detect publish method..."
pubscript="$HELM_SCRIPTS_DIR/helm-publish.sh"
if [[ -f "$pubscript" ]]
then
log_info "--- ... custom publish script (\\e[33;1m${postscript}\\e[0m) found: will use"
HELM_PUBLISH_METHOD=custom
elif [[ "$HELM_PUBLISH_URL" =~ oci://.* ]]
then
log_info "--- ... publish url looks like an OCI registry: will use helm push"
HELM_PUBLISH_METHOD=push
else
log_info "--- ... publish url looks like a Chart repository: will use push method (uses cm-push plugin)"
log_info "--- ... if auto-selected method is not suited, override with \$HELM_PUBLISH_METHOD or provide a custom publish script"
HELM_PUBLISH_METHOD=push
fi
fi
username="${HELM_PUBLISH_USER:-$CI_REGISTRY_USER}"
password="${HELM_PUBLISH_PASSWORD:-$CI_REGISTRY_PASSWORD}"
case "$HELM_PUBLISH_METHOD" in
push)
if [[ "$HELM_PUBLISH_URL" =~ oci://.* ]]
then
registry_host=$(echo "$HELM_PUBLISH_URL" | awk -F[/:] '{print $4}')
echo "$password" | helm registry login "$registry_host" --username "$username" --password-stdin
# enable OCI support prior to v3.8.0
export HELM_EXPERIMENTAL_OCI=1
helm ${TRACE+--debug} $helm_opts push "$helm_package" "$HELM_PUBLISH_URL"
else
log_info "Installing cm-push plugin (version ${HELM_CM_PUSH_PLUGIN_VERSION:-latest})..."
# shellcheck disable=SC2086
helm $helm_opts plugin install ${HELM_CM_PUSH_PLUGIN_VERSION:+--version "$HELM_CM_PUSH_PLUGIN_VERSION"} https://github.com/chartmuseum/helm-push || true
# shellcheck disable=SC2086
helm $helm_opts cm-push --username "$username" --password "$password" "$helm_package" "$HELM_PUBLISH_URL"
fi
;;
post)
if ! command -v curl > /dev/null
then
log_info "--- installing curl (required to publish Helm charts)..."
apk add --no-cache curl
fi
curl --fail --request POST --form "chart=@$helm_package" --user "$username:$password" "$HELM_PUBLISH_URL"
;;
put)
wget -v --method=PUT --user="$username" --password="$password" --body-file="$helm_package" "$HELM_PUBLISH_URL/$helm_package_name" -O -
;;
custom)
pubscript="$HELM_SCRIPTS_DIR/helm-publish.sh"
log_info "--- run custom publish script (\\e[33;1m${pubscript}\\e[0m)"
exec_hook "$pubscript"
;;
*)
log_error "Unsupported publish method: $HELM_PUBLISH_METHOD"
exit 1
;;
esac
} }
unscope_variables unscope_variables
...@@ -767,13 +861,7 @@ helm-package: ...@@ -767,13 +861,7 @@ helm-package:
- install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}" - install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"
- add_helm_repositories - add_helm_repositories
script: script:
- | - helm_package
if [[ "$SEMREL_INFO_ON" ]] && [[ "$SEMREL_INFO_NEXT_VERSION" ]] && [[ "$HELM_SEMREL_RELEASE_DISABLED" != "true" ]]
then
log_info "semantic-release info is activated, using computed next version for release: \\e[1;94m${SEMREL_INFO_NEXT_VERSION}\\e[0m"
helm_version_opts="--version ${SEMREL_INFO_NEXT_VERSION}"
fi
- helm $HELM_PACKAGE_ARGS ${TRACE+--debug} $helm_version_opts $HELM_CHART_DIR --destination helm_packages
rules: rules:
- exists: - exists:
- "**/Chart.yaml" - "**/Chart.yaml"
...@@ -790,26 +878,9 @@ helm-publish: ...@@ -790,26 +878,9 @@ helm-publish:
extends: .helm-base extends: .helm-base
stage: publish stage: publish
script: script:
- | - helm_publish
package=$(ls -1 ./helm_packages/*.tgz 2>/dev/null || echo "")
if [ -n "$HELM_PUBLISH_URL" ] && [ -n "${package}" ]
then
package_file=$(basename ${package})
log_info "publishing helm chart ${package_file} to release url: ${HELM_PUBLISH_URL}"
username="${HELM_PUBLISH_USER:-$CI_REGISTRY_USER}"
password="${HELM_PUBLISH_PASSWORD:-$CI_REGISTRY_PASSWORD}"
if [[ "$HELM_PUBLISH_METHOD" == "POST" ]]
then
maybe_install_curl
curl --fail --request POST --form "chart=@${package}" --user "$username:$password" $HELM_PUBLISH_URL
else
wget -v --method=PUT --user="$username" --password="$password" --body-file="${package}" "$HELM_PUBLISH_URL/${package_file}" -O -
fi
else
log_error "No Chart to deploy! url is: $HELM_PUBLISH_URL, and package found is: ${package}"
fi
rules: rules:
- if: $HELM_PUBLISH_URL == null || $CI_COMMIT_REF_NAME !~ $PROD_REF - if: '$HELM_PUBLISH_URL == null || $HELM_PUBLISH_URL == "" || $CI_COMMIT_REF_NAME !~ $PROD_REF || $HELM_PUBLISH_METHOD == "disabled"'
when: never when: never
- if: '$AUTODEPLOY_TO_PROD == "true"' - if: '$AUTODEPLOY_TO_PROD == "true"'
# else: manual + blocking # else: manual + blocking
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment