Skip to content

Commit b7c8fc6

Browse files
Add manual release workflow and update documentation
Co-authored-by: thomasturrell <1552612+thomasturrell@users.noreply.github.com>
1 parent d2dff77 commit b7c8fc6

3 files changed

Lines changed: 347 additions & 75 deletions

File tree

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# Manual Release Workflow
2+
#
3+
# This workflow enables manual releases with explicit version control.
4+
# It must be manually triggered via the GitHub Actions UI.
5+
#
6+
# Usage:
7+
# 1. Go to Actions > Manual Release > Run workflow
8+
# 2. Select the target branch (typically main)
9+
# 3. Enter the release version (e.g., 1.2.0) - do NOT include 'v' prefix
10+
# 4. Click "Run workflow"
11+
# 5. The workflow will:
12+
# - Validate the version format
13+
# - Run Maven release:prepare to update versions and create commits
14+
# - Run Maven release:perform to build and deploy to Maven Central
15+
# - Create a GitHub Release with the specified version
16+
# - Push all commits and tags back to the target branch
17+
18+
name: Manual Release
19+
20+
on:
21+
workflow_dispatch:
22+
inputs:
23+
version:
24+
description: 'Release version (e.g., 1.2.0) - do NOT include v prefix'
25+
required: true
26+
type: string
27+
skip_maven_central:
28+
description: 'Skip deployment to Maven Central (for testing)'
29+
required: false
30+
type: boolean
31+
default: false
32+
create_github_release:
33+
description: 'Create GitHub Release after successful deployment'
34+
required: false
35+
type: boolean
36+
default: true
37+
38+
permissions:
39+
contents: write # Required to push commits, tags, and create releases
40+
41+
jobs:
42+
release:
43+
runs-on: ubuntu-latest
44+
45+
steps:
46+
- name: Validate version format
47+
id: validate_version
48+
run: |
49+
VERSION="${{ github.event.inputs.version }}"
50+
echo "Release version: $VERSION"
51+
52+
# Validate version format (should be X.Y.Z)
53+
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
54+
echo "::error::Invalid version format. Expected format: X.Y.Z (e.g., 1.2.0)"
55+
echo "Do NOT include 'v' prefix. Just the version numbers."
56+
exit 1
57+
fi
58+
59+
# Create tag name with 'v' prefix
60+
TAG_NAME="v${VERSION}"
61+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
62+
echo "tag_name=${TAG_NAME}" >> $GITHUB_OUTPUT
63+
echo "Tag name: $TAG_NAME"
64+
65+
- name: Generate GitHub App Token
66+
id: generate_token
67+
uses: actions/create-github-app-token@v2
68+
with:
69+
app-id: ${{ secrets.APP_ID }}
70+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
71+
72+
- name: Checkout repository
73+
uses: actions/checkout@v6
74+
with:
75+
ref: ${{ github.ref }}
76+
fetch-depth: 0
77+
token: ${{ steps.generate_token.outputs.token }}
78+
79+
- name: Check if tag already exists
80+
run: |
81+
TAG_NAME="${{ steps.validate_version.outputs.tag_name }}"
82+
83+
# Check if tag exists locally or remotely
84+
if git rev-parse "$TAG_NAME" >/dev/null 2>&1; then
85+
echo "::error::Tag $TAG_NAME already exists locally"
86+
exit 1
87+
fi
88+
89+
if git ls-remote --tags origin "$TAG_NAME" | grep -q "$TAG_NAME"; then
90+
echo "::error::Tag $TAG_NAME already exists on remote"
91+
exit 1
92+
fi
93+
94+
echo "Tag $TAG_NAME does not exist. Proceeding with release."
95+
96+
- name: Set up JDK 25
97+
uses: actions/setup-java@v5
98+
with:
99+
java-version: "25"
100+
distribution: "temurin"
101+
cache: maven
102+
cache-dependency-path: |
103+
pom.xml
104+
xapi-model/pom.xml
105+
xapi-client/pom.xml
106+
xapi-model-spring-boot-starter/pom.xml
107+
server-id: central
108+
server-username: MAVEN_USERNAME
109+
server-password: MAVEN_PASSWORD
110+
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
111+
gpg-passphrase: MAVEN_GPG_PASSPHRASE
112+
113+
- name: Configure Git
114+
run: |
115+
git config user.name "github-actions[bot]"
116+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
117+
118+
- name: Run Maven release:prepare
119+
run: |
120+
VERSION="${{ steps.validate_version.outputs.version }}"
121+
TAG_NAME="${{ steps.validate_version.outputs.tag_name }}"
122+
123+
echo "Preparing release version: $VERSION"
124+
echo "Tag name: $TAG_NAME"
125+
126+
# Run release:prepare with explicit release version
127+
# Maven will automatically calculate the next development version
128+
# Only prepare production modules, exclude all sample modules
129+
# Pass -pl/-am to forked Maven invocations via -Darguments
130+
./mvnw -B release:prepare \
131+
-DreleaseVersion="${VERSION}" \
132+
-Dtag="${TAG_NAME}" \
133+
-DpushChanges=false \
134+
-Darguments="-pl xapi-model,xapi-client,xapi-model-spring-boot-starter -am"
135+
env:
136+
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
137+
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
138+
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
139+
140+
- name: Run Maven release:perform
141+
if: ${{ !github.event.inputs.skip_maven_central }}
142+
run: |
143+
echo "Performing release and deploying to Maven Central"
144+
145+
# Run release:perform to build and deploy
146+
# Only release production modules, exclude all sample modules
147+
# Pass -pl/-am to forked Maven invocations via -Darguments
148+
./mvnw -B release:perform \
149+
-DlocalCheckout=true \
150+
-DeployAtEnd=true \
151+
-Darguments="-pl xapi-model,xapi-client,xapi-model-spring-boot-starter -am"
152+
env:
153+
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
154+
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
155+
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
156+
157+
- name: Skip Maven Central deployment (dry run)
158+
if: ${{ github.event.inputs.skip_maven_central }}
159+
run: |
160+
echo "::warning::Skipping Maven Central deployment as requested"
161+
echo "This is a dry run. Artifacts will NOT be published to Maven Central."
162+
echo "Release commits and tag will still be created and pushed."
163+
164+
- name: Push changes to branch
165+
run: |
166+
TARGET_BRANCH="${{ github.ref_name }}"
167+
TAG_NAME="${{ steps.validate_version.outputs.tag_name }}"
168+
169+
echo "Pushing changes to branch: $TARGET_BRANCH"
170+
171+
# Push the commits created by release:prepare
172+
if ! git push --force-with-lease origin "HEAD:${TARGET_BRANCH}"; then
173+
echo "::error::Failed to push release commits to ${TARGET_BRANCH} due to branch divergence."
174+
echo "The remote branch may have new commits. Please resolve the conflict manually:"
175+
echo " 1. Fetch the latest changes: git fetch origin"
176+
echo " 2. Rebase or merge as needed, then re-run this workflow."
177+
exit 1
178+
fi
179+
180+
# Push the tag created by release:prepare
181+
git push origin "$TAG_NAME"
182+
183+
echo "Pushed release commits and tag to $TARGET_BRANCH"
184+
185+
- name: Create GitHub Release
186+
if: ${{ github.event.inputs.create_github_release }}
187+
uses: actions/create-release@v1
188+
env:
189+
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
190+
with:
191+
tag_name: ${{ steps.validate_version.outputs.tag_name }}
192+
release_name: Release ${{ steps.validate_version.outputs.version }}
193+
body: |
194+
## Release ${{ steps.validate_version.outputs.version }}
195+
196+
This release was created via the manual release workflow.
197+
198+
### Maven Central
199+
Artifacts are available on Maven Central:
200+
- [xapi-model](https://central.sonatype.com/artifact/dev.learning.xapi/xapi-model/${{ steps.validate_version.outputs.version }})
201+
- [xapi-client](https://central.sonatype.com/artifact/dev.learning.xapi/xapi-client/${{ steps.validate_version.outputs.version }})
202+
- [xapi-model-spring-boot-starter](https://central.sonatype.com/artifact/dev.learning.xapi/xapi-model-spring-boot-starter/${{ steps.validate_version.outputs.version }})
203+
204+
### Changes
205+
See commit history for details.
206+
draft: false
207+
prerelease: false
208+
209+
- name: Release Summary
210+
if: always()
211+
run: |
212+
echo "## Release Workflow Summary" >> $GITHUB_STEP_SUMMARY
213+
echo "" >> $GITHUB_STEP_SUMMARY
214+
echo "**Version:** ${{ steps.validate_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
215+
echo "**Tag:** ${{ steps.validate_version.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
216+
echo "**Branch:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
217+
echo "**Maven Central:** ${{ github.event.inputs.skip_maven_central && 'Skipped (dry run)' || 'Deployed' }}" >> $GITHUB_STEP_SUMMARY
218+
echo "**GitHub Release:** ${{ github.event.inputs.create_github_release && 'Created' || 'Skipped' }}" >> $GITHUB_STEP_SUMMARY
219+
echo "" >> $GITHUB_STEP_SUMMARY
220+
221+
if [ "${{ job.status }}" == "success" ]; then
222+
echo "✅ Release completed successfully!" >> $GITHUB_STEP_SUMMARY
223+
else
224+
echo "❌ Release failed. Check the logs for details." >> $GITHUB_STEP_SUMMARY
225+
fi

.github/workflows/release.yml renamed to .github/workflows/release-automated-deprecated.yml

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
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
1+
# DEPRECATED: This workflow has been replaced by manual-release.yml
32
#
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
3+
# This workflow previously automated the release process when a release was created on GitHub.
4+
# It has been deprecated in favor of a manual workflow dispatch approach for better control.
5+
#
6+
# DO NOT USE THIS WORKFLOW - Use the "Manual Release" workflow instead.
7+
# See RELEASING.md for updated release instructions.
8+
#
9+
# This file is kept for reference but the trigger has been disabled.
1210

13-
name: Automated Release
11+
name: Automated Release (DEPRECATED)
1412

15-
on:
16-
release:
17-
types: [created] # Trigger when release is created
13+
# Trigger disabled - workflow will not run automatically
14+
# on:
15+
# release:
16+
# types: [created]
1817

1918
permissions:
2019
contents: write # Required to push commits and update tags

0 commit comments

Comments
 (0)