feat(release): remove version tag prefix from release titles

HACS automatically displays the version number before release titles,
causing duplication when version tags are included in the title.

Changes:
- scripts/generate-release-notes: All backends now generate intelligent
  titles without version prefix (git-cliff, manual, and copilot)
- scripts/generate-release-notes: Added smart title generation based on
  commit analysis (feat/fix counts) for git-cliff and manual backends
- scripts/generate-release-notes: Unified section headers to use ### (H3)
  instead of ## (H2) for consistency across all backends
- scripts/generate-release-notes: Auto-update feature now uses extracted
  title without prepending version tag
- .github/workflows/release.yml: Extract title directly from generated
  release notes (first line with "# ") instead of manual construction
- .github/workflows/release.yml: Removed redundant "Generate release title"
  step

Before (HACS): v0.9.0: v0.9.0 - New Features
After (HACS):  v0.9.0: Multi-Home Support & Diagnostic Sensors

Impact: Release titles in HACS are now cleaner with single version display
and more descriptive titles generated intelligently from commit content.
All three backends (copilot, git-cliff, manual) produce consistent output
with H1 title followed by H3 sections.
This commit is contained in:
Julian Pawlowski 2025-11-16 00:26:34 +00:00
parent 4508e69ffd
commit 3c69ca6f75
2 changed files with 78 additions and 39 deletions

View file

@ -195,6 +195,13 @@ jobs:
# git-cliff will handle filtering via cliff.toml # git-cliff will handle filtering via cliff.toml
USE_AI=false ./scripts/generate-release-notes "${FROM_TAG}" "${TO_TAG}" > release-notes.md USE_AI=false ./scripts/generate-release-notes "${FROM_TAG}" "${TO_TAG}" > release-notes.md
# Extract title from release notes (first line starting with "# ")
TITLE=$(head -n 1 release-notes.md | sed 's/^# //')
if [ -z "$TITLE" ]; then
TITLE="Release Updates"
fi
echo "title=$TITLE" >> $GITHUB_OUTPUT
# Append version warning if present # Append version warning if present
WARNING="${{ steps.version_check.outputs.warning }}" WARNING="${{ steps.version_check.outputs.warning }}"
if [ -n "$WARNING" ]; then if [ -n "$WARNING" ]; then
@ -218,34 +225,10 @@ jobs:
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.version_check.outputs.warning }}" >> $GITHUB_STEP_SUMMARY echo "${{ steps.version_check.outputs.warning }}" >> $GITHUB_STEP_SUMMARY
- name: Generate release title
id: release_title
run: |
TAG_VERSION="${GITHUB_REF#refs/tags/}"
FROM_TAG="${{ steps.previoustag.outputs.previous_tag }}"
# Extract main feature types from commits
FEAT_COUNT=$(git log ${FROM_TAG}..HEAD --format="%s" --no-merges | grep -cE "^feat(\(.+\))?:" || true)
FIX_COUNT=$(git log ${FROM_TAG}..HEAD --format="%s" --no-merges | grep -cE "^fix(\(.+\))?:" || true)
# Build title based on what changed
if [ $FEAT_COUNT -gt 0 ] && [ $FIX_COUNT -gt 0 ]; then
TITLE="$TAG_VERSION - New Features & Bug Fixes"
elif [ $FEAT_COUNT -gt 0 ]; then
TITLE="$TAG_VERSION - New Features"
elif [ $FIX_COUNT -gt 0 ]; then
TITLE="$TAG_VERSION - Bug Fixes"
else
TITLE="$TAG_VERSION"
fi
echo "title=$TITLE" >> $GITHUB_OUTPUT
echo "Release title: $TITLE"
- name: Create GitHub Release - name: Create GitHub Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
with: with:
name: ${{ steps.release_title.outputs.title }} name: ${{ steps.release_notes.outputs.title }}
body: ${{ steps.release_notes.outputs.notes }} body: ${{ steps.release_notes.outputs.notes }}
draft: false draft: false
prerelease: false prerelease: false

View file

