diff --git a/CHANGELOG.md b/CHANGELOG.md index d3e29d7..1ea449b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [v0.13.0] - 2023-07-07 +### Added +- [#32] Add Helm chart release process to project + ## [v0.12.1] - 2023-06-01 ### Fixed - [#30] Add appropriate labels to generated ingress resources diff --git a/Dockerfile b/Dockerfile index 5eb0045..090716e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,7 +31,7 @@ RUN make compile-generic FROM gcr.io/distroless/static:nonroot LABEL maintainer="hello@cloudogu.com" \ NAME="k8s-service-discovery" \ - VERSION="0.12.1" + VERSION="0.13.0" WORKDIR / diff --git a/Jenkinsfile b/Jenkinsfile index 7f0bf68..da06da6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,6 +1,6 @@ #!groovy -@Library(['github.com/cloudogu/ces-build-lib@1.64.2']) +@Library(['github.com/cloudogu/ces-build-lib@1.65.0']) import com.cloudogu.ces.cesbuildlib.* // Creating necessary git objects @@ -12,11 +12,15 @@ github = new GitHub(this, git) changelog = new Changelog(this) Docker docker = new Docker(this) gpg = new Gpg(this, docker) +goVersion = "1.20" +makefile = new Makefile(this) // Configuration of repository repositoryOwner = "cloudogu" repositoryName = "k8s-service-discovery" project = "github.com/${repositoryOwner}/${repositoryName}" +registry = "registry.cloudogu.com" +registry_namespace = "k8s" // Configuration of branches productionReleaseBranch = "main" @@ -40,7 +44,7 @@ node('docker') { } docker - .image('golang:1.20.3') + .image("golang:${goVersion}") .mountJenkinsUser() .inside("--volume ${WORKSPACE}:/go/src/${project} -w /go/src/${project}") { @@ -73,14 +77,12 @@ node('docker') { K3d k3d = new K3d(this, "${WORKSPACE}", "${WORKSPACE}/k3d", env.PATH) try { - Makefile makefile = new Makefile(this) - String controllerVersion = makefile.getVersion() - stage('Set up k3d cluster') { k3d.startK3d() } def imageName + String controllerVersion = makefile.getVersion() stage('Build & Push Image') { imageName=k3d.buildAndPushToLocalRegistry("cloudogu/${repositoryName}", controllerVersion) } @@ -125,14 +127,12 @@ void gitWithCredentials(String command) { void stageLintK8SResources() { String kubevalImage = "cytopia/kubeval:0.13" - Makefile makefile = new Makefile(this) - String controllerVersion = makefile.getVersion() docker .image(kubevalImage) .inside("-v ${WORKSPACE}/target/make/k8s:/data -t --entrypoint=") { - sh "kubeval /data/${repositoryName}_${controllerVersion}.yaml --ignore-missing-schemas" + sh "kubeval /data/${repositoryName}_${makefile.getVersion()}.yaml --ignore-missing-schemas" } } @@ -181,6 +181,7 @@ void stageAutomaticRelease() { if (gitflow.isReleaseBranch()) { String releaseVersion = git.getSimpleBranchName() String dockerReleaseVersion = releaseVersion.split("v")[1] + String controllerVersion = makefile.getVersion() stage('Build & Push Image') { def dockerImage = docker.build("cloudogu/${repositoryName}:${dockerReleaseVersion}") @@ -194,14 +195,27 @@ void stageAutomaticRelease() { } stage('Push to Registry') { - Makefile makefile = new Makefile(this) - String controllerVersion = makefile.getVersion() GString targetOperatorResourceYaml = "target/make/k8s/${repositoryName}_${controllerVersion}.yaml" DoguRegistry registry = new DoguRegistry(this) registry.pushK8sYaml(targetOperatorResourceYaml, repositoryName, "k8s", "${controllerVersion}") } + stage('Push Helm chart to Harbor') { + new Docker(this) + .image("golang:${goVersion}") + .mountJenkinsUser() + .inside("--volume ${WORKSPACE}:/go/src/${project} -w /go/src/${project}") + { + make 'k8s-helm-package-release' + + withCredentials([usernamePassword(credentialsId: 'harborhelmchartpush', usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD')]) { + sh ".bin/helm registry login ${registry} --username '${HARBOR_USERNAME}' --password '${HARBOR_PASSWORD}'" + sh ".bin/helm push target/make/k8s/helm/${repositoryName}-${controllerVersion}.tgz oci://${registry}/${registry_namespace}/" + } + } + } + stage('Add Github-Release') { releaseId = github.createReleaseWithChangelog(releaseVersion, changelog, productionReleaseBranch) } diff --git a/Makefile b/Makefile index e15dda7..e553366 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ # Set these to the desired values ARTIFACT_ID=k8s-service-discovery -VERSION=0.12.1 +VERSION=0.13.0 ## Image URL to use all building/pushing image targets IMAGE_DEV=${K3CES_REGISTRY_URL_PREFIX}/${ARTIFACT_ID}:${VERSION} IMAGE=cloudogu/${ARTIFACT_ID}:${VERSION} GOTAG?=1.20.3 -MAKEFILES_VERSION=7.5.0 +MAKEFILES_VERSION=7.10.0 LINT_VERSION?=v1.52.1 ADDITIONAL_CLEAN=dist-clean diff --git a/build/make/k8s-dogu.mk b/build/make/k8s-dogu.mk index ff0973b..c498dcd 100644 --- a/build/make/k8s-dogu.mk +++ b/build/make/k8s-dogu.mk @@ -6,7 +6,7 @@ DOGU_JSON_DEV_FILE=${TARGET_DIR}/dogu.json ARTIFACT_ID=$(shell $(BINARY_YQ) -e ".Name" $(DOGU_JSON_FILE) | sed "s|.*/||g") # Namespace of the dogu is extracted from the dogu.json ARTIFACT_NAMESPACE=$(shell $(BINARY_YQ) -e ".Name" $(DOGU_JSON_FILE) | sed "s|/.*||g") -# Namespace of the dogu is extracted from the dogu.json +# Version of the dogu is extracted from the dogu.json VERSION=$(shell $(BINARY_YQ) -e ".Version" $(DOGU_JSON_FILE)) # Image of the dogu is extracted from the dogu.json IMAGE=$(shell $(BINARY_YQ) -e ".Image" $(DOGU_JSON_FILE)):$(VERSION) diff --git a/build/make/k8s.mk b/build/make/k8s.mk index 8e0fa4a..c569fa3 100644 --- a/build/make/k8s.mk +++ b/build/make/k8s.mk @@ -7,6 +7,7 @@ endif ## Variables BINARY_YQ = $(UTILITY_BIN_PATH)/yq +BINARY_HELM = $(UTILITY_BIN_PATH)/helm # The productive tag of the image IMAGE ?= @@ -19,6 +20,8 @@ K3CES_REGISTRY_URL_PREFIX="${K3S_CLUSTER_FQDN}:${K3S_LOCAL_REGISTRY_PORT}" # the current namespace and the dev image. K8S_RESOURCE_TEMP_FOLDER ?= $(TARGET_DIR)/make/k8s K8S_RESOURCE_TEMP_YAML ?= $(K8S_RESOURCE_TEMP_FOLDER)/$(ARTIFACT_ID)_$(VERSION).yaml +K8S_HELM_TARGET ?= $(K8S_RESOURCE_TEMP_FOLDER)/helm +K8S_HELM_RESSOURCES ?= k8s/helm ##@ K8s - Variables @@ -75,6 +78,56 @@ k8s-apply: k8s-generate $(K8S_POST_GENERATE_TARGETS) ## Applies all generated K8 @echo "Apply generated K8s resources..." @kubectl apply -f $(K8S_RESOURCE_TEMP_YAML) --namespace=${NAMESPACE} +##@ K8s - Helm general + +${K8S_HELM_RESSOURCES}/Chart.yaml: ${BINARY_HELM} ## Creates the Chart.yaml-template if missing + @echo "Create Chart.yaml..." + @mkdir -p ${K8S_HELM_RESSOURCES}/tmp/ + @${BINARY_HELM} create ${K8S_HELM_RESSOURCES}/tmp/${ARTIFACT_ID} + @cp ${K8S_HELM_RESSOURCES}/tmp/${ARTIFACT_ID}/Chart.yaml ${K8S_HELM_RESSOURCES}/ + @rm -dr ${K8S_HELM_RESSOURCES}/tmp + @sed -i 's/appVersion: ".*"/appVersion: "0.0.0-replaceme"/' ${K8S_HELM_RESSOURCES}/Chart.yaml + @sed -i 's/version: .*/version: 0.0.0-replaceme/' ${K8S_HELM_RESSOURCES}/Chart.yaml + +.PHONY: k8s-helm-delete +k8s-helm-delete: ${BINARY_HELM} ## Uninstalls the current helm chart. + @echo "Uninstall helm chart" + @${BINARY_HELM} uninstall ${ARTIFACT_ID} + +.PHONY: k8s-helm-generate-chart +k8s-helm-generate-chart: ${K8S_HELM_RESSOURCES}/Chart.yaml $(K8S_RESOURCE_TEMP_FOLDER) ## Generates the final helm chart. + @echo "Generate helm chart..." + @rm -drf ${K8S_HELM_TARGET} # delete folder, so Chart.yaml is newly created from template + @mkdir -p ${K8S_HELM_TARGET}/templates + @cp $(K8S_RESOURCE_TEMP_YAML) ${K8S_HELM_TARGET}/templates + @cp ${K8S_HELM_RESSOURCES}/Chart.yaml ${K8S_HELM_TARGET} + @sed -i 's/appVersion: "0.0.0-replaceme"/appVersion: "${VERSION}"/' ${K8S_HELM_TARGET}/Chart.yaml + @sed -i 's/version: 0.0.0-replaceme/version: ${VERSION}/' ${K8S_HELM_TARGET}/Chart.yaml + +##@ K8s - Helm dev targets + +.PHONY: k8s-helm-generate +k8s-helm-generate: k8s-generate k8s-helm-generate-chart ## Generates the final helm chart with dev-urls. + +.PHONY: k8s-helm-apply +k8s-helm-apply: ${BINARY_HELM} image-import k8s-helm-generate $(K8S_POST_GENERATE_TARGETS) ## Generates and installs the helm chart. + @echo "Apply generated helm chart" + @${BINARY_HELM} upgrade -i ${ARTIFACT_ID} ${K8S_HELM_TARGET} + +.PHONY: k8s-helm-reinstall +k8s-helm-reinstall: k8s-helm-delete k8s-helm-apply ## Uninstalls the current helm chart and reinstalls it. + +##@ K8s - Helm release targets + +.PHONY: k8s-helm-generate-release +k8s-helm-generate-release: $(K8S_PRE_GENERATE_TARGETS) k8s-helm-generate-chart ## Generates the final helm chart with release urls. + @sed -i "s/'{{ .Namespace }}'/'{{ .Release.Namespace }}'/" ${K8S_HELM_TARGET}/templates/$(ARTIFACT_ID)_$(VERSION).yaml + +.PHONY: k8s-helm-package-release +k8s-helm-package-release: ${BINARY_HELM} k8s-helm-generate-release $(K8S_POST_GENERATE_TARGETS) ## Generates and packages the helm chart with release urls. + @echo "Package generated helm chart" + @${BINARY_HELM} package ${K8S_HELM_TARGET} -d ${K8S_HELM_TARGET} + ##@ K8s - Docker .PHONY: docker-build @@ -115,5 +168,8 @@ __check_defined = \ $(if $(value $1),, \ $(error Undefined $1$(if $2, ($2)))) -${BINARY_YQ}: $(UTILITY_BIN_PATH) ## Download controller-gen locally if necessary. - $(call go-get-tool,$(BINARY_YQ),github.com/mikefarah/yq/v4@v4.25.1) \ No newline at end of file +${BINARY_YQ}: $(UTILITY_BIN_PATH) ## Download yq locally if necessary. + $(call go-get-tool,$(BINARY_YQ),github.com/mikefarah/yq/v4@v4.25.1) + +${BINARY_HELM}: $(UTILITY_BIN_PATH) ## Download helm locally if necessary. + $(call go-get-tool,$(BINARY_HELM),helm.sh/helm/v3/cmd/helm@latest) diff --git a/build/make/version-sha.mk b/build/make/version-sha.mk new file mode 100644 index 0000000..1335532 --- /dev/null +++ b/build/make/version-sha.mk @@ -0,0 +1,18 @@ +##@ Version + +# This makefile is used to get the sha256sum of a specific github tag-src.tar.gz or .zip. +# You may set any of the following variables before your make call to change the hash url. + +SHA_SUM_ORGANISATION?="cloudogu" +SHA_SUM_REPOSITORY?="ecosystem" +SHA_SUM_FILE_TYPE?="tar.gz" +SHA_SUM_VERSION?="v20.04.4-2" +SHA_SUM_URL?="https://github.com/${SHA_SUM_ORGANISATION}/${SHA_SUM_REPOSITORY}/archive/refs/tags/${SHA_SUM_VERSION}.${SHA_SUM_FILE_TYPE}" + +.PHONY: sha-sum +sha-sum: ## Print out the version + @echo "Downloading from: ${SHA_SUM_URL}" + @wget -O - -o /dev/null "${SHA_SUM_URL}" > .download.for.hash \ + || (echo "Could not be downloaded" && exit 1) \ + && cat .download.for.hash | sha256sum + @rm -f .download.for.hash diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 69ffc7e..f04a4dd 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -11,4 +11,4 @@ kind: Kustomization images: - name: controller newName: cloudogu/k8s-service-discovery - newTag: 0.12.1 + newTag: 0.13.0 diff --git a/k8s/helm/Chart.yaml b/k8s/helm/Chart.yaml new file mode 100644 index 0000000..25e8bf4 --- /dev/null +++ b/k8s/helm/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: k8s-service-discovery +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.0.0-replaceme + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "0.0.0-replaceme"