- Add .woodpecker.yml configuration for tag-triggered builds - Create scripts/generate-changelog.sh for grouped changelog generation - Create scripts/create-release.sh for Forgejo release publishing - Add comprehensive scripts/README.md with usage examples Pipeline triggers on version tags (v*.*.*) and performs: 1. Build release APK with Flutter 2. Generate grouped changelog from conventional commits 3. Create Forgejo release with APK attachment and changelog Scripts are standalone and can be run locally for testing. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
131 lines
3.5 KiB
Shell
Executable file
131 lines
3.5 KiB
Shell
Executable file
#!/bin/bash
|
|
# Generate changelog from git history for Woodpecker 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"
|