Skip to content

Commit 84817ed

Browse files
ci: fix rc versioning logic and artifact packaging in release workflows (#547)
1 parent 724fc98 commit 84817ed

5 files changed

Lines changed: 186 additions & 129 deletions

File tree

.github/workflows/Engine-CI.yml

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
on:
22
push:
3-
branches: [ master, develop, arena-integration ]
3+
branches: [ master, develop ]
44
pull_request:
5-
branches: [ master, develop, arena-integration ]
5+
branches: [ master, develop ]
66

77
jobs:
88
commitlint:
@@ -12,7 +12,7 @@ jobs:
1212
clang-format:
1313
strategy:
1414
matrix:
15-
directories: [ZEngine, Tetragrama, Obelisk]
15+
directories: [ZEngine, Tetragrama, Obelisk, Resources/Shaders]
1616
uses: ./.github/workflows/job-clangformat.yml
1717
with:
1818
srcDirectory: ${{ matrix.directories }}
@@ -37,3 +37,90 @@ jobs:
3737
uses: ./.github/workflows/linux-build.yml
3838
with:
3939
targetFramework: net8.0
40+
41+
publish-prerelease:
42+
needs: [windows, macOS, linux]
43+
if: ${{ !failure() && !cancelled() && github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
44+
runs-on: ubuntu-latest
45+
permissions:
46+
contents: write
47+
steps:
48+
- uses: actions/checkout@v4
49+
with:
50+
fetch-depth: 0
51+
52+
- name: Check for rc tag on HEAD
53+
id: check-tag
54+
run: |
55+
git fetch --tags --quiet
56+
TAG="$(git tag --points-at HEAD | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$' | head -1 || true)"
57+
if [ -z "$TAG" ]; then
58+
echo "No rc tag on HEAD — skipping publish."
59+
echo "skipped=true" >> "$GITHUB_OUTPUT"
60+
else
61+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
62+
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
63+
echo "skipped=false" >> "$GITHUB_OUTPUT"
64+
fi
65+
66+
- name: Generate release notes
67+
if: steps.check-tag.outputs.skipped != 'true'
68+
run: |
69+
PREV_TAG="$(git describe --tags --abbrev=0 "${{ steps.check-tag.outputs.tag }}^" 2>/dev/null || echo "")"
70+
bash Scripts/generate-changelog.sh \
71+
"$PREV_TAG" \
72+
"${{ steps.check-tag.outputs.tag }}" \
73+
"${{ steps.check-tag.outputs.version }}" > /tmp/release-notes.md
74+
75+
- name: Download Windows artifact
76+
if: steps.check-tag.outputs.skipped != 'true'
77+
uses: actions/download-artifact@v6
78+
with:
79+
name: Windows-x64-Release
80+
path: artifacts/Windows-x64-Release
81+
82+
- name: Download macOS x64 artifact
83+
if: steps.check-tag.outputs.skipped != 'true'
84+
uses: actions/download-artifact@v6
85+
with:
86+
name: macOS-x64-Release
87+
path: artifacts/macOS-x64-Release
88+
89+
- name: Download macOS arm64 artifact
90+
if: steps.check-tag.outputs.skipped != 'true'
91+
uses: actions/download-artifact@v6
92+
with:
93+
name: macOS-arm64-Release
94+
path: artifacts/macOS-arm64-Release
95+
96+
- name: Download Linux artifact
97+
if: steps.check-tag.outputs.skipped != 'true'
98+
uses: actions/download-artifact@v6
99+
with:
100+
name: linux-Release
101+
path: artifacts/linux-Release
102+
103+
- name: Package artifacts
104+
if: steps.check-tag.outputs.skipped != 'true'
105+
run: |
106+
VERSION="${{ steps.check-tag.outputs.version }}"
107+
cd artifacts
108+
zip -r "ZEngine-${VERSION}-Windows-x64.zip" Windows-x64-Release/
109+
zip -r "ZEngine-${VERSION}-macOS-x64.zip" macOS-x64-Release/
110+
zip -r "ZEngine-${VERSION}-macOS-arm64.zip" macOS-arm64-Release/
111+
tar -czf "ZEngine-${VERSION}-Linux-x64.tar.gz" linux-Release/
112+
113+
- name: Publish GitHub Pre-release
114+
if: steps.check-tag.outputs.skipped != 'true'
115+
uses: softprops/action-gh-release@v2
116+
with:
117+
tag_name: ${{ steps.check-tag.outputs.tag }}
118+
name: ${{ steps.check-tag.outputs.version }}
119+
prerelease: true
120+
generate_release_notes: false
121+
body_path: /tmp/release-notes.md
122+
files: |
123+
artifacts/ZEngine-${{ steps.check-tag.outputs.version }}-Windows-x64.zip
124+
artifacts/ZEngine-${{ steps.check-tag.outputs.version }}-macOS-x64.zip
125+
artifacts/ZEngine-${{ steps.check-tag.outputs.version }}-macOS-arm64.zip
126+
artifacts/ZEngine-${{ steps.check-tag.outputs.version }}-Linux-x64.tar.gz

.github/workflows/release-please-prerelease.yml

Lines changed: 1 addition & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,10 @@ on:
66

77
permissions:
88
contents: write
9-
pull-requests: write
10-
packages: write
119

1210
jobs:
1311
bump-version:
1412
runs-on: ubuntu-latest
15-
outputs:
16-
new_version: ${{ steps.bump.outputs.new_version }}
17-
skipped: ${{ steps.bump.outputs.skipped }}
18-
last_tag: ${{ steps.bump.outputs.last_tag }}
1913
steps:
2014
- uses: actions/checkout@v4
2115
with:
@@ -31,83 +25,14 @@ jobs:
3125
set -e
3226
if [ $EXIT_CODE -eq 2 ]; then
3327
echo "No releasable commits — skipping release."
34-
echo "skipped=true" >> "$GITHUB_OUTPUT"
3528
exit 0
3629
fi
37-
LAST_TAG="$(git describe --tags --abbrev=0 2>/dev/null || echo "")"
3830
echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
39-
echo "last_tag=$LAST_TAG" >> "$GITHUB_OUTPUT"
40-
echo "skipped=false" >> "$GITHUB_OUTPUT"
41-
42-
- name: Generate release notes
43-
id: notes
44-
if: steps.bump.outputs.skipped != 'true'
45-
run: |
46-
NOTES="$(bash Scripts/generate-changelog.sh \
47-
"${{ steps.bump.outputs.last_tag }}" \
48-
HEAD \
49-
"${{ steps.bump.outputs.new_version }}")"
50-
# Write to file to safely pass multiline content
51-
echo "$NOTES" > /tmp/release-notes.md
52-
echo "notes_file=/tmp/release-notes.md" >> "$GITHUB_OUTPUT"
5331
5432
- name: Tag
55-
if: steps.bump.outputs.skipped != 'true'
33+
if: steps.bump.outputs.new_version != ''
5634
run: |
5735
git config user.name "github-actions[bot]"
5836
git config user.email "github-actions[bot]@users.noreply.github.com"
5937
git tag -a "v${{ steps.bump.outputs.new_version }}" -m "chore: release ${{ steps.bump.outputs.new_version }}"
6038
git push origin "v${{ steps.bump.outputs.new_version }}"
61-
62-
- name: Upload release notes
63-
if: steps.bump.outputs.skipped != 'true'
64-
uses: actions/upload-artifact@v6
65-
with:
66-
name: release-notes
67-
path: /tmp/release-notes.md
68-
69-
publish-windows:
70-
needs: bump-version
71-
if: ${{ needs.bump-version.outputs.skipped != 'true' }}
72-
uses: ./.github/workflows/job-cmakebuild-windows.yml
73-
with:
74-
targetFramework: net8.0
75-
configuration: Release
76-
77-
publish-macos:
78-
needs: bump-version
79-
if: ${{ needs.bump-version.outputs.skipped != 'true' }}
80-
uses: ./.github/workflows/job-cmakebuild-macOS.yml
81-
with:
82-
targetFramework: net8.0
83-
configuration: Release
84-
85-
publish-linux:
86-
needs: bump-version
87-
if: ${{ needs.bump-version.outputs.skipped != 'true' }}
88-
uses: ./.github/workflows/job-cmakebuild-linux.yml
89-
with:
90-
targetFramework: net8.0
91-
configuration: Release
92-
93-
upload-artifacts:
94-
needs: [bump-version, publish-windows, publish-macos, publish-linux]
95-
if: ${{ needs.bump-version.outputs.skipped != 'true' }}
96-
runs-on: ubuntu-latest
97-
permissions:
98-
contents: write
99-
steps:
100-
- name: Download all build artifacts
101-
uses: actions/download-artifact@v6
102-
with:
103-
path: artifacts
104-
105-
- name: Publish GitHub Pre-release
106-
uses: softprops/action-gh-release@v2
107-
with:
108-
tag_name: v${{ needs.bump-version.outputs.new_version }}
109-
name: ${{ needs.bump-version.outputs.new_version }}
110-
prerelease: true
111-
generate_release_notes: false
112-
body_path: artifacts/release-notes/release-notes.md
113-
files: artifacts/**/*

.github/workflows/release-please.yml

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,46 @@ jobs:
5454
permissions:
5555
contents: write
5656
steps:
57-
- name: Download all build artifacts
57+
- name: Download Windows artifact
5858
uses: actions/download-artifact@v6
5959
with:
60-
path: artifacts
60+
name: Windows-x64-Release
61+
path: artifacts/Windows-x64-Release
62+
63+
- name: Download macOS x64 artifact
64+
uses: actions/download-artifact@v6
65+
with:
66+
name: macOS-x64-Release
67+
path: artifacts/macOS-x64-Release
68+
69+
- name: Download macOS arm64 artifact
70+
uses: actions/download-artifact@v6
71+
with:
72+
name: macOS-arm64-Release
73+
path: artifacts/macOS-arm64-Release
74+
75+
- name: Download Linux artifact
76+
uses: actions/download-artifact@v6
77+
with:
78+
name: linux-Release
79+
path: artifacts/linux-Release
80+
81+
- name: Package artifacts
82+
run: |
83+
VERSION="${{ needs.release-please.outputs.tag_name }}"
84+
VERSION="${VERSION#v}"
85+
cd artifacts
86+
zip -r "ZEngine-${VERSION}-Windows-x64.zip" Windows-x64-Release/
87+
zip -r "ZEngine-${VERSION}-macOS-x64.zip" macOS-x64-Release/
88+
zip -r "ZEngine-${VERSION}-macOS-arm64.zip" macOS-arm64-Release/
89+
tar -czf "ZEngine-${VERSION}-Linux-x64.tar.gz" linux-Release/
6190
6291
- name: Upload to GitHub Release
6392
uses: softprops/action-gh-release@v2
6493
with:
6594
tag_name: ${{ needs.release-please.outputs.tag_name }}
66-
files: artifacts/**/*
95+
files: |
96+
artifacts/ZEngine-*-Windows-x64.zip
97+
artifacts/ZEngine-*-macOS-x64.zip
98+
artifacts/ZEngine-*-macOS-arm64.zip
99+
artifacts/ZEngine-*-Linux-x64.tar.gz

Scripts/bump-prerelease.sh

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,61 +11,71 @@ set -euo pipefail
1111
REPO_ROOT="$(git rev-parse --show-toplevel)"
1212
VERSION_FILE="$REPO_ROOT/VERSION.txt"
1313

14-
# Read current version
15-
CURRENT="$(cat "$VERSION_FILE" | tr -d '[:space:]')"
14+
LAST_TAG="$(git describe --tags --abbrev=0 2>/dev/null || echo "")"
15+
LAST_STABLE_TAG="$(git describe --tags --abbrev=0 --exclude '*-rc.*' 2>/dev/null || echo "")"
1616

17-
# Strip any existing prerelease suffix to get the base semver
18-
BASE="$(echo "$CURRENT" | sed 's/-.*$//')"
19-
MAJOR="$(echo "$BASE" | cut -d. -f1)"
20-
MINOR="$(echo "$BASE" | cut -d. -f2)"
21-
PATCH="$(echo "$BASE" | cut -d. -f3)"
17+
# Sets HAS_BREAKING, HAS_FEAT, HAS_FIX from commits in the given range.
18+
scan_commits() {
19+
local range="$1"
20+
HAS_BREAKING=0; HAS_FEAT=0; HAS_FIX=0
21+
while IFS= read -r line; do
22+
if echo "$line" | grep -qE '^(feat|fix|perf|refactor|build|ci|revert)(\(.+\))?!:'; then
23+
HAS_BREAKING=1
24+
elif echo "$line" | grep -qE '^feat(\(.+\))?:'; then
25+
HAS_FEAT=1
26+
elif echo "$line" | grep -qE '^(fix|perf|refactor|revert)(\(.+\))?:'; then
27+
HAS_FIX=1
28+
fi
29+
done < <(git log "$range" --format="%s" 2>/dev/null)
30+
# Also scan commit bodies for the BREAKING CHANGE footer (conventional commits spec)
31+
if git log "$range" --format="%b" 2>/dev/null | grep -qE '^BREAKING CHANGE:'; then
32+
HAS_BREAKING=1
33+
fi
34+
}
2235

23-
# Extract current rc counter (0 if not an rc version)
24-
if echo "$CURRENT" | grep -qE '\-rc\.([0-9]+)$'; then
25-
ALPHA_N="$(echo "$CURRENT" | sed 's/.*-rc\.//')"
26-
else
27-
ALPHA_N=0
36+
# 1. Any new releasable commits since the last tag (rc or stable)?
37+
# If not, there is nothing to release.
38+
scan_commits "${LAST_TAG:+${LAST_TAG}..}HEAD"
39+
if [ $HAS_BREAKING -eq 0 ] && [ $HAS_FEAT -eq 0 ] && [ $HAS_FIX -eq 0 ]; then
40+
exit 2
2841
fi
2942

30-
# Find the last tag on this branch to scope commit search
31-
LAST_TAG="$(git describe --tags --abbrev=0 2>/dev/null || echo "")"
43+
# 2. Determine the correct next stable version from ALL commits since the last
44+
# stable release. This ensures a breaking change added after an rc tag
45+
# (e.g. v0.3.0-rc.1) produces 1.0.0-rc.1, not 0.3.0-rc.2.
46+
scan_commits "${LAST_STABLE_TAG:+${LAST_STABLE_TAG}..}HEAD"
3247

33-
if [ -n "$LAST_TAG" ]; then
34-
COMMIT_RANGE="$LAST_TAG..HEAD"
48+
# Prefer the stable tag as the base — it stays correct even when VERSION.txt
49+
# on develop lags behind main after a stable release.
50+
if [ -n "$LAST_STABLE_TAG" ]; then
51+
BASE="$(echo "$LAST_STABLE_TAG" | sed 's/^v//')"
3552
else
36-
COMMIT_RANGE="HEAD"
53+
BASE="$(tr -d '[:space:]' < "$VERSION_FILE" | sed 's/-.*$//')"
3754
fi
55+
MAJOR="$(echo "$BASE" | cut -d. -f1)"
56+
MINOR="$(echo "$BASE" | cut -d. -f2)"
57+
PATCH="$(echo "$BASE" | cut -d. -f3)"
3858

39-
# Analyse commits since the last tag
40-
HAS_BREAKING=0
41-
HAS_FEAT=0
42-
HAS_FIX=0
43-
44-
while IFS= read -r line; do
45-
if echo "$line" | grep -qE '^(feat|fix|perf|refactor|build|ci|revert)(\(.+\))?!:'; then
46-
HAS_BREAKING=1
47-
elif echo "$line" | grep -qE 'BREAKING CHANGE:'; then
48-
HAS_BREAKING=1
49-
elif echo "$line" | grep -qE '^feat(\(.+\))?:'; then
50-
HAS_FEAT=1
51-
elif echo "$line" | grep -qE '^(fix|perf|refactor|revert)(\(.+\))?:'; then
52-
HAS_FIX=1
53-
fi
54-
done < <(git log "$COMMIT_RANGE" --format="%s" 2>/dev/null)
55-
56-
# Determine bump type and compute next version
5759
if [ $HAS_BREAKING -eq 1 ]; then
58-
MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0; ALPHA_N=0
60+
MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0
5961
elif [ $HAS_FEAT -eq 1 ]; then
60-
MINOR=$((MINOR + 1)); PATCH=0; ALPHA_N=0
61-
elif [ $HAS_FIX -eq 1 ]; then
62-
PATCH=$((PATCH + 1)); ALPHA_N=0
62+
MINOR=$((MINOR + 1)); PATCH=0
6363
else
64-
# No releasable commits
65-
exit 2
64+
PATCH=$((PATCH + 1))
6665
fi
66+
NEXT_VERSION="${MAJOR}.${MINOR}.${PATCH}"
6767

68-
ALPHA_N=$((ALPHA_N + 1))
69-
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}-rc.${ALPHA_N}"
68+
# 3. If we are already in an RC series for this exact version, increment the
69+
# counter. Otherwise start a fresh series at rc.1.
70+
RC_BASE=""
71+
RC_N=0
72+
if echo "$LAST_TAG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$'; then
73+
RC_BASE="$(echo "$LAST_TAG" | sed 's/^v//' | sed 's/-rc\.[0-9]*$//')"
74+
RC_N="$(echo "$LAST_TAG" | sed 's/.*-rc\.//')"
75+
fi
7076

71-
echo "$NEW_VERSION"
77+
if [ "$RC_BASE" = "$NEXT_VERSION" ]; then
78+
echo "${NEXT_VERSION}-rc.$((RC_N + 1))"
79+
else
80+
echo "${NEXT_VERSION}-rc.1"
81+
fi

ZEngine/ZEngine/Core/version.h.in

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#pragma once
22

3-
#define ZENGINE_VERSION_MAJOR @ZENGINE_VERSION_MAJOR @
4-
#define ZENGINE_VERSION_MINOR @ZENGINE_VERSION_MINOR @
5-
#define ZENGINE_VERSION_PATCH @ZENGINE_VERSION_PATCH @
3+
// clang-format off
4+
#define ZENGINE_VERSION_MAJOR @ZENGINE_VERSION_MAJOR@
5+
#define ZENGINE_VERSION_MINOR @ZENGINE_VERSION_MINOR@
6+
#define ZENGINE_VERSION_PATCH @ZENGINE_VERSION_PATCH@
67
#define ZENGINE_VERSION_PRERELEASE "@ZENGINE_VERSION_PRERELEASE@"
78
#define ZENGINE_VERSION_STRING "@ZENGINE_VERSION_FULL@"
89
#define ZENGINE_VERSION_COMMIT "@ZENGINE_GIT_HASH@"
10+
// clang-format on

0 commit comments

Comments
 (0)