1- name : auto-release
1+ name : Auto Release
22
33on :
44 push :
1212 - " !.github/workflows/**"
1313
1414concurrency :
15- group : ${{ github.workflow }}
15+ group : ${{ github.workflow }}-main
1616 cancel-in-progress : false
1717
18+ permissions :
19+ contents : write
20+ actions : write
21+
1822jobs :
1923 auto-release :
20- name : Auto Release
24+ name : Auto Version Bump and Release
2125 runs-on : ubuntu-latest
22- if : " !contains(github.event.head_commit.message, 'release:') "
26+ if : ${{ !contains(github.event.head_commit.message, '[v') && github.event.head_commit.author.name != 'GitHub Action' && !contains(github.event.head_commit.message, '] [v') }}
2327 permissions :
2428 contents : write
25- pull-requests : read
29+ actions : write
30+
2631 steps :
27- - name : Checkout
32+ - name : Checkout code
2833 uses : actions/checkout@v4
2934 with :
3035 fetch-depth : 0
@@ -40,117 +45,133 @@ jobs:
4045
4146 - name : Configure Git
4247 run : |
43- git config --global user.name " github-actions[bot] "
44- git config --global user.email "github-actions[bot]@users.noreply.github.com "
48+ git config --local user.email "action@ github.com "
49+ git config --local user.name "GitHub Action "
4550
46- - name : Get latest release
47- id : latest_release
51+ - name : Get current version
52+ id : current_version
4853 run : |
49- # Get the latest release tag, fallback to package.json version if none exists
50- echo "All tags:"
51- git tag --sort=-version:refname
52- latest_tag=$(git tag --sort=-version:refname | head -n1)
53- if [ -z "$latest_tag" ]; then
54- pkg_version=$(node -p "require('./package.json').version")
55- latest_tag="v$pkg_version"
56- fi
57- echo "latest_tag=$latest_tag" >> $GITHUB_OUTPUT
58- echo "Latest release tag: $latest_tag"
54+ CURRENT_VERSION=$(node -p "require('./package.json').version")
55+ echo "current=${CURRENT_VERSION}" >> $GITHUB_OUTPUT
56+ echo "Current version: ${CURRENT_VERSION}"
5957
60- - name : Get commits since last release
61- id : commits
58+ - name : Determine version bump
59+ id : version_bump
6260 run : |
63- latest_tag="${{ steps.latest_release.outputs.latest_tag }}"
64- if git rev-parse "$latest_tag" >/dev/null 2>&1; then
65- # Tag exists, get commits since last release
66- commits =$(git log ${latest_tag}..HEAD --oneline -- pretty=format:"%s")
61+ LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
62+
63+ if [[ -z "$LAST_TAG" ]]; then
64+ COMMITS =$(git log -- pretty=format:"%s" --no-merges )
6765 else
68- # Tag does not exist, get all commits
69- commits=$(git log --oneline --pretty=format:"%s" | head -10)
66+ COMMITS=$(git log ${LAST_TAG}..HEAD --pretty=format:"%s" --no-merges)
7067 fi
7168
72- echo "Commits since $latest_tag:"
73- echo "$commits"
69+ BUMP_TYPE="patch"
7470
75- # Check if there are any commits to release
76- if [ -z "$commits" ]; then
77- echo "No new commits to release"
78- echo "should_release=false" >> $GITHUB_OUTPUT
79- exit 0
71+ if echo "$COMMITS" | grep -qiE "(BREAKING CHANGE|!:|breaking:|major:|bump.*major)"; then
72+ BUMP_TYPE="major"
73+ elif echo "$COMMITS" | grep -qiE "(feat:|feature:|minor:|bump.*minor)"; then
74+ BUMP_TYPE="minor"
75+ else
76+ BUMP_TYPE="patch"
8077 fi
8178
82- echo "should_release=true " >> $GITHUB_OUTPUT
79+ echo "bump_type=${BUMP_TYPE} " >> $GITHUB_OUTPUT
8380
84- - name : Determine version bump type
85- id : bump_type
86- if : steps.commits.outputs.should_release == 'true'
81+ - name : Bump version
82+ id : bump_version
8783 run : |
88- latest_tag="${{ steps.latest_release.outputs.latest_tag }}"
89- commits=$(git log ${latest_tag}..HEAD --oneline --pretty=format:"%s" || git log --oneline --pretty=format:"%s" | head -10)
90-
91- # Default to patch
92- bump_type="patch"
93-
94- # Check for breaking changes (major)
95- if echo "$commits" | grep -qE "^[^:]+!:|BREAKING CHANGE"; then
96- bump_type="major"
97- # Check for features (minor)
98- elif echo "$commits" | grep -qE "^feat(\(.+\))?:"; then
99- bump_type="minor"
100- # Check for fixes and other changes (patch)
101- elif echo "$commits" | grep -qE "^(fix|perf|refactor|style|docs|test|build|ci|chore)(\(.+\))?:"; then
102- bump_type="patch"
84+ CURRENT_VERSION="${{ steps.current_version.outputs.current }}"
85+ BUMP_TYPE="${{ steps.version_bump.outputs.bump_type }}"
86+
87+ IFS='.' read -ra VERSION_PARTS <<< "$CURRENT_VERSION"
88+ MAJOR=${VERSION_PARTS[0]}
89+ MINOR=${VERSION_PARTS[1]}
90+ PATCH=${VERSION_PARTS[2]}
91+
92+ case $BUMP_TYPE in
93+ "major")
94+ MAJOR=$((MAJOR + 1))
95+ MINOR=0
96+ PATCH=0
97+ ;;
98+ "minor")
99+ MINOR=$((MINOR + 1))
100+ PATCH=0
101+ ;;
102+ "patch")
103+ PATCH=$((PATCH + 1))
104+ ;;
105+ esac
106+
107+ NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
108+ echo "new_version=${NEW_VERSION}" >> $GITHUB_OUTPUT
109+ echo "tag=v${NEW_VERSION}" >> $GITHUB_OUTPUT
110+
111+ node -e "
112+ const fs = require('fs');
113+ const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
114+ pkg.version = '${NEW_VERSION}';
115+ fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
116+ "
117+
118+ - name : Collect commit messages for release
119+ id : commit_messages
120+ run : |
121+ LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
122+
123+ if [[ -z "$LAST_TAG" ]]; then
124+ COMMITS=$(git log --pretty=format:"- %s" --no-merges)
125+ else
126+ COMMITS=$(git log ${LAST_TAG}..HEAD --pretty=format:"- %s" --no-merges)
103127 fi
104128
105- echo "Determined bump type: $bump_type"
106- echo "bump_type=$bump_type" >> $GITHUB_OUTPUT
129+ echo "Raw commits:"
130+ echo "$COMMITS"
131+ COMMITS_ESCAPED=$(echo "$COMMITS" | sed ':a;N;$!ba;s/\n/\\n/g' | sed 's/"/\\"/g')
107132
108- - name : Bump version
109- id : version_bump
110- if : steps.commits.outputs.should_release == 'true'
111- run : |
112- bump_type="${{ steps.bump_type.outputs.bump_type }}"
133+ echo "commits<<EOF" >> $GITHUB_OUTPUT
134+ echo "$COMMITS" >> $GITHUB_OUTPUT
135+ echo "EOF" >> $GITHUB_OUTPUT
113136
114- # Get current version from package.json
115- current_version=$(node -p "require('./package.json').version")
116- echo "Current version: $current_version"
137+ echo "commits_json=$COMMITS_ESCAPED" >> $GITHUB_OUTPUT
117138
118- # Bump version using npm
119- npm version $bump_type --no-git-tag-version
139+ - name : Amend commit with version
140+ run : |
141+ NEW_VERSION="${{ steps.bump_version.outputs.new_version }}"
142+ CURRENT_MESSAGE=$(git log -1 --pretty=%B)
143+ NEW_MESSAGE="${CURRENT_MESSAGE} [v${NEW_VERSION}]"
120144
121- # Get new version
122- new_version=$(node -p "require('./package.json').version")
123- echo "New version: $new_version"
124- echo "new_version=$new_version" >> $GITHUB_OUTPUT
145+ git add package.json
146+ git commit --amend -m "${NEW_MESSAGE}"
147+ git push --force-with-lease origin main
125148
126- - name : Commit version bump and create tag
127- if : steps.commits.outputs.should_release == 'true'
149+ - name : Create tag and trigger release
128150 run : |
129- new_version="${{ steps.version_bump.outputs.new_version }}"
151+ TAG="${{ steps.bump_version.outputs.tag }}"
152+ NEW_VERSION="${{ steps.bump_version.outputs.new_version }}"
130153
131- # Commit the version bump
132- git add package.json
133- git commit -m "release: $new_version"
154+ # Create tag with commit messages
155+ COMMIT_MESSAGES="${{ steps.commit_messages.outputs.commits }}"
134156
135- # Website-related operations (commented out)
136- # npm run --prefix ./website new-release --release=$new_version
137- # git add -A .
157+ TAG_MESSAGE=$(printf "Release %s\n\nChanges in this release:\n%s" "${TAG}" "${COMMIT_MESSAGES}")
138158
139- # Create and push tag
140- git tag "v$new_version"
141- git push origin main
142- git push origin "v$new_version"
159+ git tag -a "${TAG}" -m "${TAG_MESSAGE}"
160+ git push origin "${TAG}"
143161
144- echo "Created and pushed tag v$new_version"
162+ COMMIT_MESSAGES_JSON="${{ steps.commit_messages.outputs.commits_json }}"
163+ curl -X POST \
164+ -H "Accept: application/vnd.github.v3+json" \
165+ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
166+ https://api.github.com/repos/${{ github.repository }}/dispatches \
167+ -d "{\"event_type\":\"release\",\"client_payload\":{\"tag\":\"${TAG}\",\"version\":\"${NEW_VERSION}\",\"commits\":\"${COMMIT_MESSAGES_JSON}\"}}"
145168
146- - name : Summary
169+ - name : Output summary
147170 run : |
148- if [ "${{ steps.commits.outputs.should_release }}" = "true" ]; then
149- echo "✅ Auto-release completed!"
150- echo "New version: ${{ steps.version_bump.outputs.new_version }}"
151- echo "Tag created: v${{ steps.version_bump.outputs.new_version }}"
152- echo ""
153- echo "The check and release workflows will now run automatically."
154- else
155- echo "ℹ️ No new commits to release - skipping auto-release"
156- fi
171+ echo "## 🚀 Auto Release Summary" >> $GITHUB_STEP_SUMMARY
172+ echo "- **Previous Version**: ${{ steps.current_version.outputs.current }}" >> $GITHUB_STEP_SUMMARY
173+ echo "- **New Version**: ${{ steps.bump_version.outputs.new_version }}" >> $GITHUB_STEP_SUMMARY
174+ echo "- **Bump Type**: ${{ steps.version_bump.outputs.bump_type }}" >> $GITHUB_STEP_SUMMARY
175+ echo "- **Tag**: ${{ steps.bump_version.outputs.tag }}" >> $GITHUB_STEP_SUMMARY
176+ echo "- **Commit**: Amended last commit with version info" >> $GITHUB_STEP_SUMMARY
177+ echo "- **Next Step**: Release workflow triggered via repository dispatch" >> $GITHUB_STEP_SUMMARY
0 commit comments