66 push :
77 branches :
88 - master
9- tags :
10- - " v*.*.*"
9+
10+ env :
11+ RELEASE_MAJOR : " 1"
12+ RELEASE_MINOR : " 0"
1113
1214permissions :
1315 contents : read
5961 release :
6062 name : release
6163 needs : test
62- if : github.event_name == 'push' && startsWith( github.ref, 'refs/tags/v')
64+ if : github.event_name == 'push' && github.ref == 'refs/heads/master'
6365 runs-on : ubuntu-latest
66+ concurrency :
67+ group : release-master
68+ cancel-in-progress : false
6469 permissions :
6570 contents : write
6671
@@ -70,33 +75,85 @@ jobs:
7075 with :
7176 fetch-depth : 0
7277
78+ - name : calculate version
79+ id : version
80+ env :
81+ HEAD_SHA : ${{ github.sha }}
82+ run : |
83+ set -euo pipefail
84+
85+ git fetch --force --tags origin
86+
87+ PREFIX="v${RELEASE_MAJOR}.${RELEASE_MINOR}."
88+ EXISTING_TAG="$(git tag --points-at "$HEAD_SHA" --list "${PREFIX}*" --sort=-v:refname | head -n 1 || true)"
89+
90+ if [[ -n "$EXISTING_TAG" ]]; then
91+ TAG_NAME="$EXISTING_TAG"
92+ else
93+ LATEST_TAG="$(git tag --list "${PREFIX}*" --sort=-v:refname | head -n 1 || true)"
94+
95+ if [[ -z "$LATEST_TAG" ]]; then
96+ NEXT_PATCH="0"
97+ else
98+ if ! [[ "$LATEST_TAG" =~ ^v${RELEASE_MAJOR}\.${RELEASE_MINOR}\.([0-9]+)$ ]]; then
99+ echo "Latest release tag has an unexpected format: $LATEST_TAG"
100+ exit 1
101+ fi
102+
103+ NEXT_PATCH="$((BASH_REMATCH[1] + 1))"
104+ fi
105+
106+ TAG_NAME="${PREFIX}${NEXT_PATCH}"
107+ fi
108+
109+ echo "tag_name=$TAG_NAME" >> "$GITHUB_OUTPUT"
110+ echo "major_tag=v${RELEASE_MAJOR}" >> "$GITHUB_OUTPUT"
111+
112+ - name : create tag
113+ env :
114+ TAG_NAME : ${{ steps.version.outputs.tag_name }}
115+ HEAD_SHA : ${{ github.sha }}
116+ run : |
117+ set -euo pipefail
118+
119+ git config user.name "github-actions[bot]"
120+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
121+
122+ if git rev-parse -q --verify "refs/tags/$TAG_NAME" >/dev/null; then
123+ TAG_SHA="$(git rev-list -n 1 "$TAG_NAME")"
124+
125+ if [[ "$TAG_SHA" != "$HEAD_SHA" ]]; then
126+ echo "Tag $TAG_NAME already points to $TAG_SHA, not $HEAD_SHA."
127+ exit 1
128+ fi
129+
130+ echo "Tag $TAG_NAME already exists on this commit."
131+ else
132+ git tag "$TAG_NAME" "$HEAD_SHA"
133+ git push origin "refs/tags/$TAG_NAME"
134+ fi
135+
73136 - name : create release
74137 env :
75138 GH_TOKEN : ${{ github.token }}
76- TAG_NAME : ${{ github.ref_name }}
139+ TAG_NAME : ${{ steps.version.outputs.tag_name }}
77140 run : |
78- if ! [[ "$TAG_NAME" =~ ^v([0-9]+)\.[0-9]+\.[0-9]+$ ]]; then
79- echo "Skipping release for non-semver tag: $TAG_NAME"
80- exit 0
81- fi
141+ set -euo pipefail
82142
83143 if gh release view "$TAG_NAME" >/dev/null 2>&1; then
84144 echo "Release $TAG_NAME already exists."
85145 else
86- gh release create "$TAG_NAME" --verify-tag --generate-notes --title "$TAG_NAME"
146+ gh release create "$TAG_NAME" --verify-tag --generate-notes --latest -- title "$TAG_NAME"
87147 fi
88148
89149 - name : update major tag
90150 env :
91- TAG_NAME : ${{ github.ref_name }}
151+ MAJOR_TAG : ${{ steps.version.outputs.major_tag }}
152+ HEAD_SHA : ${{ github.sha }}
92153 run : |
93- if ! [[ "$TAG_NAME" =~ ^v([0-9]+)\.[0-9]+\.[0-9]+$ ]]; then
94- exit 0
95- fi
154+ set -euo pipefail
96155
97- MAJOR_TAG="v${BASH_REMATCH[1]}"
98- TARGET_SHA="$(git rev-list -n 1 "$TAG_NAME")"
99156 git config user.name "github-actions[bot]"
100157 git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
101- git tag -f "$MAJOR_TAG" "$TARGET_SHA "
158+ git tag -f "$MAJOR_TAG" "$HEAD_SHA "
102159 git push -f origin "refs/tags/$MAJOR_TAG"
0 commit comments