@ -269,6 +269,36 @@ End the output after the last release note item. Nothing more."
generate_with_gitcliff() { generate_with_gitcliff() {
log_info "${BLUE}==> Generating with git-cliff${NC}" log_info "${BLUE}==> Generating with git-cliff${NC}"
# Analyze commits to generate smart title
FROM_TAG_SHORT="${FROM_TAG}"
TO_TAG_SHORT="${TO_TAG}"
COMMITS_LOG=$(git log --pretty=format:"%s" "${FROM_TAG}..${TO_TAG}" 2>/dev/null || echo "")
# Count user-facing changes (exclude dev/ci/docs)
FEAT_COUNT=$(echo "$COMMITS_LOG" | grep -cE "^feat\((sensors|binary_sensor|config_flow|services|coordinator|api)\):" || true)
FIX_COUNT=$(echo "$COMMITS_LOG" | grep -cE "^fix\((sensors|binary_sensor|config_flow|services|coordinator|api|translations)\):" || true)
PERF_COUNT=$(echo "$COMMITS_LOG" | grep -cE "^perf\(" || true)
# Generate intelligent title based on changes
if [ $PERF_COUNT -gt 0 ]; then
TITLE="# Performance & Reliability Improvements"
elif [ $FEAT_COUNT -gt 2 ]; then
TITLE="# New Features & Enhancements"
elif [ $FEAT_COUNT -gt 0 ] && [ $FIX_COUNT -gt 0 ]; then
TITLE="# New Features & Bug Fixes"
elif [ $FEAT_COUNT -gt 0 ]; then
TITLE="# New Features"
elif [ $FIX_COUNT -gt 2 ]; then
TITLE="# Bug Fixes & Improvements"
elif [ $FIX_COUNT -gt 0 ]; then
TITLE="# Bug Fixes"
else
TITLE="# Release Updates"
fi
echo "$TITLE"
echo ""
# Create temporary cliff.toml if not exists # Create temporary cliff.toml if not exists
if [ ! -f "cliff.toml" ]; then if [ ! -f "cliff.toml" ]; then
cat > /tmp/cliff.toml <<'EOF' cat > /tmp/cliff.toml <<'EOF'
@ -325,6 +355,32 @@ generate_with_manual() {
exit 0 exit 0
fi fi
# Analyze commits to generate smart title
COMMITS_LOG=$(git log --pretty=format:"%s" "${FROM_TAG}..${TO_TAG}" 2>/dev/null || echo "")
# Count user-facing changes (exclude dev/ci/docs)
FEAT_COUNT=$(echo "$COMMITS_LOG" | grep -cE "^feat\((sensors|binary_sensor|config_flow|services|coordinator|api)\):" || true)
FIX_COUNT=$(echo "$COMMITS_LOG" | grep -cE "^fix\((sensors|binary_sensor|config_flow|services|coordinator|api|translations)\):" || true)
PERF_COUNT=$(echo "$COMMITS_LOG" | grep -cE "^perf\(" || true)
# Generate intelligent title based on changes
if [ $PERF_COUNT -gt 0 ]; then
echo "# Performance & Reliability Improvements"
elif [ $FEAT_COUNT -gt 2 ]; then
echo "# New Features & Enhancements"
elif [ $FEAT_COUNT -gt 0 ] && [ $FIX_COUNT -gt 0 ]; then
echo "# New Features & Bug Fixes"
elif [ $FEAT_COUNT -gt 0 ]; then
echo "# New Features"
elif [ $FIX_COUNT -gt 2 ]; then
echo "# Bug Fixes & Improvements"
elif [ $FIX_COUNT -gt 0 ]; then
echo "# Bug Fixes"
else
echo "# Release Updates"
fi
echo ""
# Create temporary files for each category # Create temporary files for each category
TMPDIR=$(mktemp -d) TMPDIR=$(mktemp -d)
FEAT_FILE="${TMPDIR}/feat" FEAT_FILE="${TMPDIR}/feat"
@ -382,42 +438,42 @@ generate_with_manual() {
# Output grouped by category # Output grouped by category
if [ -s "$FEAT_FILE" ]; then if [ -s "$FEAT_FILE" ]; then
echo "## 🎉 New Features" echo "### 🎉 New Features"
echo "" echo ""
cat "$FEAT_FILE" cat "$FEAT_FILE"
echo "" echo ""
fi fi
if [ -s "$FIX_FILE" ]; then if [ -s "$FIX_FILE" ]; then
echo "## 🐛 Bug Fixes" echo "### 🐛 Bug Fixes"
echo "" echo ""
cat "$FIX_FILE" cat "$FIX_FILE"
echo "" echo ""
fi fi
if [ -s "$DOCS_FILE" ]; then if [ -s "$DOCS_FILE" ]; then
echo "## 📚 Documentation" echo "### 📚 Documentation"
echo "" echo ""
cat "$DOCS_FILE" cat "$DOCS_FILE"
echo "" echo ""
fi fi
if [ -s "$REFACTOR_FILE" ]; then if [ -s "$REFACTOR_FILE" ]; then
echo "## 🔧 Maintenance & Refactoring" echo "### 🔧 Maintenance & Refactoring"
echo "" echo ""
cat "$REFACTOR_FILE" cat "$REFACTOR_FILE"
echo "" echo ""
fi fi
if [ -s "$TEST_FILE" ]; then if [ -s "$TEST_FILE" ]; then
echo "## 🧪 Testing" echo "### 🧪 Testing"
echo "" echo ""
cat "$TEST_FILE" cat "$TEST_FILE"
echo "" echo ""
fi fi
if [ -s "$OTHER_FILE" ]; then if [ -s "$OTHER_FILE" ]; then
echo "## 📝 Other Changes" echo "### 📝 Other Changes"
echo "" echo ""
cat "$OTHER_FILE" cat "$OTHER_FILE"
echo "" echo ""
@ -525,10 +581,10 @@ else
NOTES_BODY=$(cat "$TEMP_NOTES") NOTES_BODY=$(cat "$TEMP_NOTES")
fi fi
# Generate final title for GitHub release # Generate final title for GitHub release (without version tag - HACS adds it automatically)
if [ -n "$EXTRACTED_TITLE" ]; then if [ -n "$EXTRACTED_TITLE" ]; then
# AI provided a title, prepend version tag # Use the extracted title from release notes (no version prefix)
RELEASE_TITLE="$TO_TAG - $EXTRACTED_TITLE" RELEASE_TITLE="$EXTRACTED_TITLE"
else else
# Fallback: Keep current title if it looks meaningful # Fallback: Keep current title if it looks meaningful
# (more than just the tag itself) # (more than just the tag itself)
@ -541,15 +597,15 @@ else
DOCS_COUNT=$(echo "$NOTES_BODY" | grep -c "^### 📚 Documentation" || true) DOCS_COUNT=$(echo "$NOTES_BODY" | grep -c "^### 📚 Documentation" || true)
if [ "$FEAT_COUNT" -gt 0 ] && [ "$FIX_COUNT" -gt 0 ]; then if [ "$FEAT_COUNT" -gt 0 ] && [ "$FIX_COUNT" -gt 0 ]; then
RELEASE_TITLE="$TO_TAG - New Features & Bug Fixes" RELEASE_TITLE="New Features & Bug Fixes"
elif [ "$FEAT_COUNT" -gt 0 ]; then elif [ "$FEAT_COUNT" -gt 0 ]; then
RELEASE_TITLE="$TO_TAG - New Features" RELEASE_TITLE="New Features"
elif [ "$FIX_COUNT" -gt 0 ]; then elif [ "$FIX_COUNT" -gt 0 ]; then
RELEASE_TITLE="$TO_TAG - Bug Fixes" RELEASE_TITLE="Bug Fixes"
elif [ "$DOCS_COUNT" -gt 0 ]; then elif [ "$DOCS_COUNT" -gt 0 ]; then
RELEASE_TITLE="$TO_TAG - Documentation Updates" RELEASE_TITLE="Documentation Updates"
else else
RELEASE_TITLE="$TO_TAG - Updates" RELEASE_TITLE="Release Updates"
fi fi
fi fi
fi fi