Skip to content

Commit f096dff

Browse files
Use Maven release plugin (release:prepare and release:perform) with branch auto-detection
Co-authored-by: thomasturrell <1552612+thomasturrell@users.noreply.github.com>
1 parent 01573ba commit f096dff

2 files changed

Lines changed: 134 additions & 148 deletions

File tree

.github/workflows/release.yml

Lines changed: 67 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
# This workflow automates the release process when a release is created on GitHub
2-
# It creates a release branch, updates versions, and deploys to Maven Central
2+
# It uses Maven release plugin to manage versions and deploys to Maven Central
33
#
44
# Usage:
55
# 1. Create a new release in GitHub UI with tag format: vX.Y.Z (e.g., v1.2.0)
6+
# - Select the target branch (typically main)
67
# 2. This workflow will automatically:
7-
# - Create a release-X.Y.Z branch
8-
# - Update pom.xml versions to release version
9-
# - Build and deploy artifacts to Maven Central
10-
# - Update pom.xml to next development version
11-
# - Push version commits back to the release branch
8+
# - Use Maven release:prepare to update versions and create release commits
9+
# - Use Maven release:perform to build and deploy artifacts to Maven Central
10+
# - Move the tag to point to the actual release commit
11+
# - Push commits back to the originating branch
1212

1313
name: Automated Release
1414

1515
on:
1616
release:
17-
types: [created] # Trigger when release is created (before it's published)
17+
types: [created] # Trigger when release is created
1818

1919
permissions:
20-
contents: write # Required to create branches and push commits
20+
contents: write # Required to push commits and update tags
2121

2222
jobs:
2323
release:
@@ -41,11 +41,6 @@ jobs:
4141
echo "version=${VERSION}" >> $GITHUB_OUTPUT
4242
echo "Extracted version: $VERSION"
4343
44-
# Create release branch name
45-
RELEASE_BRANCH="release-${VERSION}"
46-
echo "release_branch=${RELEASE_BRANCH}" >> $GITHUB_OUTPUT
47-
echo "Release branch: $RELEASE_BRANCH"
48-
4944
# Calculate next development version (increment patch version)
5045
IFS='.' read -ra VERSION_PARTS <<< "$VERSION"
5146
MAJOR="${VERSION_PARTS[0]}"
@@ -56,20 +51,36 @@ jobs:
5651
echo "next_version=${NEXT_VERSION}" >> $GITHUB_OUTPUT
5752
echo "Next development version: $NEXT_VERSION"
5853
59-
- name: Checkout repository at release tag
54+
- name: Determine target branch
55+
id: target_branch
56+
run: |
57+
# Use target_commitish to determine the originating branch
58+
TARGET="${{ github.event.release.target_commitish }}"
59+
60+
# If target_commitish is empty or a SHA, default to main
61+
if [[ -z "$TARGET" ]] || [[ "$TARGET" =~ ^[0-9a-f]{40}$ ]]; then
62+
TARGET="main"
63+
fi
64+
65+
echo "target_branch=${TARGET}" >> $GITHUB_OUTPUT
66+
echo "Target branch: $TARGET"
67+
68+
- name: Checkout repository
6069
uses: actions/checkout@v3
6170
with:
62-
ref: ${{ github.event.release.tag_name }}
71+
ref: ${{ steps.target_branch.outputs.target_branch }}
6372
fetch-depth: 0
6473
token: ${{ secrets.GITHUB_TOKEN }}
6574

