diff --git a/.github/workflows/release-helm.yaml b/.github/workflows/release-helm.yaml new file mode 100644 index 00000000..cb4360df --- /dev/null +++ b/.github/workflows/release-helm.yaml @@ -0,0 +1,80 @@ +name: Release Helm Chart + +on: + push: + tags: + - '*' + workflow_dispatch: + +env: + HELM_REGISTRY_USER: ${{ github.actor }} + HELM_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }} + HELM_REGISTRY_ORG: ${{ github.repository_owner }} + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +jobs: + release: + name: Release Helm Chart + if: github.repository == 'containers/kubernetes-mcp-server' + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Install Helm + uses: azure/setup-helm@v4 + with: + version: '3.19.2' + + - name: Extract versions + id: versions + run: | + CHART_VERSION=$(make helm-print-chart-version) + echo "chart_version=$CHART_VERSION" >> $GITHUB_OUTPUT + echo "Chart version: $CHART_VERSION" + + APP_VERSION=$(make print-git-tag-version) + echo "app_version=$APP_VERSION" >> $GITHUB_OUTPUT + echo "App version: $APP_VERSION" + + HELM_REGISTRY=$(make helm-print-registry) + echo "helm_registry=$HELM_REGISTRY" >> $GITHUB_OUTPUT + echo "Helm registry: $HELM_REGISTRY" + + CHART_NAME=$(make helm-print-chart-name) + echo "chart_name=$CHART_NAME" >> $GITHUB_OUTPUT + echo "Chart name: $CHART_NAME" + + - name: Validate with kubeconform + run: make helm-validate + + - name: Login to Helm registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ${{ steps.versions.outputs.helm_registry }} -u ${{ github.actor }} --password-stdin + + - name: Package Helm chart and push chart to OCI registry + run: make helm-push + + - name: Verify chart installation + run: make helm-verify + + - name: Generate release summary + run: | + echo "## Helm Chart Release Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- **Chart Name:** ${{ steps.versions.outputs.chart_name }}" >> $GITHUB_STEP_SUMMARY + echo "- **Chart Version:** ${{ steps.versions.outputs.chart_version }}" >> $GITHUB_STEP_SUMMARY + echo "- **App Version:** ${{ steps.versions.outputs.app_version }}" >> $GITHUB_STEP_SUMMARY + echo "- **Registry:** ${{ steps.versions.outputs.helm_registry }}/${{ github.repository_owner }}/charts" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Installation Command" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY + echo "helm install ${{ steps.versions.outputs.chart_name }} oci://${{ steps.versions.outputs.helm_registry }}/${{ github.repository_owner }}/charts/${{ steps.versions.outputs.chart_name }} --set ingress.host= --version ${{ steps.versions.outputs.chart_version }} --create-namespace --namespace mcp-system" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY diff --git a/Makefile b/Makefile index e0015dda..82ee91b5 100644 --- a/Makefile +++ b/Makefile @@ -70,8 +70,9 @@ format: ## Format the code tidy: ## Tidy up the go modules go mod tidy +# Download and install golangci-lint if not already installed .PHONY: golangci-lint -golangci-lint: ## Download and install golangci-lint if not already installed +golangci-lint: @[ -f $(GOLANGCI_LINT) ] || { \ set -e ;\ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(shell dirname $(GOLANGCI_LINT)) $(GOLANGCI_LINT_VERSION) ;\ @@ -122,5 +123,9 @@ local-env-setup: ## Setup complete local development environment with Kind clust local-env-teardown: ## Tear down the local Kind cluster $(MAKE) kind-delete-cluster +.PHONY: print-git-tag-version +print-git-tag-version: ## Print the GIT_TAG_VERSION + @echo $(GIT_TAG_VERSION) + # Include build configuration files -include build/*.mk diff --git a/build/helm.mk b/build/helm.mk new file mode 100644 index 00000000..9aa746db --- /dev/null +++ b/build/helm.mk @@ -0,0 +1,81 @@ +##@ Helm Chart build targets + +HELM_CHART_DIR = ./charts/kubernetes-mcp-server +HELM_CHART_VERSION = $(shell grep '^version:' $(HELM_CHART_DIR)/Chart.yaml | awk '{print $$2}') +HELM_PACKAGE_DIR = ./_output/helm-packages +HELM_REGISTRY ?= ghcr.io +HELM_REGISTRY_ORG ?= containers +HELM_CHART_NAME = kubernetes-mcp-server + +KUBECONFORM = $(shell pwd)/_output/tools/bin/kubeconform +KUBECONFORM_VERSION ?= latest + +CLEAN_TARGETS += $(HELM_PACKAGE_DIR) + +.PHONY: helm-lint +helm-lint: ## Lint the Helm chart + helm lint $(HELM_CHART_DIR) + +.PHONY: helm-template +helm-template: ## Render Helm chart templates (dry run) + helm template test-release $(HELM_CHART_DIR) --set ingress.host=localhost --debug + +# Download and install kubeconform if not already installed +.PHONY: kubeconform +kubeconform: + @[ -f $(KUBECONFORM) ] || { \ + set -e ;\ + echo "Installing kubeconform to $(KUBECONFORM)..." ;\ + mkdir -p $(shell dirname $(KUBECONFORM)) ;\ + TMPDIR=$$(mktemp -d) ;\ + curl -L https://github.com/yannh/kubeconform/releases/$(KUBECONFORM_VERSION)/download/kubeconform-$(shell uname -s | tr '[:upper:]' '[:lower:]')-$(shell uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz | tar xz -C $$TMPDIR ;\ + mv $$TMPDIR/kubeconform $(KUBECONFORM) ;\ + rm -rf $$TMPDIR ;\ + } + +.PHONY: helm-validate +helm-validate: kubeconform ## Validate Helm chart manifests with kubeconform + helm template test-release $(HELM_CHART_DIR) --set ingress.host=localhost | $(KUBECONFORM) -strict -summary -ignore-missing-schemas + +.PHONY: helm-package +helm-package: helm-lint helm-template ## Package the Helm chart + @mkdir -p $(HELM_PACKAGE_DIR) + @echo "Updating appVersion to $(GIT_TAG_VERSION)..." + @sed -i.bak "s/appVersion: .*/appVersion: \"$(GIT_TAG_VERSION)\"/" $(HELM_CHART_DIR)/Chart.yaml + @echo "Updated Chart.yaml:" + @cat $(HELM_CHART_DIR)/Chart.yaml + helm package $(HELM_CHART_DIR) --destination $(HELM_PACKAGE_DIR) + @mv $(HELM_CHART_DIR)/Chart.yaml.bak $(HELM_CHART_DIR)/Chart.yaml + +.PHONY: helm-push +helm-push: helm-package ## Push Helm chart to OCI registry (assumes helm registry login has been performed) + @chart_package=$$(ls $(HELM_PACKAGE_DIR)/$(HELM_CHART_NAME)-*.tgz 2>/dev/null | head -n 1); \ + if [ -z "$$chart_package" ]; then echo "Error: No chart package found in $(HELM_PACKAGE_DIR)"; exit 1; fi; \ + echo "Pushing chart package: $$chart_package"; \ + helm push "$$chart_package" oci://$(HELM_REGISTRY)/$(HELM_REGISTRY_ORG)/charts + + +.PHONY: helm-verify +helm-verify: ## Verify chart installation from OCI registry + @echo "Testing chart template rendering from OCI registry..." + helm template test-install oci://$(HELM_REGISTRY)/$(HELM_REGISTRY_ORG)/charts/$(HELM_CHART_NAME) \ + --set ingress.host=localhost --version $(HELM_CHART_VERSION) --debug + +.PHONY: helm-publish +helm-publish: helm-package helm-push helm-verify ## Package, push, and verify Helm chart release + @echo "Helm chart $(HELM_CHART_NAME) version $(HELM_CHART_VERSION) published successfully" + +# Print the Helm chart version +.PHONY: helm-print-chart-version +helm-print-chart-version: + @echo $(HELM_CHART_VERSION) + +# Print the Helm chart name +.PHONY: helm-print-chart-name +helm-print-chart-name: + @echo $(HELM_CHART_NAME) + +# Print the Helm registry +.PHONY: helm-print-registry +helm-print-registry: + @echo $(HELM_REGISTRY) diff --git a/charts/kubernetes-mcp-server/Chart.yaml b/charts/kubernetes-mcp-server/Chart.yaml index a66650bb..01fc3f75 100644 --- a/charts/kubernetes-mcp-server/Chart.yaml +++ b/charts/kubernetes-mcp-server/Chart.yaml @@ -11,3 +11,4 @@ maintainers: - name: Marc Nuri email: marc.nuri@redhat.com version: 0.1.0 +appVersion: "latest" diff --git a/charts/kubernetes-mcp-server/README.md b/charts/kubernetes-mcp-server/README.md index 49b5759d..e7d27def 100644 --- a/charts/kubernetes-mcp-server/README.md +++ b/charts/kubernetes-mcp-server/README.md @@ -1,6 +1,6 @@ # kubernetes-mcp-server -![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![AppVersion: latest](https://img.shields.io/badge/AppVersion-latest-informational?style=flat-square) Helm Chart for the Kubernetes MCP Server @@ -20,12 +20,12 @@ The Chart can be installed quickly and easily to a Kubernetes cluster. Since an Install the Chart using the following command from the root of this directory: ```shell -helm upgrade -i -n kubernetes-mcp-server --create-namespace kubernetes-mcp-server . --set openshift=true --set ingress.host= +helm upgrade -i -n kubernetes-mcp-server --create-namespace kubernetes-mcp-server oci://ghcr.io/containers/charts/kubernetes-mcp-server --set ingress.host= ``` ### Optimized OpenShift Deployment -Functionality has bee added to the Chart to simplify the deployment to OpenShift Cluster. +Functionality has been added to the Chart to simplify the deployment to OpenShift Cluster. ## Values @@ -72,5 +72,5 @@ The contents of the README.md file is generated using [helm-docs](https://github Execute the following command to regenerate the documentation from within the Helm Chart directory. ```shell -helm-docs -t README.md.gotpl +helm-docs -t README.md.gotmpl ``` diff --git a/charts/kubernetes-mcp-server/README.md.gotmpl b/charts/kubernetes-mcp-server/README.md.gotmpl index b1b30d68..5f8c3ef0 100644 --- a/charts/kubernetes-mcp-server/README.md.gotmpl +++ b/charts/kubernetes-mcp-server/README.md.gotmpl @@ -20,7 +20,7 @@ The Chart can be installed quickly and easily to a Kubernetes cluster. Since an Install the Chart using the following command from the root of this directory: ```shell -helm upgrade -i -n kubernetes-mcp-server --create-namespace kubernetes-mcp-server . --set openshift=true --set ingress.host= +helm upgrade -i -n kubernetes-mcp-server --create-namespace kubernetes-mcp-server oci://ghcr.io/containers/charts/kubernetes-mcp-server --set ingress.host= ``` ### Optimized OpenShift Deployment @@ -36,5 +36,5 @@ The contents of the README.md file is generated using [helm-docs](https://github Execute the following command to regenerate the documentation from within the Helm Chart directory. ```shell -helm-docs -t README.md.gotpl +helm-docs -t README.md.gotmpl ```