1
+ name : Update Stable Branch
2
+
3
+ on :
4
+ push :
5
+ branches :
6
+ - main
7
+
8
+ permissions :
9
+ contents : write
10
+
11
+ jobs :
12
+ update-commit :
13
+ if : contains(github.event.head_commit.message, '#release')
14
+ runs-on : ubuntu-latest
15
+
16
+ steps :
17
+ - name : Checkout the code
18
+ uses : actions/checkout@v3
19
+
20
+ - name : Get the latest commit hash
21
+ run : echo "COMMIT_HASH=$(git rev-parse HEAD)" >> $GITHUB_ENV
22
+
23
+ - name : Update commit file
24
+ run : |
25
+ echo "{ \"commit\": \"$COMMIT_HASH\" }" > app/commit.json
26
+
27
+ - name : Commit and push the update
28
+ run : |
29
+ git config --global user.name "github-actions[bot]"
30
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
31
+ git add app/commit.json
32
+ git commit -m "chore: update commit hash to $COMMIT_HASH"
33
+ git push
34
+ prepare-release :
35
+ needs : update-commit
36
+ if : contains(github.event.head_commit.message, '#release')
37
+ runs-on : ubuntu-latest
38
+
39
+ steps :
40
+ - uses : actions/checkout@v4
41
+ with :
42
+ fetch-depth : 0
43
+
44
+ - name : Configure Git
45
+ run : |
46
+ git config --global user.name 'github-actions[bot]'
47
+ git config --global user.email 'github-actions[bot]@users.noreply.github.com'
48
+
49
+ - name : Setup Node.js
50
+ uses : actions/setup-node@v4
51
+ with :
52
+ node-version : ' 20'
53
+
54
+ - name : Install pnpm
55
+ uses : pnpm/action-setup@v2
56
+ with :
57
+ version : latest
58
+ run_install : false
59
+
60
+ - name : Get pnpm store directory
61
+ id : pnpm-cache
62
+ shell : bash
63
+ run : |
64
+ echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
65
+
66
+ - name : Setup pnpm cache
67
+ uses : actions/cache@v4
68
+ with :
69
+ path : ${{ steps.pnpm-cache.outputs.STORE_PATH }}
70
+ key : ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
71
+ restore-keys : |
72
+ ${{ runner.os }}-pnpm-store-
73
+
74
+ - name : Get Current Version
75
+ id : current_version
76
+ run : |
77
+ CURRENT_VERSION=$(node -p "require('./package.json').version")
78
+ echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
79
+
80
+ - name : Install semver
81
+ run : pnpm add -g semver
82
+
83
+ - name : Determine Version Bump
84
+ id : version_bump
85
+ run : |
86
+ COMMIT_MSG="${{ github.event.head_commit.message }}"
87
+ if [[ $COMMIT_MSG =~ "#release:major" ]]; then
88
+ echo "bump=major" >> $GITHUB_OUTPUT
89
+ elif [[ $COMMIT_MSG =~ "#release:minor" ]]; then
90
+ echo "bump=minor" >> $GITHUB_OUTPUT
91
+ else
92
+ echo "bump=patch" >> $GITHUB_OUTPUT
93
+ fi
94
+
95
+ - name : Bump Version
96
+ id : bump_version
97
+ run : |
98
+ NEW_VERSION=$(semver -i ${{ steps.version_bump.outputs.bump }} ${{ steps.current_version.outputs.version }})
99
+ echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
100
+
101
+ - name : Update Package.json
102
+ run : |
103
+ NEW_VERSION=${{ steps.bump_version.outputs.new_version }}
104
+ pnpm version $NEW_VERSION --no-git-tag-version --allow-same-version
105
+
106
+ - name : Generate Changelog
107
+ id : changelog
108
+ run : |
109
+ # Get the latest tag
110
+ LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
111
+
112
+ # Start changelog file
113
+ echo "# Release v${{ steps.bump_version.outputs.new_version }}" > changelog.md
114
+ echo "" >> changelog.md
115
+
116
+ if [ -z "$LATEST_TAG" ]; then
117
+ echo "### 🎉 First Release" >> changelog.md
118
+ echo "" >> changelog.md
119
+ COMPARE_BASE="$(git rev-list --max-parents=0 HEAD)"
120
+ else
121
+ echo "### 🔄 Changes since $LATEST_TAG" >> changelog.md
122
+ echo "" >> changelog.md
123
+ COMPARE_BASE="$LATEST_TAG"
124
+ fi
125
+
126
+ # Function to extract conventional commit type
127
+ get_commit_type() {
128
+ if [[ $1 =~ ^feat:|^feature: ]]; then echo "✨ Features";
129
+ elif [[ $1 =~ ^fix: ]]; then echo "🐛 Bug Fixes";
130
+ elif [[ $1 =~ ^docs: ]]; then echo "📚 Documentation";
131
+ elif [[ $1 =~ ^style: ]]; then echo "💎 Styles";
132
+ elif [[ $1 =~ ^refactor: ]]; then echo "♻️ Code Refactoring";
133
+ elif [[ $1 =~ ^perf: ]]; then echo "⚡️ Performance Improvements";
134
+ elif [[ $1 =~ ^test: ]]; then echo "✅ Tests";
135
+ elif [[ $1 =~ ^build: ]]; then echo "🛠️ Build System";
136
+ elif [[ $1 =~ ^ci: ]]; then echo "⚙️ CI";
137
+ elif [[ $1 =~ ^chore: ]]; then echo "🔧 Chores";
138
+ else echo "🔍 Other Changes";
139
+ fi
140
+ }
141
+
142
+ # Generate categorized changelog
143
+ declare -A CATEGORIES
144
+ declare -A COMMITS_BY_CATEGORY
145
+
146
+ # Get commits since last tag or all commits if no tag exists
147
+ while IFS= read -r commit_line; do
148
+ HASH=$(echo "$commit_line" | cut -d'|' -f1)
149
+ MSG=$(echo "$commit_line" | cut -d'|' -f2)
150
+ PR_NUM=$(echo "$commit_line" | cut -d'|' -f3)
151
+
152
+ CATEGORY=$(get_commit_type "$MSG")
153
+ CATEGORIES["$CATEGORY"]=1
154
+
155
+ # Format commit message with PR link if available
156
+ if [ -n "$PR_NUM" ]; then
157
+ COMMITS_BY_CATEGORY["$CATEGORY"]+="- ${MSG#*: } ([#$PR_NUM](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/pull/$PR_NUM))"$'\n'
158
+ else
159
+ COMMITS_BY_CATEGORY["$CATEGORY"]+="- ${MSG#*: }"$'\n'
160
+ fi
161
+ done < <(git log "${COMPARE_BASE}..HEAD" --pretty=format:"%H|%s|%(trailers:key=PR-Number,valueonly)" --reverse)
162
+
163
+ # Write categorized commits to changelog
164
+ for category in "✨ Features" "🐛 Bug Fixes" "📚 Documentation" "💎 Styles" "♻️ Code Refactoring" "⚡️ Performance Improvements" "✅ Tests" "🛠️ Build System" "⚙️ CI" "🔧 Chores" "🔍 Other Changes"; do
165
+ if [ -n "${COMMITS_BY_CATEGORY[$category]}" ]; then
166
+ echo "#### $category" >> changelog.md
167
+ echo "" >> changelog.md
168
+ echo "${COMMITS_BY_CATEGORY[$category]}" >> changelog.md
169
+ echo "" >> changelog.md
170
+ fi
171
+ done
172
+
173
+ # Add compare link if not first release
174
+ if [ -n "$LATEST_TAG" ]; then
175
+ echo "**Full Changelog**: [\`$LATEST_TAG..v${{ steps.bump_version.outputs.new_version }}\`](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/compare/$LATEST_TAG...v${{ steps.bump_version.outputs.new_version }})" >> changelog.md
176
+ fi
177
+
178
+ # Save changelog content for the release
179
+ CHANGELOG_CONTENT=$(cat changelog.md)
180
+ echo "content<<EOF" >> $GITHUB_OUTPUT
181
+ echo "$CHANGELOG_CONTENT" >> $GITHUB_OUTPUT
182
+ echo "EOF" >> $GITHUB_OUTPUT
183
+
184
+ - name : Commit and Tag Release
185
+ run : |
186
+ git pull
187
+ git add package.json pnpm-lock.yaml changelog.md
188
+ git commit -m "chore: release version ${{ steps.bump_version.outputs.new_version }}"
189
+ git tag "v${{ steps.bump_version.outputs.new_version }}"
190
+ git push
191
+ git push --tags
192
+
193
+ - name : Update Stable Branch
194
+ run : |
195
+ if ! git checkout stable 2>/dev/null; then
196
+ echo "Creating new stable branch..."
197
+ git checkout -b stable
198
+ fi
199
+ git merge main --no-ff -m "chore: release version ${{ steps.bump_version.outputs.new_version }}"
200
+ git push --set-upstream origin stable --force
201
+
202
+ - name : Create GitHub Release
203
+ env :
204
+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
205
+ run : |
206
+ VERSION="v${{ steps.bump_version.outputs.new_version }}"
207
+ gh release create "$VERSION" \
208
+ --title "Release $VERSION" \
209
+ --notes "${{ steps.changelog.outputs.content }}" \
210
+ --target stable
0 commit comments