-
Notifications
You must be signed in to change notification settings - Fork 4
244 lines (209 loc) · 9.07 KB
/
Copy pathrelease.yml
File metadata and controls
244 lines (209 loc) · 9.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# This workflow automates the release process when a draft release is created
# on GitHub. It uses Maven release plugin to manage versions and deploys to
# Maven Central
#
# Usage:
# 1. Create a new draft release in GitHub UI with tag format: vX.Y.Z
# (e.g., v1.2.0)
# - Select the target branch (typically main)
# 2. This workflow will automatically:
# - Use Maven release:prepare to update versions and create release commit
# - Use Maven release:perform to build and deploy artifacts to Maven Central
# - Create the tag to point to release commit
# - Push commits back to the originating branch
# - Publish the GitHub release (mark draft as non-draft)
name: Automated Release
on:
release:
types: [created] # Only fire when a release is created
permissions:
contents: write # Required to push commits, update tags and edit releases
jobs:
release:
# Only run for draft releases; ignore non-draft created events
if: github.event.release.draft
runs-on: ubuntu-latest
steps:
- name: Validate release tag format
id: validate_tag
run: |
TAG_NAME="${{ github.event.release.tag_name }}"
echo "Release tag: $TAG_NAME"
# Validate tag format (should be vX.Y.Z)
if [[ ! "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Invalid tag format. Expected format: vX.Y.Z (e.g., v1.2.0)"
exit 1
fi
# Remove 'v' prefix to get the version number
VERSION="${TAG_NAME#v}"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Extracted version: $VERSION"
- name: Determine target branch
id: target_branch
run: |
# Use target_commitish to determine the originating branch
TARGET="${{ github.event.release.target_commitish }}"
# If target_commitish is empty or a SHA, default to main
if [[ -z "$TARGET" ]] || [[ "$TARGET" =~ ^[0-9a-f]{40}$ ]]; then
TARGET="main"
fi
echo "target_branch=${TARGET}" >> "$GITHUB_OUTPUT"
echo "Target branch: $TARGET"
- name: Generate GitHub App Token
id: generate_token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Checkout repository
uses: actions/checkout@v6
with:
ref: ${{ steps.target_branch.outputs.target_branch }}
fetch-depth: 0
token: ${{ steps.generate_token.outputs.token }}
- name: Pre-build condition checks
run: |
TAG_NAME="${{ github.event.release.tag_name }}"
echo "Performing pre-build condition checks..."
# Fetch latest state from remote
git fetch origin --tags
# Check if a tag exists
if git ls-remote --tags origin | grep -q "refs/tags/$TAG_NAME$"; then
echo "::error::Tag $TAG_NAME already exists on remote."
exit 1
fi
echo "Pre-build checks passed. No issues detected."
- name: Set up JDK 25
uses: actions/setup-java@v5
with:
java-version: "25"
distribution: "temurin"
cache: maven
cache-dependency-path: |
pom.xml
xapi-model/pom.xml
xapi-client/pom.xml
xapi-model-spring-boot-starter/pom.xml
server-id: central
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
gpg-passphrase: MAVEN_GPG_PASSPHRASE
- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Run Maven release:prepare
run: |
VERSION="${{ steps.validate_tag.outputs.version }}"
TAG_NAME="${{ github.event.release.tag_name }}"
echo "Preparing release version: $VERSION"
echo "Tag name: $TAG_NAME"
./mvnw -B release:prepare \
-DreleaseVersion="${VERSION}" \
-Dtag="${TAG_NAME}" \
-DpushChanges=false \
-Darguments="-pl xapi-model,xapi-client,xapi-model-spring-boot-starter -am"
env:
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
- name: Run Maven release:perform
run: |
echo "Performing release and deploying to Maven Central"
./mvnw -B release:perform \
-DlocalCheckout=true \
-DdeployAtEnd=true \
-Darguments="-pl xapi-model,xapi-client,xapi-model-spring-boot-starter -am"
env:
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
- name: Push changes to originating branch and tag (with merge fallback)
run: |
TARGET_BRANCH="${{ steps.target_branch.outputs.target_branch }}"
TAG_NAME="${{ github.event.release.tag_name }}"
echo "Pushing changes to branch: $TARGET_BRANCH"
# First, try a normal fast-forward push
if git push origin "HEAD:${TARGET_BRANCH}"; then
echo "Fast-forward push to ${TARGET_BRANCH} succeeded."
else
echo "::warning::Fast-forward push to ${TARGET_BRANCH} failed. Trying merge fallback."
# Fetch latest state of the branch
git fetch origin "${TARGET_BRANCH}"
# Merge origin/TARGET_BRANCH into our release HEAD.
# If this conflicts, we bail out rather than trying to auto-resolve.
if ! git merge --no-edit "origin/${TARGET_BRANCH}"; then
echo "::error::Merge conflict detected - likely due to a race condition."
echo ""
echo "This typically happens when changes to POM files were merged to ${TARGET_BRANCH}"
echo "while this release workflow was running."
echo ""
echo "Recommended resolution:"
echo " 1. Delete this draft release in GitHub"
echo " 2. Create a new release via the GitHub Release UI"
echo ""
echo "Note: Artifacts have been deployed to Maven Central."
exit 1
fi
# Now push the merge commit
if git push origin "HEAD:${TARGET_BRANCH}"; then
echo "Pushed merge commit to ${TARGET_BRANCH}."
else
echo "::error::Failed to push merge commit to ${TARGET_BRANCH} after merge."
echo ""
echo "This may be due to branch protection rules or another race condition."
echo ""
echo "Recommended resolution:"
echo " 1. Delete this draft release in GitHub"
echo " 2. Create a new release via the GitHub Release UI"
exit 1
fi
fi
echo "Pushing tag $TAG_NAME"
if ! git push origin "$TAG_NAME"; then
echo "::error::Failed to push tag $TAG_NAME."
echo ""
echo "This may be due to concurrent tag creation (tag collision), where someone created a tag with"
echo "the same name while this workflow was running."
echo ""
echo "Recommended resolution:"
echo " 1. Check if the tag $TAG_NAME already exists on the remote"
echo " 2. If the tag exists but points to wrong commit, delete it"
echo " 3. Create a new draft release via the GitHub Release UI"
exit 1
fi
echo "Pushed release commits and tag to $TARGET_BRANCH"
- name: Collect release assets
run: |
set -e
VERSION="${{ steps.validate_tag.outputs.version }}"
mkdir -p artifacts
# Define artifact paths
CLIENT_JAR="xapi-client/target/xapi-client-${VERSION}.jar"
MODEL_JAR="xapi-model/target/xapi-model-${VERSION}.jar"
STARTER_JAR="xapi-model-spring-boot-starter/target/xapi-model-spring-boot-starter-${VERSION}.jar"
# Check existence and copy
for JAR in "$CLIENT_JAR" "$MODEL_JAR" "$STARTER_JAR"; do
if [ ! -f "$JAR" ]; then
echo "::error::Artifact not found: $JAR"
exit 1
fi
cp "$JAR" artifacts/
done
- name: Upload release assets
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG_NAME="${{ github.event.release.tag_name }}"
for FILE in artifacts/*; do
echo "Uploading $(basename "$FILE")"
gh release upload "$TAG_NAME" "$FILE" --clobber
done
- name: Publish GitHub release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG_NAME="${{ github.event.release.tag_name }}"
echo "Publishing draft release for $TAG_NAME"
gh release edit "$TAG_NAME" --draft=false