diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..7e967a70c4 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,86 @@ +name: Release + +on: + push: + tags: + - v* + +permissions: + contents: write + pull-requests: write + +env: + GO_VERSION: "^1.21" + GOLANGCI_LINT_VERSION: "v1.54.2" + E2E_SETUP_KIND: yes + E2E_SETUP_KUBECTL: yes + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Extract pushed release tag + id: extract_tag + run: echo "::set-output name=tag::${GITHUB_REF##*/}" + - name: Checkout into the corresponding release branch + uses: actions/checkout@v4 + - name: Create VCS sandbox + run: | + git checkout -b release-${{ steps.extract_tag.outputs.tag }} + - name: Set up the Go@${{ env.GO_VERSION }} environment + uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + - name: Get the pushed tag + id: get_tag + run: echo ::set-output name=tag::${GITHUB_REF#refs/*/} + - name: Store the previous tag + id: get_previous_tag + run: echo ::set-output name=previous_tag::$(cat VERSION | cut -d. -f1,2) + - name: Update the VERSION manifest to the pushed tag + run: echo "${{ steps.get_tag.outputs.tag }}" | sed 's/^v//' > VERSION + - name: Update the compatibility matrix (README.md) + run: ./scripts/update-compatibility-matrix.sh + - name: Generate the release notes (CHANGELOG.md) + run: ./scripts/generate-release-notes.sh + - name: Install tools + run: make install-tools + - name: Lint + run: | + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | \ + sh -s -- -b $(go env GOPATH)/bin ${{ env.GOLANGCI_LINT_VERSION }} + make lint-fix + - name: Generate manifests + run: make examples + - name: Run rule tests + run: PROMTOOL_CLI=./promtool make install-promtool test-rules + - name: Run unit tests + run: make test-unit + - name: Run end-to-end tests + run: make e2e + - name: Update the remote and commit the changes + run: | + git config --local user.email "ksm-release-bot@mock-k8s.io" + git config --local user.name "KSM Release Bot" + git add . + git commit -m "chore: Cut ${{ steps.get_tag.outputs.tag }}" + git push origin HEAD:release-${{ steps.get_tag.outputs.tag }} --force-with-lease + - name: Benchmark tests + run: LATEST_RELEASE_BRANCH=release-${{ steps.get_previous_tag.outputs.previous_tag }} make test-benchmark-compare + - name: Validate docs + run: make doccheck + - name: Validate manifests + run: make validate-manifests + - name: Validate go modules + run: make validate-modules + - name: Create a pull request + run: | + gh pr create \ + --title "chore: Cut ${{ steps.get_tag.outputs.tag }}" \ + --body "This PR was automatically created by the release workflow, and should be targeted to the corresponding release branch." \ + --base main \ + --head release-${{ steps.get_tag.outputs.tag }} + --reviewer @sig-instrumentation-approvers \ + --assignee @sig-instrumentation-leads + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/Makefile b/Makefile index 885154c430..76f86c6ea5 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ REGISTRY ?= gcr.io/k8s-staging-kube-state-metrics TAG_PREFIX = v VERSION = $(shell cat VERSION) TAG ?= $(TAG_PREFIX)$(VERSION) -LATEST_RELEASE_BRANCH := release-$(shell grep -ohE "[0-9]+.[0-9]+" VERSION) +LATEST_RELEASE_BRANCH ?= release-$(shell grep -ohE "[0-9]+.[0-9]+" VERSION) BRANCH = $(strip $(shell git rev-parse --abbrev-ref HEAD)) DOCKER_CLI ?= docker PROMTOOL_CLI ?= promtool diff --git a/README.md b/README.md index 702f7cc072..05854bc447 100644 --- a/README.md +++ b/README.md @@ -270,7 +270,7 @@ To have Prometheus discover kube-state-metrics instances it is advised to create kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud info --format='value(config.account)') ``` -Note that your GCP identity is case sensitive but `gcloud info` as of Google Cloud SDK 221.0.0 is not. This means that if your IAM member contains capital letters, the above one-liner may not work for you. If you have 403 forbidden responses after running the above command and `kubectl apply -f examples/standard`, check the IAM member associated with your account at https://console.cloud.google.com/iam-admin/iam?project=PROJECT_ID. If it contains capital letters, you may need to set the --user flag in the command above to the case-sensitive role listed at https://console.cloud.google.com/iam-admin/iam?project=PROJECT_ID. +Note that your GCP identity is case sensitive but `gcloud info` as of Google Cloud SDK 221.0.0 is not. This means that if your IAM member contains capital letters, the above one-liner may not work for you. If you have 403 forbidden responses after running the above command and `kubectl apply -f examples/standard`, check the IAM member associated with your account at . If it contains capital letters, you may need to set the --user flag in the command above to the case-sensitive role listed at . After running the above, if you see `Clusterrolebinding "cluster-admin-binding" created`, then you are able to continue with the setup of this service. diff --git a/go.mod b/go.mod index f4f719f041..df9e0739e9 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,6 @@ require ( ) require ( - github.com/Kunde21/markdownfmt/v3 v3.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect @@ -54,7 +53,6 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -71,7 +69,6 @@ require ( github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/yuin/goldmark v1.3.5 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.18.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect diff --git a/go.sum b/go.sum index d45803d9d3..327ea86e07 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/Kunde21/markdownfmt/v3 v3.1.0 h1:KiZu9LKs+wFFBQKhrZJrFZwtLnCCWJahL+S+E/3VnM0= -github.com/Kunde21/markdownfmt/v3 v3.1.0/go.mod h1:tPXN1RTyOzJwhfHoon9wUr4HGYmWgVxSQN6VBJDkrVc= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= @@ -80,8 +78,6 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -147,8 +143,6 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/scripts/generate-release-notes.sh b/scripts/generate-release-notes.sh new file mode 100755 index 0000000000..9d1cafa487 --- /dev/null +++ b/scripts/generate-release-notes.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -exuo pipefail + +CHANGELOG="CHANGELOG.md" + +# Fetch the latest two tags. +# NOTE: This assumes a patch release for an older release is not made after a later minor release (which is the case right now). +# Backports will be handled manually, on a case-by-case basis. +last_two_tags=$(git tag --sort=-creatordate | head -n 2) + +# read will return a non-zero exit code when it hits EOF, so we need to disable the exit-on-error option. +set +e +IFS=$'\n' read -d '' -r -a tags <<< "$last_two_tags" +set -e + +# Get the commits between the two tags. +commits=$(git log --pretty=format:"%h: %an <%ae>: %s" "${tags[1]}".."${tags[0]}" | grep -i -v -e 'fixup' -e 'merge' -e 'dependabot') + +# Update the changelog with the latest release notes. +echo -e "## ${tags[0]} / $(date "+%Y-%m-%d")\n\n$commits\n\n$(cat $CHANGELOG)" > $CHANGELOG diff --git a/scripts/update-compatibility-matrix.sh b/scripts/update-compatibility-matrix.sh new file mode 100755 index 0000000000..b5bdfe3f94 --- /dev/null +++ b/scripts/update-compatibility-matrix.sh @@ -0,0 +1,53 @@ +#!/bin/bash +set -exuo pipefail + +# Determine the OS to use the correct version of sed and awk. +# shellcheck disable=SC2209 +SED=sed +# shellcheck disable=SC2209 +AWK=awk +if [[ $(uname) == "Darwin" ]]; then + # Check if gnu-sed and gawk are installed. + if ! command -v gsed &> /dev/null; then + echo "gnu-sed is not installed. Please install it using 'brew install gnu-sed'." >&2 + exit 1 + fi + if ! command -v gawk &> /dev/null; then + echo "gawk is not installed. Please install it using 'brew install gawk'." >&2 + exit 1 + fi + AWK=gawk + SED=gsed +fi + +# Fetch the latest tag. +git fetch --tags +latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)") + +# Determine if it's a patch release or not (minor and major releases are handled the same way in the compatibility matrix). +if [[ $latest_tag =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + IFS='.' read -ra TAG <<< "$latest_tag" + if [[ ${#TAG[@]} -eq 2 || ${#TAG[@]} -eq 3 && ${TAG[2]} -eq 0 ]]; then + # Prep for a non-patch release. + # shellcheck disable=SC2016 + main_client_go_version=$($AWK '/\| \*\*main\*\*/ {print $4}' README.md) + $SED -i "/|\s*\*\*main\*\*\s*|\s*$main_client_go_version\s*|/i| \*\*$latest_tag\*\* | $main_client_go_version |" README.md + # shellcheck disable=SC2016 + oldest_supported_client_go_version=$($AWK '/\| kube-state-metrics \| Kubernetes client-go Version \|/ {getline; getline; print $4; exit}' README.md) + # Remove the first row (i.e., the oldest supported client-go version). + $SED -i "/|\s*\*\*.*\*\*\s*|\s*$oldest_supported_client_go_version\s*|/d" README.md + else + # Prep for a patch release. + minor_release="${TAG[0]}.${TAG[1]}" + # Get the client-go version of the corresponding minor release row (that needs to be updated with the patch release version). + # shellcheck disable=SC2016 + last_client_go_version=$($AWK '/\| kube-state-metrics \| Kubernetes client-go Version \|/ {getline; getline; getline; getline; getline; getline; print $4; exit}' README.md) + # Update the row with the latest tag and client-go version. + $SED -i "s/|\s*\*\*$minor_release.*\*\*\s*|\s*$last_client_go_version\s*|/| \*\*$latest_tag\*\* | $last_client_go_version |/" README.md + fi +else + echo -e "Bad tag format: $latest_tag, expected one of the following formats:\n + * vMAJOR.MINOR (non-patch release)\n + * vMAJOR.MINOR.PATCH (patch release)" + exit 1 +fi diff --git a/tools/tools.go b/tools/tools.go index 0f2db0a141..bd493c9915 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -20,7 +20,7 @@ limitations under the License. package tools import ( - _ "github.com/Kunde21/markdownfmt/v3" + _ "github.com/Kunde21/markdownfmt/v3/markdown" _ "github.com/brancz/gojsontoyaml" _ "github.com/campoy/embedmd" _ "github.com/google/go-jsonnet/cmd/jsonnet"