11name : CD
22
33on :
4+ workflow_dispatch :
45 push :
56 branches : [develop, master]
67
1819 # ═══════════════════════════════════════════════
1920
2021 pre-release :
21- if : github.ref == 'refs/heads/develop'
22+ if : >-
23+ github.ref == 'refs/heads/develop'
24+ || (github.event_name == 'workflow_dispatch' && github.ref != 'refs/heads/master')
2225 runs-on : ubuntu-latest
2326 outputs :
2427 tag : ${{ steps.tag.outputs.tag }}
@@ -27,16 +30,53 @@ jobs:
2730 with :
2831 fetch-depth : 0
2932
30- - name : Compute pre- release tag
33+ - name : Compute version from commits like release please
3134 id : tag
3235 run : |
33- VERSION=$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2)
34- TAG="v${VERSION}-rc.${{ github.run_number }}"
36+ # ── Find latest stable tag reachable from HEAD ──
37+ LATEST_TAG=""
38+ for t in $(git tag -l 'v[0-9]*.[0-9]*.[0-9]*' --sort=-version:refname | grep -v '-'); do
39+ if git merge-base --is-ancestor "$t" HEAD 2>/dev/null; then
40+ LATEST_TAG="$t"; break
41+ fi
42+ done
43+ if [ -z "$LATEST_TAG" ]; then
44+ echo "::error::No stable release tag found in branch history"
45+ exit 1
46+ fi
47+ LATEST_VERSION="${LATEST_TAG#v}"
48+ echo "Latest ancestor release: $LATEST_TAG"
49+
50+ # ── Analyse conventional commits since that tag ──
51+ COMMITS=$(git log "${LATEST_TAG}..HEAD" --format="%s")
52+ HAS_BREAKING=$(echo "$COMMITS" | grep -cE '^[a-z]+(\(.+\))?!:' || true)
53+ HAS_FEAT=$(echo "$COMMITS" | grep -cE '^feat(\(.+\))?:' || true)
54+ HAS_FIX=$(echo "$COMMITS" | grep -cE '^fix(\(.+\))?:' || true)
55+ echo "Commits since ${LATEST_TAG} — breaking=$HAS_BREAKING feat=$HAS_FEAT fix=$HAS_FIX"
3556
36- # Safety: warn if this base version is already released
37- if git ls-remote --tags origin "refs/tags/v${VERSION}" | grep -q .; then
38- echo "::warning::v${VERSION} already released. Consider bumping Cargo.toml on develop."
57+ # ── Compute next version (matches release-please observed behaviour) ──
58+ # Pre-1.0 with bump-minor-pre-major: breaking → minor, feat → minor, fix → patch
59+ IFS='.' read -r MAJOR MINOR PATCH <<< "$LATEST_VERSION"
60+ if [ "$MAJOR" -eq 0 ]; then
61+ if [ "$HAS_BREAKING" -gt 0 ] || [ "$HAS_FEAT" -gt 0 ]; then
62+ MINOR=$((MINOR + 1)); PATCH=0 # breaking or feat → minor
63+ else
64+ PATCH=$((PATCH + 1)) # fix only → patch
65+ fi
66+ else
67+ if [ "$HAS_BREAKING" -gt 0 ]; then
68+ MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 # breaking → major
69+ elif [ "$HAS_FEAT" -gt 0 ]; then
70+ MINOR=$((MINOR + 1)); PATCH=0 # feat → minor
71+ else
72+ PATCH=$((PATCH + 1)) # fix → patch
73+ fi
3974 fi
75+ VERSION="${MAJOR}.${MINOR}.${PATCH}"
76+ TAG="v${VERSION}-rc.${{ github.run_number }}"
77+
78+ echo "Next version: $VERSION (from $LATEST_VERSION)"
79+ echo "Pre-release tag: $TAG"
4080
4181 # Safety: fail if this exact tag already exists
4282 if git ls-remote --tags origin "refs/tags/${TAG}" | grep -q .; then
4585 fi
4686
4787 echo "tag=$TAG" >> $GITHUB_OUTPUT
48- echo "Pre-release tag: $TAG"
4988
5089 build-prerelease :
5190 name : Build pre-release
64103 # ═══════════════════════════════════════════════
65104
66105 release-please :
67- if : github.ref == 'refs/heads/master'
106+ if : github.ref == 'refs/heads/master' && github.event_name == 'push'
68107 runs-on : ubuntu-latest
69108 outputs :
70109 release_created : ${{ steps.release.outputs.release_created }}
0 commit comments