Skip to content

Commit a279a6a

Browse files
authored
Correct versioning in releases (Audionut#644)
1 parent 4fd098d commit a279a6a

File tree

2 files changed

+265
-77
lines changed

2 files changed

+265
-77
lines changed

.github/workflows/docker-image.yml

Lines changed: 30 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -14,119 +14,72 @@ jobs:
1414
build-and-push-image:
1515
runs-on: ubuntu-latest
1616
permissions:
17-
contents: write
17+
contents: read
1818
packages: write
1919

2020
steps:
2121
- name: Checkout repository
22-
uses: actions/checkout@v3
23-
with:
24-
fetch-depth: 0 # Ensures we get all history for tag retrieval
22+
uses: actions/checkout@v4
2523

2624
- name: Set up QEMU
27-
uses: docker/setup-qemu-action@v2
25+
uses: docker/setup-qemu-action@v3
2826

2927
- name: Set up Docker Buildx
30-
uses: docker/setup-buildx-action@v2
28+
uses: docker/setup-buildx-action@v3
3129

3230
- name: Log in to the Container registry
33-
uses: docker/login-action@v2
31+
uses: docker/login-action@v3
3432
with:
3533
registry: ${{ env.REGISTRY }}
3634
username: ${{ github.actor }}
3735
password: ${{ secrets.GITHUB_TOKEN }}
3836

39-
- name: Extract metadata (tags, labels) for Docker
40-
id: meta
41-
uses: docker/metadata-action@v4
42-
with:
43-
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
44-
4537
- name: Get lowercase repo name
46-
id: get_lowercase_repo_name
4738
run: |
4839
REPO_NAME=${{ env.IMAGE_NAME }}
4940
echo "LOWER_CASE_REPO_NAME=${REPO_NAME,,}" >> $GITHUB_ENV
5041
51-
- name: Get release version or branch name
52-
id: get_version_or_branch
42+
- name: Get version for tagging
5343
run: |
5444
if [ "${{ github.event_name }}" == "release" ]; then
5545
RELEASE_VERSION="${{ github.event.release.tag_name }}"
56-
if [ -z "$RELEASE_VERSION" ]; then
57-
echo "Error: RELEASE_VERSION is empty. Ensure a valid release tag."
58-
exit 1
59-
fi
6046
echo "VERSION=${RELEASE_VERSION}" >> $GITHUB_ENV
61-
echo "UPDATE_VERSION=true" >> $GITHUB_ENV
6247
elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
6348
BRANCH_NAME="${{ github.ref_name }}"
6449
echo "VERSION=${BRANCH_NAME}" >> $GITHUB_ENV
65-
echo "UPDATE_VERSION=false" >> $GITHUB_ENV
66-
else
67-
echo "Unsupported event: ${{ github.event_name }}"
68-
exit 1
6950
fi
7051
71-
- name: Get release notes (only for release events)
72-
if: github.event_name == 'release'
73-
id: get_release_info
74-
run: |
75-
cat << 'RELEASE_NOTES_EOF' >> $GITHUB_ENV
76-
RELEASE_NOTES<<EOF
77-
${{ github.event.release.body }}
78-
EOF
79-
RELEASE_NOTES_EOF
80-
81-
- name: Update version.py (only on release)
82-
if: github.event_name == 'release' && env.UPDATE_VERSION == 'true'
83-
run: |
84-
TIMESTAMP=$(date +"%Y-%m-%d")
85-
VERSION_FILE="data/version.py"
86-
87-
# Create version.py if it doesn't exist
88-
if [ ! -f "$VERSION_FILE" ]; then
89-
echo "__version__ = \"0.0.0\"" > "$VERSION_FILE"
90-
echo "" >> "$VERSION_FILE"
91-
fi
92-
93-
# Prepend new release info
94-
TEMP_FILE=$(mktemp)
95-
echo "__version__ = \"${{ env.VERSION }}\"" > "$TEMP_FILE"
96-
echo "" >> "$TEMP_FILE"
97-
echo "\"\"\"" >> "$TEMP_FILE"
98-
echo "Changelog for version ${{ env.VERSION }} ($TIMESTAMP):" >> "$TEMP_FILE"
99-
echo "" >> "$TEMP_FILE"
100-
echo "${{ env.RELEASE_NOTES }}" >> "$TEMP_FILE"
101-
echo "\"\"\"" >> "$TEMP_FILE"
102-
echo "" >> "$TEMP_FILE"
103-
cat "$VERSION_FILE" >> "$TEMP_FILE"
104-
mv "$TEMP_FILE" "$VERSION_FILE"
105-
106-
- name: Commit and push version update (only on release)
107-
if: github.event_name == 'release' && env.UPDATE_VERSION == 'true'
108-
run: |
109-
git checkout master # Ensure we're on master branch
110-
git config --global user.name "github-actions[bot]"
111-
git config --global user.email "github-actions[bot]@users.noreply.github.com"
112-
git add data/version.py
113-
git commit -m "Update version.py to ${{ env.VERSION }} with changelog"
114-
git push origin master
115-
116-
- name: Debug VERSION and UPDATE_VERSION
117-
run: |
118-
echo "VERSION=${{ env.VERSION }}"
119-
echo "UPDATE_VERSION=${{ env.UPDATE_VERSION }}"
52+
- name: Extract metadata (tags, labels) for Docker
53+
id: meta
54+
uses: docker/metadata-action@v5
55+
with:
56+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
57+
tags: |
58+
type=ref,event=branch
59+
type=ref,event=tag
60+
type=raw,value=latest,enable={{is_default_branch}}
12061
12162
- name: Build and push Docker image
122-
uses: docker/build-push-action@v4
63+
uses: docker/build-push-action@v5
12364
with:
12465
context: .
12566
platforms: linux/amd64,linux/arm64
12667
push: true
12768
tags: |
12869
${{ env.REGISTRY }}/${{ env.LOWER_CASE_REPO_NAME }}:${{ env.VERSION }}
129-
${{ steps.meta.outputs.tags }}
70+
${{ env.REGISTRY }}/${{ env.LOWER_CASE_REPO_NAME }}:latest
13071
labels: ${{ steps.meta.outputs.labels }}
13172
cache-from: type=gha
132-
cache-to: type=gha,mode=max
73+
cache-to: type=gha,mode=max
74+
75+
- name: Output build information
76+
run: |
77+
echo "✅ Docker images built and pushed successfully!"
78+
echo "🐋 Images:"
79+
echo " - ${{ env.REGISTRY }}/${{ env.LOWER_CASE_REPO_NAME }}:${{ env.VERSION }}"
80+
echo " - ${{ env.REGISTRY }}/${{ env.LOWER_CASE_REPO_NAME }}:latest"
81+
if [ "${{ github.event_name }}" == "release" ]; then
82+
echo "📝 Triggered by release: ${{ github.event.release.tag_name }}"
83+
else
84+
echo "📝 Triggered by manual workflow dispatch on branch: ${{ github.ref_name }}"
85+
fi
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
name: Create Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Release version (e.g., v1.2.3)'
8+
required: true
9+
type: string
10+
previous_version:
11+
description: 'Previous version for changelog (leave empty for auto-detect)'
12+
required: false
13+
type: string
14+
15+
jobs:
16+
create-release:
17+
runs-on: ubuntu-latest
18+
permissions:
19+
contents: write
20+
21+
steps:
22+
- name: Checkout repository
23+
uses: actions/checkout@v4
24+
with:
25+
fetch-depth: 0 # Get full history for changelog generation
26+
token: ${{ secrets.GITHUB_TOKEN }}
27+
28+
- name: Validate version format
29+
run: |
30+
VERSION="${{ github.event.inputs.version }}"
31+
if [[ ! $VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
32+
echo "❌ Invalid version format. Use format: v1.2.3"
33+
exit 1
34+
fi
35+
echo "VERSION=${VERSION}" >> $GITHUB_ENV
36+
echo "VERSION_NUMBER=${VERSION#v}" >> $GITHUB_ENV
37+
38+
- name: Check if tag already exists
39+
run: |
40+
if git tag -l "${{ env.VERSION }}" | grep -q "${{ env.VERSION }}"; then
41+
echo "❌ Tag ${{ env.VERSION }} already exists!"
42+
exit 1
43+
fi
44+
45+
- name: Get previous tag for changelog
46+
run: |
47+
if [ -n "${{ github.event.inputs.previous_version }}" ]; then
48+
PREVIOUS_TAG="${{ github.event.inputs.previous_version }}"
49+
else
50+
PREVIOUS_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
51+
fi
52+
53+
if [ -z "$PREVIOUS_TAG" ]; then
54+
echo "PREVIOUS_TAG=initial" >> $GITHUB_ENV
55+
else
56+
echo "PREVIOUS_TAG=${PREVIOUS_TAG}" >> $GITHUB_ENV
57+
fi
58+
echo "📝 Previous tag: ${PREVIOUS_TAG:-'none (first release)'}"
59+
60+
- name: Generate changelog from merged PRs and commits
61+
run: |
62+
if [ "${{ env.PREVIOUS_TAG }}" = "initial" ]; then
63+
# For first release, get all commits since beginning
64+
COMMIT_RANGE=""
65+
else
66+
# Get commits since previous tag
67+
COMMIT_RANGE="${{ env.PREVIOUS_TAG }}..HEAD"
68+
fi
69+
70+
# Create changelog
71+
{
72+
echo "CHANGELOG<<EOF"
73+
echo "## What's Changed"
74+
echo ""
75+
76+
# Get commits in chronological order
77+
if [ -z "$COMMIT_RANGE" ]; then
78+
COMMITS=$(git log --pretty=format:"%H|%an|%s" --reverse)
79+
else
80+
COMMITS=$(git log $COMMIT_RANGE --pretty=format:"%H|%an|%s" --reverse)
81+
fi
82+
83+
# Track if we found any changes
84+
FOUND_CHANGES=false
85+
86+
# Process each commit
87+
echo "$COMMITS" | while IFS='|' read -r COMMIT_HASH AUTHOR SUBJECT; do
88+
# Skip empty lines
89+
[ -z "$COMMIT_HASH" ] && continue
90+
91+
# Handle PR merge commits
92+
if [[ $SUBJECT =~ ^Merge\ pull\ request\ #([0-9]+)\ from\ (.+) ]]; then
93+
PR_NUMBER="${BASH_REMATCH[1]}"
94+
BRANCH_INFO="${BASH_REMATCH[2]}"
95+
96+
# Get PR title from GitHub API
97+
PR_TITLE=$(curl -s \
98+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
99+
-H "Accept: application/vnd.github.v3+json" \
100+
"https://api.github.com/repos/${{ github.repository }}/pulls/${PR_NUMBER}" \
101+
| jq -r '.title // empty')
102+
103+
# Get PR author from GitHub API
104+
PR_AUTHOR=$(curl -s \
105+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
106+
-H "Accept: application/vnd.github.v3+json" \
107+
"https://api.github.com/repos/${{ github.repository }}/pulls/${PR_NUMBER}" \
108+
| jq -r '.user.login // empty')
109+
110+
# Use PR title if available, otherwise use branch name
111+
if [ -n "$PR_TITLE" ] && [ "$PR_TITLE" != "null" ]; then
112+
TITLE="$PR_TITLE"
113+
else
114+
# Clean up branch name for display
115+
TITLE=$(echo "$BRANCH_INFO" | sed 's|.*/||' | sed 's|-| |g' | sed 's/_/ /g')
116+
fi
117+
118+
# Use PR author if available, otherwise use commit author
119+
if [ -n "$PR_AUTHOR" ] && [ "$PR_AUTHOR" != "null" ]; then
120+
DISPLAY_AUTHOR="@$PR_AUTHOR"
121+
else
122+
DISPLAY_AUTHOR="@$AUTHOR"
123+
fi
124+
125+
echo "* ${TITLE} by ${DISPLAY_AUTHOR} in https://github.com/${{ github.repository }}/pull/${PR_NUMBER}"
126+
FOUND_CHANGES=true
127+
128+
# Handle direct branch merges
129+
elif [[ $SUBJECT =~ ^Merge\ branch\ \'([^\']+)\' ]]; then
130+
BRANCH_NAME="${BASH_REMATCH[1]}"
131+
132+
# Clean up branch name for display
133+
CLEAN_BRANCH=$(echo "$BRANCH_NAME" | sed 's|-| |g' | sed 's/_/ /g')
134+
135+
echo "* Merge branch '${BRANCH_NAME}' by @${AUTHOR}"
136+
FOUND_CHANGES=true
137+
138+
# Handle direct commits (non-merge commits that might be significant)
139+
elif [[ ! $SUBJECT =~ ^Merge ]]; then
140+
# Skip version update commits and other automated commits
141+
if [[ ! $SUBJECT =~ ^Update\ version\.py ]] && [[ ! $SUBJECT =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] && [[ ! $AUTHOR =~ github-actions ]]; then
142+
# Only include if it looks like a meaningful change
143+
if [[ $SUBJECT =~ ^(feat|fix|add|update|improve|remove|refactor): ]] || [[ ${#SUBJECT} -gt 10 ]]; then
144+
echo "* ${SUBJECT} by @${AUTHOR} in ${COMMIT_HASH:0:7}"
145+
FOUND_CHANGES=true
146+
fi
147+
fi
148+
fi
149+
done
150+
151+
# If no changes found, add default message
152+
if [ "$FOUND_CHANGES" = false ]; then
153+
echo "* Other minor updates and improvements"
154+
fi
155+
156+
echo ""
157+
if [ "${{ env.PREVIOUS_TAG }}" != "initial" ]; then
158+
echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ env.PREVIOUS_TAG }}...${{ env.VERSION }}"
159+
else
160+
echo "**Full Changelog**: https://github.com/${{ github.repository }}/commits/${{ env.VERSION }}"
161+
fi
162+
echo "EOF"
163+
} >> $GITHUB_ENV
164+
165+
- name: Update version.py
166+
run: |
167+
TIMESTAMP=$(date +"%Y-%m-%d")
168+
VERSION_FILE="data/version.py"
169+
170+
# Create version.py if it doesn't exist
171+
if [ ! -f "$VERSION_FILE" ]; then
172+
echo "__version__ = \"0.0.0\"" > "$VERSION_FILE"
173+
echo "" >> "$VERSION_FILE"
174+
fi
175+
176+
# Prepend new release info
177+
TEMP_FILE=$(mktemp)
178+
echo "__version__ = \"${{ env.VERSION }}\"" > "$TEMP_FILE"
179+
echo "" >> "$TEMP_FILE"
180+
echo "\"\"\"" >> "$TEMP_FILE"
181+
echo "Release Notes for version ${{ env.VERSION }} ($TIMESTAMP):" >> "$TEMP_FILE"
182+
echo "" >> "$TEMP_FILE"
183+
echo "${{ env.CHANGELOG }}" | sed 's/^/# /' >> "$TEMP_FILE"
184+
echo "\"\"\"" >> "$TEMP_FILE"
185+
echo "" >> "$TEMP_FILE"
186+
187+
# Skip the first line of existing version.py (old __version__)
188+
if [ -f "$VERSION_FILE" ]; then
189+
tail -n +2 "$VERSION_FILE" >> "$TEMP_FILE"
190+
fi
191+
mv "$TEMP_FILE" "$VERSION_FILE"
192+
193+
- name: Commit version update
194+
run: |
195+
git config --global user.name "github-actions[bot]"
196+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
197+
git add data/version.py
198+
199+
# Check if there are changes to commit
200+
if git diff --staged --quiet; then
201+
echo "No changes to commit"
202+
else
203+
git commit -m "${{ env.VERSION }}"
204+
echo "✅ Committed version.py update with message: ${{ env.VERSION }}"
205+
fi
206+
207+
- name: Create and push tag
208+
run: |
209+
# Create the tag on the commit that includes the version update
210+
git tag -a "${{ env.VERSION }}" -m "Release ${{ env.VERSION }}"
211+
212+
# Push the commit and tag
213+
git push origin HEAD:${{ github.event.repository.default_branch }}
214+
git push origin "${{ env.VERSION }}"
215+
216+
echo "✅ Created and pushed tag: ${{ env.VERSION }}"
217+
218+
- name: Create GitHub Release
219+
uses: softprops/action-gh-release@v1
220+
with:
221+
tag_name: ${{ env.VERSION }}
222+
name: "Release ${{ env.VERSION }}"
223+
body: ${{ env.CHANGELOG }}
224+
draft: false
225+
prerelease: false
226+
generate_release_notes: false # Use only our custom changelog
227+
env:
228+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
229+
230+
- name: Output release information
231+
run: |
232+
echo "✅ Release ${{ env.VERSION }} created successfully!"
233+
echo "📝 Release URL: https://github.com/${{ github.repository }}/releases/tag/${{ env.VERSION }}"
234+
echo "📄 Version file updated and committed with tag: ${{ env.VERSION }}"
235+
echo "🏷️ Tag includes the version commit"

0 commit comments

Comments
 (0)