Skip to content

Commit 376e619

Browse files
CopilotCopilot
andauthored
Automate release workflow via GitHub releases using Maven release plugin (#346)
* Add automated release workflow and documentation Co-authored-by: thomasturrell <1552612+thomasturrell@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 43deb4c commit 376e619

4 files changed

Lines changed: 296 additions & 1 deletion

File tree

.github/workflows/maven-publish.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
# DEPRECATED: This workflow is kept for backward compatibility only
2+
#
3+
# Please use the automated release process instead:
4+
# 1. Create a new release in GitHub UI with tag format vX.Y.Z
5+
# 2. The "Automated Release" workflow will handle the rest
6+
#
17
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
28
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
39

4-
name: Maven Release
10+
name: Maven Release (Manual - Deprecated)
511

612
on: workflow_dispatch
713
jobs:

.github/workflows/release.yml

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# This workflow automates the release process when a release is created on GitHub
2+
# It uses Maven release plugin to manage versions and deploys to Maven Central
3+
#
4+
# Usage:
5+
# 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)
7+
# 2. This workflow will automatically:
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
12+
13+
name: Automated Release
14+
15+
on:
16+
release:
17+
types: [created] # Trigger when release is created
18+
19+
permissions:
20+
contents: write # Required to push commits and update tags
21+
22+
jobs:
23+
release:
24+
runs-on: ubuntu-latest
25+
26+
steps:
27+
- name: Validate release tag format
28+
id: validate_tag
29+
run: |
30+
TAG_NAME="${{ github.event.release.tag_name }}"
31+
echo "Release tag: $TAG_NAME"
32+
33+
# Validate tag format (should be vX.Y.Z)
34+
if [[ ! "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
35+
echo "::error::Invalid tag format. Expected format: vX.Y.Z (e.g., v1.2.0)"
36+
exit 1
37+
fi
38+
39+
# Remove 'v' prefix to get the version number
40+
VERSION="${TAG_NAME#v}"
41+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
42+
echo "Extracted version: $VERSION"
43+
44+
- name: Determine target branch
45+
id: target_branch
46+
run: |
47+
# Use target_commitish to determine the originating branch
48+
TARGET="${{ github.event.release.target_commitish }}"
49+
50+
# If target_commitish is empty or a SHA, default to main
51+
if [[ -z "$TARGET" ]] || [[ "$TARGET" =~ ^[0-9a-f]{40}$ ]]; then
52+
TARGET="main"
53+
fi
54+
55+
echo "target_branch=${TARGET}" >> $GITHUB_OUTPUT
56+
echo "Target branch: $TARGET"
57+
58+
- name: Checkout repository
59+
uses: actions/checkout@v3
60+
with:
61+
ref: ${{ steps.target_branch.outputs.target_branch }}
62+
fetch-depth: 0
63+
token: ${{ secrets.GITHUB_TOKEN }}
64+
65+
- name: Delete user-created tag
66+
run: |
67+
TAG_NAME="${{ github.event.release.tag_name }}"
68+
69+
# Delete the tag created by the user (will be recreated by release:prepare)
70+
git tag -d "$TAG_NAME" || true
71+
git push origin ":refs/tags/$TAG_NAME" || true
72+
73+
echo "Deleted user-created tag $TAG_NAME"
74+
75+
- name: Set up JDK 17
76+
uses: actions/setup-java@v5
77+
with:
78+
java-version: "17"
79+
distribution: "temurin"
80+
cache: maven
81+
82+
- name: Configure Git
83+
run: |
84+
git config user.name "github-actions[bot]"
85+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
86+
87+
- name: Run Maven release:prepare
88+
run: |
89+
VERSION="${{ steps.validate_tag.outputs.version }}"
90+
TAG_NAME="${{ github.event.release.tag_name }}"
91+
92+
echo "Preparing release version: $VERSION"
93+
echo "Tag name: $TAG_NAME"
94+
95+
# Run release:prepare with explicit release version
96+
# Maven will automatically calculate the next development version
97+
./mvnw -B release:prepare \
98+
-DreleaseVersion="${VERSION}" \
99+
-Dtag="${TAG_NAME}" \
100+
-DpushChanges=false
101+
env:
102+
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
103+
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
104+
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
105+
106+
- name: Run Maven release:perform
107+
run: |
108+
echo "Performing release and deploying to Maven Central"
109+
110+
# Run release:perform to build and deploy
111+
./mvnw -B release:perform \
112+
-DlocalCheckout=true \
113+
-DeployAtEnd=true
114+
env:
115+
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
116+
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
117+
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
118+
119+
- name: Push changes to originating branch
120+
run: |
121+
TARGET_BRANCH="${{ steps.target_branch.outputs.target_branch }}"
122+
TAG_NAME="${{ github.event.release.tag_name }}"
123+
124+
echo "Pushing changes to branch: $TARGET_BRANCH"
125+
126+
# Push the commits created by release:prepare
127+
if ! git push --force-with-lease origin "HEAD:${TARGET_BRANCH}"; then
128+
echo "::error::Failed to push release commits to ${TARGET_BRANCH} due to branch divergence."
129+
echo "The remote branch may have new commits. Please resolve the conflict manually:"
130+
echo " 1. Fetch the latest changes: git fetch origin"
131+
echo " 2. Rebase or merge as needed, then push again with --force-with-lease."
132+
exit 1
133+
fi
134+
135+
# Push the tag created by release:prepare
136+
git push origin "$TAG_NAME"
137+
138+
echo "Pushed release commits and tag to $TARGET_BRANCH"

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,3 +488,7 @@ public ResponseEntity<Collection<UUID>> postStatements(
488488
}
489489

490490
```
491+
492+
## Contributing
493+
494+
For information about creating releases, see [RELEASING.md](RELEASING.md).

RELEASING.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# Release Process
2+
3+
This document describes the automated release process for xAPI Java.
4+
5+
## Overview
6+
7+
The release process is **fully automated** via GitHub Actions. Creating a release is as simple as:
8+
1. Click "Create Release" in GitHub UI
9+
2. Enter tag (e.g., `v1.2.0`)
10+
3. Publish
11+
4. Wait for workflow to complete ✅
12+
13+
All version management, building, testing, and deployment happens automatically.
14+
15+
## Automated Release Process
16+
17+
18+
19+
### Step 1: Create a GitHub Release
20+
21+
1. Navigate to the [Releases page](https://github.com/BerryCloud/xapi-java/releases)
22+
2. Click **"Draft a new release"**
23+
3. **Choose a tag**: Enter the tag version in the format: `vX.Y.Z` (e.g., `v1.2.0`)
24+
- The tag **must** start with `v` followed by semantic version numbers
25+
- Example: `v1.1.16`, `v2.0.0`, `v1.2.3`
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"**
31+
32+
### Step 2: Automated Workflow Execution
33+
34+
Once you publish the release, the "Automated Release" workflow will:
35+
36+
1. ✅ Validate the tag format (must be `vX.Y.Z`)
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
50+
51+
**Workflow Diagram:**
52+
```
53+
User Action: Create Release (tag: v1.2.0, target: main)
54+
55+
GitHub: Creates tag v1.2.0 → commit A (from main)
56+
57+
Workflow: Detects target branch (main)
58+
59+
Workflow: Deletes user-created tag v1.2.0
60+
61+
Workflow: Runs release:prepare
62+
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)
66+
67+
Workflow: Runs release:perform
68+
69+
- Checks out tag v1.2.0 (commit B)
70+
- Builds and tests
71+
- Deploys to Maven Central
72+
73+
Workflow: Pushes commits B & C to main
74+
75+
Workflow: Pushes tag v1.2.0 → commit B
76+
77+
Result:
78+
- Tag v1.2.0 → commit B (release version)
79+
- Main branch → commit C (next SNAPSHOT: 1.2.1-SNAPSHOT)
80+
- Artifacts deployed to Maven Central
81+
```
82+
83+
### Step 3: Verify Release
84+
85+
1. Check the [Actions tab](https://github.com/BerryCloud/xapi-java/actions) to ensure the workflow completed successfully
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`
89+
3. Verify artifacts are available on [Maven Central](https://central.sonatype.com/artifact/dev.learning.xapi/xapi-model)
90+
91+
## Release Branch Strategy
92+
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
102+
103+
## Troubleshooting
104+
105+
### Release Workflow Failed
106+
107+
If the automated release workflow fails:
108+
109+
1. **Check the workflow logs** in the [Actions tab](https://github.com/BerryCloud/xapi-java/actions)
110+
2. **Identify the failed step** and review the error message
111+
3. **Common issues and solutions:**
112+
113+
| Issue | Solution |
114+
|-------|----------|
115+
| Invalid tag format | Use format `vX.Y.Z` (e.g., `v1.2.0`, not `1.2.0` or `v1.2`) |
116+
| Missing secrets | Ensure GPG keys and Maven credentials are configured in repository secrets |
117+
| Build failures | Fix build issues on main branch first, then retry release |
118+
| Test failures | Fix failing tests on main branch first, then retry release |
119+
120+
4. **After fixing issues:**
121+
- Delete the failed release and tag in GitHub UI
122+
- **Important**: Reset your target branch if commits were already pushed:
123+
```bash
124+
# If release:prepare pushed commits before failure
125+
git fetch origin
126+
git checkout main # or your target branch
127+
git reset --hard origin/main~2 # Remove the 2 release commits
128+
git push -f origin main
129+
```
130+
- Create a new release with the same tag
131+
132+
### Workflow Stuck or Taking Too Long
133+
134+
The workflow typically takes 5-10 minutes. If it's taking longer:
135+
136+
1. Check if tests are running (this is the longest step)
137+
2. Check for any hanging processes in the workflow logs
138+
3. You can cancel the workflow run and restart it
139+
140+
### Artifacts Not Appearing on Maven Central
141+
142+
If artifacts don't appear on Maven Central after a successful workflow:
143+
144+
1. Check the Central Portal for deployment status: https://central.sonatype.com/
145+
2. Deployment can take up to 2 hours to sync to Maven Central
146+
3. Check for any deployment errors in the workflow logs
147+
4. Verify GPG signing was successful (check for GPG-related errors)

0 commit comments

Comments
 (0)