Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,10 @@

**Which issue(s) this PR fixes:** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*
Fixes #

<!-- In case of the change being user-facing, an entry should be appended to the latest unreleased section in CHANGELOG.md.
The expected format is as follows:
- [ENHANCEMENT/CHANGE/BUGFIX/FEATURE]: <PR TITLE> by @PR_AUTHOR in https://github.com/kubernetes/kube-state-metrics/pull/<PR NUMBER> (avoid using #<PR NUMBER> for inter-VCS compatibility), for instance:
- [ENHANCEMENT]: Add support for Windows by @k8s-ci-robot in https://github.com/kubernetes/kube-state-metrics/pull/1234
-->
- [ ] I have added a CHANGELOG entry for this change.
181 changes: 181 additions & 0 deletions .github/workflows/pre-release-pull-request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
name: Pre-Release PR

on:
workflow_dispatch:
inputs:
new_version:
description: 'The new release version (e.g., v2.10.0)'
required: true
type: string

permissions:
contents: write
pull-requests: write

env:
GO_VERSION: "^1.24"
GOLANGCI_LINT_VERSION: "v2.4.0"
E2E_SETUP_KIND: yes
E2E_SETUP_KUBECTL: yes

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Validate version format
run: |
if [[ ! "${{ inputs.new_version }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: Version format is incorrect. It must be in the format 'vX.Y.Z'."
exit 1
fi
echo "Version format is valid."
- name: Checkout into the corresponding release branch
uses: actions/checkout@v4
- name: Checkout to release branch
run: |
git checkout -b prep-${{ inputs.new_version }}
MAJOR_MINOR_VERSION=$(echo "${{ inputs.new_version }}" | sed 's/^v//' | cut -d. -f1,2)
if git show-ref --verify --quiet refs/remotes/origin/release-$MAJOR_MINOR_VERSION; then
echo "Release branch release-$MAJOR_MINOR_VERSION already exists, switching to it"
git checkout -b release-$MAJOR_MINOR_VERSION origin/release-$MAJOR_MINOR_VERSION
else
echo "Creating new release branch release-$MAJOR_MINOR_VERSION"
git checkout -b release-$MAJOR_MINOR_VERSION
git push origin release-$MAJOR_MINOR_VERSION
fi
git checkout prep-${{ inputs.new_version }}
- name: Set up the go@${{ env.GO_VERSION }} environment
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Update the VERSION manifest
run: echo "${{ inputs.new_version }}" | sed 's/^v//' > VERSION
- name: Update data.yaml
run: ./scripts/update-data-yaml.sh "${{ inputs.new_version }}"
- name: Update the compatibility matrix (README.md)
run: make generate
- name: Move unreleased to released in CHANGELOG.md
run: ./scripts/generate-release-date.sh "${{ inputs.new_version }}"
- name: make lint-fix
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 clean || true
VERSION="${{ inputs.new_version }}" make examples
- name: Update the remote and commit the changes
run: |
git config --local user.email "${{ github.actor }}@users.noreply.github.com"
git config --local user.name "${{ github.actor }}"
git add .
git commit -m "chore: Cut ${{ inputs.new_version }}"
git push origin prep-${{ inputs.new_version }}
- name: Validate docs
run: make doccheck
- name: Validate manifests
run: make validate-manifests
- name: Validate go modules
run: make validate-modules
- 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
find examples -name "*.yaml" -type f -exec sed -i 's|kube-state-metrics-amd64|kube-state-metrics|g; s|kube-state-metrics-arm64|kube-state-metrics|g' {} \;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the scripts are appending the architecture to the binary name, this should be fixed in those scripts itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there is a direct way to fix that in e2e script otherwise it would fail, I've already tried updating the script

- name: Run benchmark tests
run: |
BENCHSTAT_OUTPUT_FILE=result.txt ./tests/compare_benchmarks.sh main 2
- name: Post results to job summary
run: |
echo "### Benchmark Comparison Results" >> "$GITHUB_STEP_SUMMARY"
echo "\`\`\`" >> "$GITHUB_STEP_SUMMARY"
cat result.txt >> "$GITHUB_STEP_SUMMARY"
echo "\`\`\`" >> "$GITHUB_STEP_SUMMARY"
- name: Create a pull request
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd appreciate if the longer lines could be broken (using multi-line separators) down and commented for this step.

run: |
# Extract major.minor version for branch naming
MAJOR_MINOR_VERSION=$(echo "${{ inputs.new_version }}" | sed 's/^v//' | cut -d. -f1,2)

# Get the most recent tag for changelog generation
PREV_TAG=$(git tag --sort=-version:refname | head -n1 || echo "")

# Determine date range for PR search
if [[ -n "$PREV_TAG" ]]; then
PREV_TAG_DATE="$(git show -s --format=%cI "$PREV_TAG" 2>/dev/null || true)"
RANGE="${PREV_TAG}..HEAD"
else
PREV_TAG_DATE="1970-01-01T00:00:00Z"
PREV_REF="$(git rev-list --max-parents=0 HEAD)"
RANGE="${PREV_REF}..HEAD"
fi

# Format dates for PR search
PREV_DATE_SHORT="$(date -d "$PREV_TAG_DATE" +%Y-%m-%d 2>/dev/null || echo "1970-01-01")"
TAG_DATE_SHORT="$(date -u +%Y-%m-%d)"

# Extract changelog section for this version
CHANGELOG_SECTION=$(awk '/^## '"${{ inputs.new_version }}"'/{flag=1; next} /^## /{if(flag) exit} flag' CHANGELOG.md | \
grep -E '^\s*\*\s*\[' | \
sed 's/^/ /' || \
echo " No user-facing changes found for this version.")

# Get merged PRs in the date range
PR_LINES="$(gh pr list \
--state merged \
--search "merged:${PREV_DATE_SHORT}..${TAG_DATE_SHORT}" \
--json number,title,author \
--limit 1000 \
--template '{{range .}}{{.number}}|{{.title}}|{{.author.login}}{{"\n"}}{{end}}')" || true

# Build full changelog from merged PRs
FULL_CHANGELOG_LINES=()
if [[ -n "$PR_LINES" ]]; then
while IFS= read -r line; do
if [[ -n "$line" ]]; then
prnum="${line%%|*}"
rest="${line#*|}"
title="${rest%%|*}"
login="${rest##*|}"
FULL_CHANGELOG_LINES+=(" - ${title} by @${login} in #${prnum}")
fi
done <<< "$PR_LINES"
fi

# Format full changelog text
FULL_CHANGELOG_TEXT=""
if [[ ${#FULL_CHANGELOG_LINES[@]} -gt 0 ]]; then
printf -v FULL_CHANGELOG_TEXT "%s\n" "${FULL_CHANGELOG_LINES[@]}"
else
FULL_CHANGELOG_TEXT=" (no merged PRs found in this release)"
fi

# Create PR body file to avoid quote issues
cat > pr_body.txt << EOF
This PR was automatically created by the release workflow.

## Changelog

$CHANGELOG_SECTION

## Full Changelog

$FULL_CHANGELOG_TEXT
EOF

# Create the pull request
gh pr create \
--title "chore: Cut ${{ inputs.new_version }}" \
--body-file pr_body.txt \
--base release-$MAJOR_MINOR_VERSION \
--head prep-${{ inputs.new_version }} \
--reviewer @sig-instrumentation-approvers \
--assignee @sig-instrumentation-leads

# Clean up temporary file
rm pr_body.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@ help.txt

# jsonnet dependency management
/scripts/vendor

promtool
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased

## Released

## v2.17.0 / 2025-09-01

* This release builds with Go `v1.24.6`
Expand Down
54 changes: 54 additions & 0 deletions scripts/generate-release-date.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/bin/bash
set -exuo pipefail

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
REPO_ROOT=$( cd -- "${SCRIPT_DIR}/.." &> /dev/null && pwd )
CHANGELOG_FILE="${REPO_ROOT}/CHANGELOG.md"

if [ -z "$1" ]; then
echo "Error: A version argument is required (e.g., v2.10.0)." >&2
exit 1
fi
new_version=$1

# Determine the OS to use the correct version of sed.
# shellcheck disable=SC2209
SED=sed
if [[ $(uname) == "Darwin" ]]; then
# Check if gnu-sed is 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
SED=gsed
fi

# Extract content between "## Unreleased" and "## Released"
UNRELEASED_CONTENT=$($SED -n '/^## Unreleased/,/^## Released/{/^## Unreleased/d; /^## Released/d; p;}' "${CHANGELOG_FILE}")

# Clear the Unreleased section (remove everything between "## Unreleased" and "## Released")
$SED -i '/^## Unreleased/,/^## Released/{/^## Unreleased/!{/^## Released/!d;}}' "${CHANGELOG_FILE}"

# Add an empty line after the Unreleased section
$SED -i '/^## Unreleased/a\\' "${CHANGELOG_FILE}"

# Add the new version section with date after "## Released"
if [[ -n "$UNRELEASED_CONTENT" ]]; then
# Create a temporary file to avoid issues with quotes and special characters
TEMP_FILE=$(mktemp)
echo "" > "$TEMP_FILE"
echo "## $new_version / $(date +'%Y-%m-%d')" >> "$TEMP_FILE"
echo "" >> "$TEMP_FILE"
echo "$UNRELEASED_CONTENT" >> "$TEMP_FILE"

$SED -i "/^## Released/r $TEMP_FILE" "${CHANGELOG_FILE}"

rm "$TEMP_FILE"
else
# If no content in Unreleased, just add the version header
$SED -i "/^## Released/a\\
\\
## $new_version / $(date +'%Y-%m-%d')" "${CHANGELOG_FILE}"
fi

echo "CHANGELOG.md updated successfully. Moved unreleased content to $new_version section."