-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathgenerate-changelog.sh
More file actions
140 lines (123 loc) · 4.04 KB
/
generate-changelog.sh
File metadata and controls
140 lines (123 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/bin/bash
set -euo pipefail
# Usage: generate-changelog.sh <output_file> [tag_or_range]
# If tag_or_range is empty, generates from latest tag to HEAD
OUTPUT_FILE="$1"
TAG_OR_RANGE="${2:-}"
mkdir -p "$(dirname "$OUTPUT_FILE")"
if [[ -z "$TAG_OR_RANGE" ]]; then
LATEST_TAG=$(git describe --tags --abbrev=0 --match "v*.*.*" 2>/dev/null || echo "")
if [[ -z "$LATEST_TAG" ]]; then
LOG_RANGE=""
CONTEXT_MSG="All unreleased changes:"
VERSION_TITLE="Development Version"
else
LOG_RANGE="$LATEST_TAG..HEAD"
CONTEXT_MSG="Changes since $LATEST_TAG:"
VERSION_TITLE="Development Version"
fi
else
VERSION="$TAG_OR_RANGE"
PREVIOUS_TAG=$(git describe --tags --abbrev=0 --match "v*.*.*" "$TAG_OR_RANGE^" 2>/dev/null || echo "")
if [[ -z "$PREVIOUS_TAG" ]]; then
LOG_RANGE="$TAG_OR_RANGE"
CONTEXT_MSG="All changes in this release:"
else
LOG_RANGE="$PREVIOUS_TAG..$TAG_OR_RANGE"
CONTEXT_MSG="Changes since $PREVIOUS_TAG:"
fi
VERSION_TITLE="Version ${VERSION#v}"
fi
mapfile -t COMMITS < <(git log --pretty=format:'%H' $LOG_RANGE)
FEATURES=""
FIXES=""
MISC=""
for commit_hash in "${COMMITS[@]}"; do
commit_msg=$(git log -1 --pretty=format:'%s' "$commit_hash")
commit_body=$(git log -1 --pretty=format:'%b' "$commit_hash")
changelog_type=""
if echo "$commit_msg" | grep -iqE 'changelog[(: ]'; then
if echo "$commit_msg" | grep -iqE 'changelog\((feature|feat)\)'; then
changelog_type="feature"
elif echo "$commit_msg" | grep -iqE 'changelog\((fix)\)'; then
changelog_type="fix"
elif echo "$commit_msg" | grep -iqE 'changelog\((misc)\)'; then
changelog_type="misc"
fi
fi
if [ -z "$changelog_type" ]; then
if echo "$commit_body" | grep -iqE 'changelog[(: ]'; then
if echo "$commit_body" | grep -iqE 'changelog\((feature|feat)\)'; then
changelog_type="feature"
elif echo "$commit_body" | grep -iqE 'changelog\((fix)\)'; then
changelog_type="fix"
elif echo "$commit_body" | grep -iqE 'changelog\((misc)\)'; then
changelog_type="misc"
fi
fi
fi
if [ -z "$changelog_type" ]; then
if echo "$commit_msg" | grep -iqE '^(feat|feature)(\(.*\))?:'; then
changelog_type="feature"
commit_msg=$(echo "$commit_msg" | sed -E 's/^(feat|feature)(\(.*\))?:[[:space:]]*//')
elif echo "$commit_msg" | grep -iqE '^fix(\(.*\))?:'; then
changelog_type="fix"
commit_msg=$(echo "$commit_msg" | sed -E 's/^fix(\(.*\))?:[[:space:]]*//')
elif echo "$commit_msg" | grep -iqE '^(chore|docs|style|refactor|perf|test)(\(.*\))?:'; then
changelog_type="misc"
commit_msg=$(echo "$commit_msg" | sed -E 's/^(chore|docs|style|refactor|perf|test)(\(.*\))?:[[:space:]]*//')
fi
fi
if [ -n "$changelog_type" ]; then
body_content=$(echo "$commit_body" | awk 'BEGIN{IGNORECASE=1} !/changelog[(: ]/ && NF')
entry="- $commit_msg"
if [ -n "$body_content" ]; then
entry=$(printf "%s\n%s" "$entry" "$(echo "$body_content" | sed 's/^/ /')")
fi
if [ "$changelog_type" = "feature" ]; then
FEATURES=$(printf "%s\n%s" "$FEATURES" "$entry")
elif [ "$changelog_type" = "fix" ]; then
FIXES=$(printf "%s\n%s" "$FIXES" "$entry")
else
MISC=$(printf "%s\n%s" "$MISC" "$entry")
fi
fi
done
{
echo "# Changelog for $VERSION_TITLE"
echo ""
if [[ -z "$TAG_OR_RANGE" ]]; then
echo "This page shows unreleased changes in the development version."
else
echo "Release Date: $(date +'%Y-%m-%d')"
fi
echo ""
echo "$CONTEXT_MSG"
echo ""
if [[ -n "$FEATURES" ]]; then
echo "## ✨ New Features"
echo ""
echo "$FEATURES"
echo ""
fi
if [[ -n "$FIXES" ]]; then
echo "## 🐛 Fixes"
echo ""
echo "$FIXES"
echo ""
fi
if [[ -n "$MISC" ]]; then
echo "## 🔧 Miscellaneous"
echo ""
echo "$MISC"
echo ""
fi
if [[ -z "$FEATURES" && -z "$FIXES" && -z "$MISC" ]]; then
if [[ -z "$TAG_OR_RANGE" ]]; then
echo "No changes yet."
else
echo "No changes."
fi
fi
} > "$OUTPUT_FILE"
echo "Changelog generated: $OUTPUT_FILE"