66-
- name: Create release branch
75+
- name: Delete user-created tag
6776
run: |
68-
RELEASE_BRANCH="${{ steps.validate_tag.outputs.release_branch }}"
77+
TAG_NAME="${{ github.event.release.tag_name }}"
78+
79+
# Delete the tag created by the user (will be recreated by release:prepare)
80+
git tag -d "$TAG_NAME" || true
81+
git push origin ":refs/tags/$TAG_NAME" || true
6982
70-
# Create new branch from the release tag
71-
git checkout -b "$RELEASE_BRANCH"
72-
echo "Created branch $RELEASE_BRANCH from tag ${{ github.event.release.tag_name }}"
83+
echo "Deleted user-created tag $TAG_NAME"
7384
7485
- name: Set up JDK 17
7586
uses: actions/setup-java@v5
@@ -88,103 +99,60 @@ jobs:
8899
git config user.name "github-actions[bot]"
89100
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
90101
91-
- name: Set release version in POM
92-
run: |
93-
VERSION="${{ steps.validate_tag.outputs.version }}"
94-
echo "Setting version to: $VERSION"
95-
96-
# Use Maven versions plugin to set the version
97-
./mvnw -B versions:set -DnewVersion="${VERSION}" -DgenerateBackupPoms=false
98-
99-
# Commit the version change
100-
git add .
101-
git commit -m "[maven-release-plugin] prepare release v${VERSION}"
102-
103-
- name: Verify release build
104-
run: |
105-
echo "Running tests and verification for release version"
106-
107-
# Build and test the release version
108-
./mvnw -B clean verify
109-
110-
- name: Build and deploy release
102+
- name: Run Maven release:prepare
111103
run: |
112104
VERSION="${{ steps.validate_tag.outputs.version }}"
113-
echo "Building and deploying version: $VERSION"
105+
NEXT_VERSION="${{ steps.validate_tag.outputs.next_version }}"
106+
TAG_NAME="${{ github.event.release.tag_name }}"
114107
115-
# Build and deploy with release profile (includes signing, sources, javadocs)
116-
./mvnw -B clean deploy -Prelease \
117-
-pl xapi-model,xapi-client,xapi-model-spring-boot-starter -am \
118-
-DskipTests
108+
echo "Preparing release version: $VERSION"
109+
echo "Next development version: $NEXT_VERSION"
110+
echo "Tag name: $TAG_NAME"
111+
112+
# Run release:prepare with explicit versions
113+
./mvnw -B release:prepare \
114+
-DreleaseVersion="${VERSION}" \
115+
-DdevelopmentVersion="${NEXT_VERSION}" \
116+
-Dtag="${TAG_NAME}" \
117+
-DpushChanges=false \
118+
-DremoteTagging=false
119119
env:
120120
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
121121
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
122122
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
123123

124-
- name: Update to next development version
124+
- name: Run Maven release:perform
125125
run: |
126-
NEXT_VERSION="${{ steps.validate_tag.outputs.next_version }}"
127-
echo "Setting next development version to: $NEXT_VERSION"
126+
echo "Performing release and deploying to Maven Central"
128127
129-
# Update to next SNAPSHOT version
130-
./mvnw -B versions:set -DnewVersion="${NEXT_VERSION}" -DgenerateBackupPoms=false
131-
132-
# Commit the version change
133-
git add .
134-
git commit -m "[maven-release-plugin] prepare for next development iteration"
128+
# Run release:perform to build and deploy
129+
./mvnw -B release:perform \
130+
-DlocalCheckout=true \
131+
-DeployAtEnd=true
132+
env:
133+
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
134+
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
135+
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
135136

136-
- name: Update release tag to point to release commit
137+
- name: Push changes to originating branch
137138
run: |
139+
TARGET_BRANCH="${{ steps.target_branch.outputs.target_branch }}"
138140
TAG_NAME="${{ github.event.release.tag_name }}"
139141
140-
# Delete the existing tag locally
141-
git tag -d "$TAG_NAME"
142-
143-
# Get the commit hash of the release preparation commit (one before current)
144-
RELEASE_COMMIT=$(git rev-parse HEAD~1)
145-
146-
# Create new tag pointing to the release commit
147-
git tag -a "$TAG_NAME" "$RELEASE_COMMIT" -m "Release $TAG_NAME"
148-
149-
# Force push the updated tag
150-
git push -f origin "$TAG_NAME"
151-
152-
echo "Updated tag $TAG_NAME to point to release commit: $RELEASE_COMMIT"
153-
154-
- name: Push release branch
155-
run: |
156-
RELEASE_BRANCH="${{ steps.validate_tag.outputs.release_branch }}"
157-
158-
# Push the release branch with all commits
159-
git push -u origin "$RELEASE_BRANCH"
160-
161-
echo "Pushed release branch: $RELEASE_BRANCH"
162-
163-
- name: Update main branch with next development version
164-
run: |
165-
NEXT_VERSION="${{ steps.validate_tag.outputs.next_version }}"
166-
167-
echo "Updating main branch to next development version: $NEXT_VERSION"
168-
169-
# Fetch and checkout main branch
170-
git fetch origin main
171-
git checkout main
172-
173-
# Update to next SNAPSHOT version
174-
./mvnw -B versions:set -DnewVersion="${NEXT_VERSION}" -DgenerateBackupPoms=false
142+
echo "Pushing changes to branch: $TARGET_BRANCH"
175143
176-
# Commit the version change
177-
git add .
178-
git commit -m "[maven-release-plugin] prepare for next development iteration"
144+
# Push the commits created by release:prepare
145+
git push origin "HEAD:${TARGET_BRANCH}"
179146
180-
# Push to main
181-
git push origin main
147+
# Push the tag created by release:prepare
148+
git push origin "$TAG_NAME"
182149
183-
echo "Updated main branch to version: $NEXT_VERSION"
150+
echo "Pushed release commits and tag to $TARGET_BRANCH"
184151
185152
- name: Clean up
186153
if: always()
187154
run: |
188-
# Clean up any Maven artifacts
189-
rm -f release.properties
190-
find . -name "pom.xml.versionsBackup" -delete || true
155+
# Clean up Maven release artifacts
156+
rm -f release.properties pom.xml.releaseBackup
157+
find . -name "pom.xml.releaseBackup" -delete || true
158+
find . -name "pom.xml.tag" -delete || true

