From 8d17f889f04749bb27a6001fb1d2a1c84087b80e Mon Sep 17 00:00:00 2001 From: Stefan Date: Sun, 29 Mar 2026 16:48:46 +0200 Subject: [PATCH] ci: auto-generate release notes from commits --- .drone.yml | 13 +++++- scripts/generate-release-notes.sh | 71 +++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100755 scripts/generate-release-notes.sh diff --git a/.drone.yml b/.drone.yml index 11f08d6..d5021c2 100644 --- a/.drone.yml +++ b/.drone.yml @@ -24,6 +24,16 @@ steps: - go install golang.org/x/vuln/cmd/govulncheck@latest - govulncheck -json ./... > vulncheck.json +- name: release-notes + image: alpine/git + commands: + - bash scripts/generate-release-notes.sh + when: + event: + - tag + status: + - success + - name: package image: golang:1.25.8 commands: @@ -42,8 +52,9 @@ steps: files: - .build/coverage.txt - .build/sources.tar.gz + - .build/release-notes.md title: ${DRONE_TAG} - note: "Release ${DRONE_TAG}\n\nCoverage report: coverage.txt" + note_from_file: .build/release-notes.md when: event: - tag diff --git a/scripts/generate-release-notes.sh b/scripts/generate-release-notes.sh new file mode 100755 index 0000000..8bf7b95 --- /dev/null +++ b/scripts/generate-release-notes.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# Generate release notes from commits since the last tag + +set -e + +CURRENT_TAG="${1:-${DRONE_TAG}}" +OUTPUT_FILE="${2:-.build/release-notes.md}" + +if [ -z "$CURRENT_TAG" ]; then + echo "Error: Current tag not provided" + exit 1 +fi + +# Find the previous tag +PREVIOUS_TAG=$(git describe --tags --abbrev=0 "$CURRENT_TAG"^ 2>/dev/null || echo "") + +mkdir -p "$(dirname "$OUTPUT_FILE")" + +# Start release notes +{ + echo "# Release $CURRENT_TAG" + echo "" + + if [ -n "$PREVIOUS_TAG" ]; then + echo "**Changes since $PREVIOUS_TAG:**" + echo "" + + # Extract commits and group by type (feat, fix, docs, ci, etc.) + git log "$PREVIOUS_TAG..$CURRENT_TAG" --pretty=format:"%s" | while read -r commit; do + # Parse conventional commits + if [[ $commit =~ ^([a-z]+)(\(.+\))?:\ (.+)$ ]]; then + TYPE="${BASH_REMATCH[1]}" + SCOPE="${BASH_REMATCH[2]}" + MESSAGE="${BASH_REMATCH[3]}" + + case "$TYPE" in + feat) + echo "- ✨ **Feature**${SCOPE}: $MESSAGE" ;; + fix) + echo "- 🐛 **Fix**${SCOPE}: $MESSAGE" ;; + docs) + echo "- 📖 **Docs**${SCOPE}: $MESSAGE" ;; + ci) + echo "- 🔧 **CI**${SCOPE}: $MESSAGE" ;; + test) + echo "- ✅ **Test**${SCOPE}: $MESSAGE" ;; + refactor) + echo "- ♻️ **Refactor**${SCOPE}: $MESSAGE" ;; + perf) + echo "- ⚡ **Performance**${SCOPE}: $MESSAGE" ;; + *) + echo "- 📝 $commit" ;; + esac + else + echo "- 📝 $commit" + fi + done + else + echo "Initial release" + echo "" + git log "$CURRENT_TAG" --pretty=format:"- 📝 %s" | head -20 + fi + + echo "" + echo "---" + echo "See [all changes](https://scm.yoorie.de/git/go-lib/util/compare/$PREVIOUS_TAG...$CURRENT_TAG)" + +} > "$OUTPUT_FILE" + +echo "Release notes generated: $OUTPUT_FILE" +cat "$OUTPUT_FILE"