From d0a6f56f04bbd516da25198e0cce6636984e4c4d Mon Sep 17 00:00:00 2001 From: Jorge Massih Date: Sat, 11 May 2024 13:19:54 -0400 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20add=20`helm=20package`=20hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-hooks.yaml | 9 ++- README.md | 1 + hooks/helmpackage.sh | 122 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 hooks/helmpackage.sh diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 76e78365..4bb1853f 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -81,7 +81,6 @@ description: golangci-lint is a Go linters aggregator entry: hooks/golangci-lint.sh language: script - language: script files: \.go$ require_serial: true @@ -105,6 +104,14 @@ files: \.((ya?ml)|(tpl))$ require_serial: true +- id: helm-package + name: helm-package + description: Run helm package to package helm charts. + entry: hooks/helmpackage.sh + language: script + files: \.((ya?ml)|(tpl))$ + require_serial: true + - id: markdown-link-check name: markdown-link-check description: Run markdown-link-check to check all the relative and absolute links in markdown docs. diff --git a/README.md b/README.md index f3691499..351f83b5 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ supported hooks are: * **golangci-lint**: Automatically run `golangci-lint` on all Golang code (`*.go` files). * **yapf**: Automatically run [`yapf`](https://github.com/google/yapf) on all python code (`*.py` files). * **helmlint** Automatically run [`helm lint`](https://helm.sh/docs/helm/helm_lint/) on your Helm chart files. [See caveats here](#helm-lint-caveats). +* **helm-package** Automatically run [`helm package`](https://helm.sh/docs/helm/helm_package/) to package your Helm charts. * **markdown-link-check** Automatically run [markdown-link-check](https://github.com/tcort/markdown-link-check) on markdown doc files. * **sentinel-fmt**: Automatically run `sentinel fmt` on all Sentinel code (`*.sentinel.*` files). diff --git a/hooks/helmpackage.sh b/hooks/helmpackage.sh new file mode 100644 index 00000000..2ef7be2b --- /dev/null +++ b/hooks/helmpackage.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash + +set -e + +# Run helm package on the root path. +# A typical helm chart directory structure looks as follows: +# +# root/ +# ├─ custom_chart1/ +# │ ├─ Chart.yaml +# │ ├─ ... +# ├─ index.yaml +# ├─ README.md +# ├─ charts/ +# │ ├─ custom_chart1-0.1.0.tgz +# │ ├─ custom_chart2-1.2.3.tgz +# ├─ custom_chart2/ +# │ ├─ Chart.yaml +# │ ├─ ... +# +# The `Chart.yaml` file is metadata that helm uses to index the chart, and is added to the release info. It includes things +# like `name`, `version`, and `maintainers`. +# The `charts` directory are subcharts / dependencies that are deployed with the chart. +# The `templates` directory is what contains the go templates to render the Kubernetes resource yaml. Also includes +# helper template definitions (suffix `.tpl`). +# +# Any time files in `templates` or `charts` changes, we should run `helm lint`. `helm lint` can only be run on the root +# path of a chart, so this pre-commit hook will take the changed files and resolve it to the helm chart path. The helm +# chart path is determined by a heuristic: it is the directory containing the `Chart.yaml` file. +# +# Note that pre-commit will only feed this the files that changed in the commit, so we can't do the filtering at the +# hook setting level (e.g `files: Chart.yaml` will not work if no changes are made in the Chart.yaml file). + +# OSX GUI apps do not pick up environment variables the same way as Terminal apps and there are no easy solutions, +# especially as Apple changes the GUI app behavior every release (see https://stackoverflow.com/q/135688/483528). As a +# workaround to allow GitHub Desktop to work, add this (hopefully harmless) setting here. +# Update the PATH environment variable to include the default installation path of helm. +export PATH=$PATH:/usr/local/bin + +# Get the absolute path of the current working directory to know when to stop traversing up the directory tree. +readonly cwd_abspath="$(realpath "$PWD")" + +# Function to check if an array contains a specific element. +# Usage: contains_element "value_to_find" "${array[@]}" +# Returns: 0 if found, 1 otherwise. +contains_element() { + local -r match="$1" + shift + for e in "$@"; do + if [[ "$e" == "$match" ]]; then + return 0 + fi + done + return 1 +} + +# Function to output debug information only when the PRECOMMIT_DEBUG environment variable is set. +# Outputs to stderr. +debug() { + if [[ ! -z $PRECOMMIT_DEBUG ]]; then + >&2 echo "$@" + fi +} + +# Function to recursively find the path of a Helm chart by traversing up from the file location until it finds a Chart.yaml. +# Usage: chart_path "path_of_changed_file" +# Returns: Path of the directory containing Chart.yaml or an empty string if not found. +chart_path() { + local -r changed_file="$1" + local -r changed_file_abspath="$(realpath "$changed_file")" + local -r changed_file_dir="$(dirname "$changed_file_abspath")" + + debug "Checking directory $changed_file_abspath and $changed_file_dir for Chart.yaml" + + if [[ "$changed_file_abspath" == "$cwd_abspath" ]]; then + debug "No chart path found" + echo "" + return 0 + fi + + if [[ "$(basename "$changed_file_abspath")" == "Chart.yaml" ]]; then + debug "Chart path found: $changed_file_dir" + echo "$changed_file_dir" + return 0 + fi + + if [[ -f "$changed_file_abspath/Chart.yaml" ]]; then + debug "Chart path found: $changed_file_abspath" + echo "$changed_file_abspath" + return 0 + fi + + if [[ -f "$changed_file_dir/Chart.yaml" ]]; then + debug "Chart path found: $changed_file_dir" + echo "$changed_file_dir" + return 0 + fi + + chart_path "$changed_file_dir" +} + +# Array to track which chart directories have already been packaged to avoid duplicate processing. +packaged_chart_paths=() + +# Main loop to process each file passed to the script. +for file in "$@"; do + debug "Checking $file" + file_chart_path=$(chart_path "$file") + debug "Resolved $file to chart path $file_chart_path" + + if [[ ! -z "$file_chart_path" ]] && ! contains_element "$file_chart_path" "${packaged_chart_paths[@]}"; then + # Package the chart and add its path to the list of packaged charts. + helm package "$file_chart_path" + packaged_chart_paths+=( "$file_chart_path" ) + debug "Packaged $file_chart_path" + fi +done + +# After all charts have been packaged, update the index for the repository. +# This assumes that the script is run from the repository root. +helm repo index $cwd_abspath +debug "Repository index updated." From cd205739ea6f339941c14b0e4b988eedd1c039d6 Mon Sep 17 00:00:00 2001 From: Jorge Massih Date: Sat, 11 May 2024 14:08:51 -0400 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=A9=B9=20make=20hook=20executable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hooks/helmpackage.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 hooks/helmpackage.sh diff --git a/hooks/helmpackage.sh b/hooks/helmpackage.sh old mode 100644 new mode 100755 From 7c118c41faae8eace2090de76b745b132bb1275f Mon Sep 17 00:00:00 2001 From: Jorge Massih Date: Sat, 11 May 2024 14:15:28 -0400 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=90=9B=20add=20charts=20directory=20t?= =?UTF-8?q?o=20command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hooks/helmpackage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hooks/helmpackage.sh b/hooks/helmpackage.sh index 2ef7be2b..05c374d7 100755 --- a/hooks/helmpackage.sh +++ b/hooks/helmpackage.sh @@ -110,7 +110,7 @@ for file in "$@"; do if [[ ! -z "$file_chart_path" ]] && ! contains_element "$file_chart_path" "${packaged_chart_paths[@]}"; then # Package the chart and add its path to the list of packaged charts. - helm package "$file_chart_path" + helm package "$file_chart_path" -d $cwd_abspath/charts packaged_chart_paths+=( "$file_chart_path" ) debug "Packaged $file_chart_path" fi From 194abb0db15dceed6ad408ed32fae75f8e203eca Mon Sep 17 00:00:00 2001 From: Jorge Massih Date: Sat, 11 May 2024 22:20:28 -0400 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=94=A7=20add=20proper=20exclusion=20f?= =?UTF-8?q?iles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-hooks.yaml | 5 ++++- hooks/helmpackage.sh | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 4bb1853f..4dc2f51e 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -109,7 +109,10 @@ description: Run helm package to package helm charts. entry: hooks/helmpackage.sh language: script - files: \.((ya?ml)|(tpl))$ + files: \.((yma?l)|(tpl))$ + types: + - "file" + exclude: ^index\.ya?ml$ require_serial: true - id: markdown-link-check diff --git a/hooks/helmpackage.sh b/hooks/helmpackage.sh index 05c374d7..6439ff4a 100755 --- a/hooks/helmpackage.sh +++ b/hooks/helmpackage.sh @@ -40,6 +40,8 @@ export PATH=$PATH:/usr/local/bin # Get the absolute path of the current working directory to know when to stop traversing up the directory tree. readonly cwd_abspath="$(realpath "$PWD")" +readonly charts_path="$cwd_abspath/charts" + # Function to check if an array contains a specific element. # Usage: contains_element "value_to_find" "${array[@]}" # Returns: 0 if found, 1 otherwise. @@ -110,7 +112,7 @@ for file in "$@"; do if [[ ! -z "$file_chart_path" ]] && ! contains_element "$file_chart_path" "${packaged_chart_paths[@]}"; then # Package the chart and add its path to the list of packaged charts. - helm package "$file_chart_path" -d $cwd_abspath/charts + helm package "$file_chart_path" -d $charts_path packaged_chart_paths+=( "$file_chart_path" ) debug "Packaged $file_chart_path" fi