RELEASING.md

Lines changed: 67 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -20,80 +20,85 @@ The release process is fully automated via GitHub Actions. To create a new relea
2020

2121
1. Navigate to the [Releases page](https://github.com/BerryCloud/xapi-java/releases)
2222
2. Click **"Draft a new release"**
23-
3. Enter the tag version in the format: `vX.Y.Z` (e.g., `v1.2.0`)
23+
3. **Choose a tag**: Enter the tag version in the format: `vX.Y.Z` (e.g., `v1.2.0`)
2424
- The tag **must** start with `v` followed by semantic version numbers
2525
- Example: `v1.1.16`, `v2.0.0`, `v1.2.3`
26-
4. Enter a release title (e.g., "Release 1.2.0")
27-
5. Add release notes describing the changes
28-
6. Click **"Publish release"**
26+
4. **Target**: Select the branch to release from (typically `main`)
27+
- The workflow will automatically detect and use this branch
28+
5. Enter a release title (e.g., "Release 1.2.0")
29+
6. Add release notes describing the changes
30+
7. Click **"Publish release"**
2931

3032
### Step 2: Automated Workflow Execution
3133

3234
Once you publish the release, the "Automated Release" workflow will:
3335

3436
1. ✅ Validate the tag format (must be `vX.Y.Z`)
35-
2. ✅ Extract the version number from the tag
36-
3. ✅ Create a `release-X.Y.Z` branch from the release tag
37-
4. ✅ Update all `pom.xml` files to the release version
38-
5. ✅ Commit the version change
39-
6.**Run full test suite** to verify the release
40-
7. ✅ Build and deploy artifacts to Maven Central with:
41-
- Compiled JARs
42-
- Source JARs
43-
- Javadoc JARs
44-
- GPG signatures
45-
8. ✅ Update the release tag to point to the release commit
46-
9. ✅ Update `pom.xml` files to the next SNAPSHOT version on release branch
47-
10. ✅ Push all commits to the release branch
48-
11. ✅ Update `main` branch with the next SNAPSHOT version
37+
2. ✅ Detect the target branch (auto-detected from release)
38+
3. ✅ Delete the user-created tag (will be recreated properly)
39+
4.**Run Maven release:prepare** to:
40+
- Update all `pom.xml` files to the release version
41+
- Commit the version change
42+
- Create the release tag pointing to the release commit
43+
- Update `pom.xml` files to the next SNAPSHOT version
44+
- Commit the next development iteration
45+
5.**Run Maven release:perform** to:
46+
- Check out the release tag
47+
- Build and test the release version
48+
- Deploy artifacts to Maven Central with GPG signatures
49+
6. ✅ Push commits and tag back to the originating branch
4950

5051
**Workflow Diagram:**
5152
```
52-
User Action: Create Release (tag: v1.2.0)
53+
User Action: Create Release (tag: v1.2.0, target: main)
5354
5455
GitHub: Creates tag v1.2.0 → commit A (from main)
5556
56-
Workflow: Checkout tag v1.2.0
57+
Workflow: Detects target branch (main)
5758
58-
Workflow: Create branch release-1.2.0
59+
Workflow: Deletes user-created tag v1.2.0
5960
60-
Workflow: Update pom.xml to 1.2.0 → commit B
61+
Workflow: Runs release:prepare
6162
62-
Workflow: Run tests (mvn verify)
63+
- Commit B: pom.xml → 1.2.0 (release version)
64+
- Creates tag v1.2.0 → commit B
65+
- Commit C: pom.xml → 1.2.1-SNAPSHOT (next dev version)
6366
64-
Workflow: Build & deploy to Maven Central
67+
Workflow: Runs release:perform
6568
66-
Workflow: Move tag v1.2.0 to commit B
69+
- Checks out tag v1.2.0 (commit B)
70+
- Builds and tests
71+
- Deploys to Maven Central
6772
68-
Workflow: Update pom.xml to 1.2.1-SNAPSHOT → commit C
73+
Workflow: Pushes commits B & C to main
6974
70-
Workflow: Push branch release-1.2.0
71-
72-
Workflow: Update main branch → pom.xml to 1.2.1-SNAPSHOT
75+
Workflow: Pushes tag v1.2.0 → commit B
7376
7477
Result:
7578
- Tag v1.2.0 → commit B (release version)
76-
- Branch release-1.2.0 → commit C (next SNAPSHOT)
77-
- Main branch → updated to 1.2.1-SNAPSHOT
79+
- Main branch → commit C (next SNAPSHOT: 1.2.1-SNAPSHOT)
7880
- Artifacts deployed to Maven Central
7981
```
8082

8183
### Step 3: Verify Release
8284

8385
1. Check the [Actions tab](https://github.com/BerryCloud/xapi-java/actions) to ensure the workflow completed successfully
84-
2. Verify the release branch was created: `release-X.Y.Z`
86+
2. Verify the target branch (e.g., `main`) has two new commits:
87+
- Release commit: `[maven-release-plugin] prepare release vX.Y.Z`
88+
- Development commit: `[maven-release-plugin] prepare for next development iteration`
8589
3. Verify artifacts are available on [Maven Central](https://central.sonatype.com/artifact/dev.learning.xapi/xapi-model)
8690

8791
## Release Branch Strategy
8892

89-
- **Main branch (`main`)**: Contains development code with `-SNAPSHOT` versions
90-
- Automatically updated to next SNAPSHOT version after each release
91-
- **Release branches (`release-X.Y.Z`)**: Created automatically for each release
92-
- Contains two commits:
93-
1. Version update to release version (X.Y.Z)
94-
2. Version update to next development version (X.Y.Z+1-SNAPSHOT)
95-
- The next development version commit is also applied to `main`
96-
- **Release tags (`vX.Y.Z`)**: Points to the release version commit
93+
- **Main branch (`main`)** (or other target branch): Contains development code with `-SNAPSHOT` versions
94+
- After each release, receives two commits from Maven release plugin:
95+
1. Release commit: Version update to release version (X.Y.Z)
96+
2. Development commit: Version update to next development version (X.Y.Z+1-SNAPSHOT)
97+
- The HEAD always points to the next development version
98+
- **Release tags (`vX.Y.Z`)**: Created by Maven release plugin
99+
- Points to the release version commit (first commit)
100+
- Used for reproducible builds and deployments
101+
- **No separate release branches**: The release workflow pushes directly to the originating branch
97102

98103
## Version Numbering
99104

@@ -136,21 +141,34 @@ If the automated release workflow fails:
136141

137142
4. **After fixing issues:**
138143
- Delete the failed release and tag in GitHub UI
139-
- Delete the release branch if it was created: `git push origin --delete release-X.Y.Z`
144+
- **Important**: Reset your target branch if commits were already pushed:
145+
```bash
146+
# If release:prepare pushed commits before failure
147+
git fetch origin
148+
git checkout main # or your target branch
149+
git reset --hard origin/main~2 # Remove the 2 release commits
150+
git push -f origin main
151+
```
140152
- Create a new release with the same tag
141153

142-
### Release Branch Already Exists
154+
### Re-releasing the Same Version
143155

144-
If you need to re-release the same version:
156+
If you need to re-release the same version after a failed release:
145157

146-
1. Delete the existing release branch:
158+
1. Delete the existing release in GitHub UI:
159+
- Go to Releases → Click on the release → Delete release
160+
2. Delete the tag (locally and remotely):
147161
```bash
148-
git push origin --delete release-X.Y.Z
162+
git tag -d vX.Y.Z
163+
git push origin :refs/tags/vX.Y.Z
164+
```
165+
3. Reset the target branch if commits were pushed:
166+
```bash
167+
git fetch origin
168+
git checkout main # or your target branch
169+
git reset --hard origin/main~2 # Remove the 2 release commits if they exist
170+
git push -f origin main # Only if commits were pushed
149171
```
150-
2. Delete the existing release in GitHub UI:
151-
- Go to Releases → Click on the release → Delete release
152-
3. Delete the tag:
153-
- Go to Tags → Find the tag → Delete tag
154172
4. Create a new release with the same version tag
155173

156174
### Workflow Stuck or Taking Too Long

0 commit comments

Comments
 (0)