diff --git a/githooks/functions/libhelmlint.sh b/githooks/functions/libhelmlint.sh new file mode 100644 index 0000000000..72ecbb2637 --- /dev/null +++ b/githooks/functions/libhelmlint.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +run_helm_lint_chart() { + local -r chart_name="${1:?missing_chart_name}" + local -r chart_path="$(git rev-parse --show-toplevel)"/"$chart_name" + local test_failed=0 + + printf '\033[0;34m- Running helm lint %s\n\033[0m' "$chart_name" + if helm lint "$chart_path"; then + printf '\033[0;32m\U00002705 helm lint %s\n\n\033[0m' "$chart_name" + else + printf '\033[0;31m\U0001F6AB helm lint %s failed.\n\n\033[0m' "$chart_name" + test_failed=1 + fi + for values_file in "$chart_path"/values.yaml "$chart_path"/ci/*.yaml; do + if [[ ! -f "$values_file" ]];then + continue + fi + values_file_display=${values_file#$chart_path/} + + printf '\033\033[0;34m- Running helm template --values %s %s\n\033[0m' "$values_file_display" "$chart_name" + helm repo add bitnami https://charts.bitnami.com/bitnami >> /dev/null + helm dependency update "$chart_path" >> /dev/null + if helm template --values "$values_file" "$chart_path" >> /dev/null; then + printf '\033[0;32m\U00002705 helm template --values %s %s\n\n\033[0m' "$values_file_display" "$chart_name" + else + printf '\033[0;31m\U0001F6AB helm template --values %s %s failed.\n\n\033[0m' "$values_file_display" "$chart_path" + test_failed=1 + fi + done + + if [[ "$test_failed" = "1" ]]; then + false + else + true + fi +} diff --git a/githooks/functions/libkubeval.sh b/githooks/functions/libkubeval.sh new file mode 100644 index 0000000000..8c645c38b3 --- /dev/null +++ b/githooks/functions/libkubeval.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +check_kubeval() { + if ! command -v kubeval > /dev/null 2>&1; then + printf '\033[0;31m\U0001F6AB kubeval is not installed\033[0m' + printf ' Install it from https://github.com/instrumenta/kubeval/releases' + exit 1 + fi +} + +run_kubeval_chart() { + local -r chart_name="${1:?missing_chart_name}" + local -r chart_path="$(git rev-parse --show-toplevel)"/"$chart_name" + local test_failed=0 + for values_file in "$chart_path"/values.yaml "$chart_path"/ci/*.yaml; do + if [[ ! -f "$values_file" ]];then + continue + fi + values_file_display=${values_file#$chart_path/} + + printf '\033[0;34m- Running helm template --values %s %s | kubeval\n\033[0m' "$values_file_display" "$chart_name" + if helm template --values "$values_file" "$chart_path" | kubeval; then + printf '\033[0;32m\U00002705 helm template --values %s %s | kubeval\n\n\033[0m' "$values_file_display" "$chart_name" + else + printf '\033[0;31m\U0001F6AB helm template --values %s %s | kubeval failed. Push cancelled.\n\n\033[0m' "$values_file_display" "$chart_name" + test_failed=1 + fi + done + if [[ "$test_failed" = "1" ]]; then + false + else + true + fi +} diff --git a/githooks/functions/libyamllint.sh b/githooks/functions/libyamllint.sh new file mode 100644 index 0000000000..05dcc9bcb6 --- /dev/null +++ b/githooks/functions/libyamllint.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +render_and_yaml_lint() { + local -r chart_path="${1:?missing_chart}" + local -r path="${2:?missing_file}" + local -r values="${3:?missing_values}" + local -r repo_path="$(git rev-parse --show-toplevel)" + local -r display_chart_path=${chart_path#"$repo_path/"} + local -r display_values=${values#"$chart_path/"} + local -r lint_rules="{extends: default, rules: {line-length: disable, trailing-spaces: disable, truthy: enable, document-start: disable, empty-lines: {max-end: 2} }}" + printf '\033[0;34m- Running yamllint on %s/%s (values: %s)\n\033[0m' "$display_chart_path" "$path" "$display_values" + + if ! helm template --values "$values" "$chart_path" -x "$path" | yamllint -s -d "$lint_rules" -; then + printf '\033[0;31m\\U0001F6AB (helm template --values %s %s -x %s | yamllint -s -d "%s" -) failed\n\n\033[0m' "$display_values" "$display_chart_path" "$path" "$lint_rules" + false + else + printf '\033[0;32m\U00002705 %s/%s (values: %s)\n\n\033[0m' "$display_chart_path" "$path" "$display_values" + true + fi +} + +yaml_lint_file() { + local -r path="${1:?missing_file}" + local -r lint_rules="{extends: default, rules: {line-length: disable, trailing-spaces: disable, truthy: enable, document-start: disable, empty-lines: {max-end: 2}}}" + local -r repo_path="$(git rev-parse --show-toplevel)" + local -r display_path=${path#"$repo_path/"} + printf '\033[0;34m- Running yamllint on %s\n' "$display_path" + if ! yamllint -s -d "$lint_rules" "$path"; then + printf '\033[0;31m\U0001F6AB yamllint -s -d "%s" %s failed\n\n\033[0m' "$lint_rules" "$display_path" + false + else + printf '\033[0;32m\U00002705 %s\n\n\033[0m' "$display_path" + true + fi +} + +check_yaml_lint() { + if ! command -v yamllint > /dev/null 2>&1; then + printf '\033[0;31m\U0001F6AB yamllint is not installed\033[0m' + printf ' Installation for Linux' + printf ' pip install --user yamllint' + printf ' Installation for Mac OS' + printf ' brew install yamllint' + exit 1 + fi +} + +run_yaml_lint_chart() { + local -r chart_name="${1:?missing_chart_name}" + local -r chart_path="$(git rev-parse --show-toplevel)"/"$chart_name" + local test_failed=0 + for yaml_file in "$chart_path"/values.yaml "$chart_path"/values-production.yaml "$chart_path"/requirements.yaml "$chart_path"/Chart.yaml "$chart_path"/ci/*; do + if [[ -f "$yaml_file" ]] && ! yaml_lint_file "$yaml_file"; then + test_failed=1 + fi + done + + for values_file in "$chart_path"/values.yaml "$chart_path"/ci/*.yaml; do + if [[ ! -f "$values_file" ]];then + continue + fi + for yaml_file in "$chart_path"/templates/*.yaml; do + path_basename=templates/$(basename "$yaml_file") + if ! render_and_yaml_lint "$chart_path" "$path_basename" "$values_file"; then + test_failed=1 + fi + done + done + + if [[ "$test_failed" = "1" ]]; then + false + else + true + fi +} diff --git a/githooks/pre-push/helm-lint b/githooks/pre-push/helm-lint index 0e5b93ba51..f586297589 100755 --- a/githooks/pre-push/helm-lint +++ b/githooks/pre-push/helm-lint @@ -1,5 +1,7 @@ #!/bin/bash +. ../functions/libhelmlint.sh + readonly current_branch="$(git rev-parse --abbrev-ref HEAD)" readonly origin_commit="$(git rev-parse --short "$(git merge-base master "$current_branch")")" readonly files_to_push="$(git diff --name-only "$origin_commit")" @@ -10,30 +12,13 @@ for chart_name in $( cut -d'/' -f1,2 <<< "$files_to_push" | uniq ); do if [[ $chart_name = bitnami/* ]]; then printf '\033[01;33mValidating %s with helm lint:\n\033[0m' "$chart_name" chart_path="$(git rev-parse --show-toplevel)"/"$chart_name" - printf '\033[0;34m- Running helm lint %s\n\033[0m' "$chart_name" - if helm lint "$chart_path"; then - printf '\033[0;32m\U00002705 helm lint %s\n\n\033[0m' "$chart_name" - else - printf '\033[0;31m\U0001F6AB helm lint %s failed. Push cancelled.\n\n\033[0m' "$chart_name" - failed=1 - fi - for values_file in "$chart_path"/values.yaml "$chart_path"/ci/*.yaml; do - if [[ ! -f "$values_file" ]];then - continue - fi - values_file_display=${values_file#$chart_path/} - - printf '\033\033[0;34m- Running helm template --values %s %s\n\033[0m' "$values_file_display" "$chart_name" - helm repo add bitnami https://charts.bitnami.com/bitnami >> /dev/null - helm dependency update "$chart_path" >> /dev/null - if helm template --values "$values_file" "$chart_path" >> /dev/null; then - printf '\033[0;32m\U00002705 helm template --values %s %s\n\n\033[0m' "$values_file_display" "$chart_name" - else - printf '\033[0;31m\U0001F6AB helm template --values %s %s failed. Push cancelled.\n\n\033[0m' "$values_file_display" "$chart_path" - failed=1 - fi - done fi done +if [[ "$failed" = "1" ]]; then + printf '\033[0;31m\U0001F6AB Helm lint failed. Not pushing\n\n\033[0m' +else + printf '\033[0;32m\U00002705 Helm lint succeeded\n\n\033[0m' +fi + exit $failed diff --git a/githooks/pre-push/kubeval b/githooks/pre-push/kubeval index f6c5d47d1d..140c8b930b 100755 --- a/githooks/pre-push/kubeval +++ b/githooks/pre-push/kubeval @@ -1,39 +1,27 @@ #!/bin/bash +. ../functions/libkubeval.sh + readonly current_branch="$(git rev-parse --abbrev-ref HEAD)" readonly origin_commit="$(git rev-parse --short "$(git merge-base master "$current_branch")")" readonly files_to_push="$(git diff --name-only "$origin_commit")" failed=0 -check_kubeval() { - if ! command -v kubeval > /dev/null 2>&1; then - printf '\033[0;31m\U0001F6AB kubeval is not installed\033[0m' - printf ' Install it from https://github.com/instrumenta/kubeval/releases' - exit 1 - fi -} - for chart_name in $( cut -d'/' -f1,2 <<< "$files_to_push" | uniq ); do check_kubeval # Avoid running 'kubeval' when modified dirs are not charts if [[ $chart_name = bitnami/* ]]; then printf '\033[01;33mValidating %s with kubeval:\n\033[0m' "$chart_name" - chart_path="$(git rev-parse --show-toplevel)"/"$chart_name" - for values_file in "$chart_path"/values.yaml "$chart_path"/ci/*.yaml; do - if [[ ! -f "$values_file" ]];then - continue - fi - values_file_display=${values_file#$chart_path/} - - printf '\033[0;34m- Running helm template --values %s %s | kubeval\n\033[0m' "$values_file_display" "$chart_name" - if helm template --values "$values_file" "$chart_path" | kubeval; then - printf '\033[0;32m\U00002705 helm template --values %s %s | kubeval\n\n\033[0m' "$values_file_display" "$chart_name" - else - printf '\033[0;31m\U0001F6AB helm template --values %s %s | kubeval failed. Push cancelled.\n\n\033[0m' "$values_file_display" "$chart_name" - failed=1 - fi - done + if ! run_kubeval_chart "$chart_name"; then + failed=1 + fi fi done +if [[ "$failed" = "1" ]]; then + printf '\033[0;31m\U0001F6AB Kubeval failed. Not pushing\n\n\033[0m' +else + printf '\033[0;32m\U00002705 Kubeval succeeded\n\n\033[0m' +fi + exit $failed diff --git a/githooks/pre-push/yaml-lint b/githooks/pre-push/yaml-lint index e0a56d554f..07781c4f87 100755 --- a/githooks/pre-push/yaml-lint +++ b/githooks/pre-push/yaml-lint @@ -1,79 +1,20 @@ #!/bin/bash +. ../functions/libkubeval.sh + readonly current_branch="$(git rev-parse --abbrev-ref HEAD)" readonly origin_commit="$(git rev-parse --short "$(git merge-base master "$current_branch")")" readonly files_to_push="$(git diff --name-only "$origin_commit")" -readonly repo_path="$(git rev-parse --show-toplevel)" - failed=0 -render_and_yaml_lint() { - local -r chart_path="${1:?missing_chart}" - local -r path="${2:?missing_file}" - local -r values="${3:?missing_values}" - local -r display_chart_path=${1#"$repo_path/"} - local -r display_values=${3#"$chart_path/"} - local -r lint_rules="{extends: default, rules: {line-length: disable, trailing-spaces: disable, truthy: enable, document-start: disable, empty-lines: {max-end: 2} }}" - printf '\033[0;34m- Running yamllint on %s/%s (values: %s)\n\033[0m' "$display_chart_path" "$path" "$display_values" - - if ! helm template --values "$values" "$chart_path" -x "$path" | yamllint -s -d "$lint_rules" -; then - printf '\033[0;31m\\U0001F6AB (helm template --values %s %s -x %s | yamllint -s -d "%s" -) failed\n\n\033[0m' "$display_values" "$display_chart_path" "$path" "$lint_rules" - false - else - printf '\033[0;32m\U00002705 %s/%s (values: %s)\n\n\033[0m' "$display_chart_path" "$path" "$display_values" - true - fi -} - -yaml_lint_file() { - local -r path="${1:?missing_file}" - local -r lint_rules="{extends: default, rules: {line-length: disable, trailing-spaces: disable, truthy: enable, document-start: disable, empty-lines: {max-end: 2}}}" - local -r display_path=${1#"$repo_path/"} - printf '\033[0;34m- Running yamllint on %s\n' "$display_path" - if ! yamllint -s -d "$lint_rules" "$path"; then - printf '\033[0;31m\U0001F6AB yamllint -s -d "%s" %s failed\n\n\033[0m' "$lint_rules" "$display_path" - false - else - printf '\033[0;32m\U00002705 %s\n\n\033[0m' "$display_path" - true - fi -} - -check_yaml_lint() { - if ! command -v yamllint > /dev/null 2>&1; then - printf '\033[0;31m\U0001F6AB yamllint is not installed\033[0m' - printf ' Installation for Linux' - printf ' pip install --user yamllint' - printf ' Installation for Mac OS' - printf ' brew install yamllint' - exit 1 - fi -} - for chart_name in $( cut -d'/' -f1,2 <<< "$files_to_push" | uniq ); do check_yaml_lint # Avoid running 'yamllint' when modified dirs are not charts if [[ $chart_name = bitnami/* ]]; then printf '\033[01;33mLinting yaml of %s:\n\033[0m' "$chart_name" - chart_path="$repo_path"/"$chart_name" - - for yaml_file in "$chart_path"/values.yaml "$chart_path"/values-production.yaml "$chart_path"/requirements.yaml "$chart_path"/Chart.yaml "$chart_path"/ci/*; do - if [[ -f "$yaml_file" ]] && ! yaml_lint_file "$yaml_file"; then - failed=1 - fi - done - - for values_file in "$chart_path"/values.yaml "$chart_path"/ci/*.yaml; do - if [[ ! -f "$values_file" ]];then - continue - fi - for yaml_file in "$chart_path"/templates/*.yaml; do - path_basename=templates/$(basename "$yaml_file") - if ! render_and_yaml_lint "$chart_path" "$path_basename" "$values_file"; then - failed=1 - fi - done - done + if ! run_yaml_lint_chart "$chart_name"; then + failed=1 + fi fi done