worldhopper/scripts/generate-changelog.sh
Felipe M. 260ac28c7c
Some checks failed
Release / build (push) Failing after 1m19s
feat: migrate CI from Woodpecker to Forgejo Actions
2026-04-06 20:35:31 +02:00

131 lines
3.5 KiB
Shell
Executable file

#!/bin/bash
# Generate changelog from git history for CI releases
# Groups commits by conventional commit types (feat, fix, chore, refactor)
#
# Usage: ./generate-changelog.sh <tag> [output-file]
# tag: Git tag to generate changelog for (e.g., v1.0.0)
# output-file: Optional output file path (default: CHANGELOG.md)
set -e
# Check if tag argument is provided
if [ -z "$1" ]; then
echo "Error: Tag argument required"
echo "Usage: $0 <tag> [output-file]"
exit 1
fi
TAG="$1"
OUTPUT_FILE="${2:-CHANGELOG.md}"
echo "Generating changelog for ${TAG}..."
# Get previous tag (if exists)
PREV_TAG=$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || echo "")
if [ -z "$PREV_TAG" ]; then
echo "No previous tag found. This is the first release."
# Get the first commit in the repository
FIRST_COMMIT=$(git rev-list --max-parents=0 HEAD)
COMMIT_RANGE="${FIRST_COMMIT}..${TAG}"
echo "Generating changelog from first commit to ${TAG}"
else
COMMIT_RANGE="${PREV_TAG}..${TAG}"
echo "Generating changelog from ${PREV_TAG} to ${TAG}"
fi
# Initialize changelog file
echo "# Release ${TAG}" > "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
if [ -z "$PREV_TAG" ]; then
echo "First release of Worldhopper! 🎉" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
fi
# Get all commits in range
COMMITS=$(git log "${COMMIT_RANGE}" --pretty=format:"%H|%s" 2>/dev/null || echo "")
if [ -z "$COMMITS" ]; then
echo "No commits found in range" >> "$OUTPUT_FILE"
else
# Arrays to hold categorized commits
FEATURES=""
FIXES=""
CHORES=""
REFACTORS=""
OTHERS=""
# Parse commits and categorize
while IFS='|' read -r hash message; do
# Skip empty lines
[ -z "$hash" ] && continue
case "$message" in
feat:*|feat\(*)
FEATURES="${FEATURES}- ${message#feat:} (${hash:0:7})\n"
;;
fix:*|fix\(*)
FIXES="${FIXES}- ${message#fix:} (${hash:0:7})\n"
;;
chore:*|chore\(*)
CHORES="${CHORES}- ${message#chore:} (${hash:0:7})\n"
;;
refactor:*|refactor\(*)
REFACTORS="${REFACTORS}- ${message#refactor:} (${hash:0:7})\n"
;;
*)
OTHERS="${OTHERS}- ${message} (${hash:0:7})\n"
;;
esac
done <<< "$COMMITS"
# Write categorized sections
if [ -n "$FEATURES" ]; then
echo "## ✨ Features" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
echo -e "$FEATURES" >> "$OUTPUT_FILE"
fi
if [ -n "$FIXES" ]; then
echo "## 🐛 Bug Fixes" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
echo -e "$FIXES" >> "$OUTPUT_FILE"
fi
if [ -n "$REFACTORS" ]; then
echo "## ♻️ Refactoring" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
echo -e "$REFACTORS" >> "$OUTPUT_FILE"
fi
if [ -n "$CHORES" ]; then
echo "## 🔧 Chores" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
echo -e "$CHORES" >> "$OUTPUT_FILE"
fi
if [ -n "$OTHERS" ]; then
echo "## 📝 Other Changes" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
echo -e "$OTHERS" >> "$OUTPUT_FILE"
fi
fi
echo "" >> "$OUTPUT_FILE"
echo "---" >> "$OUTPUT_FILE"
# Add full changelog link if we have git forge info
if [ -n "$CI_FORGE_URL" ] && [ -n "$CI_REPO" ]; then
COMPARE_BASE="${PREV_TAG:-$(git rev-list --max-parents=0 HEAD | head -1)}"
echo "**Full Changelog**: ${CI_FORGE_URL}/${CI_REPO}/compare/${COMPARE_BASE}...${TAG}" >> "$OUTPUT_FILE"
elif [ -n "$PREV_TAG" ]; then
echo "**Commits**: \`git log ${PREV_TAG}..${TAG}\`" >> "$OUTPUT_FILE"
else
echo "**First Release**" >> "$OUTPUT_FILE"
fi
echo ""
echo "Changelog generated successfully: ${OUTPUT_FILE}"
echo ""
cat "$OUTPUT_FILE"