Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 22 additions & 131 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,161 +1,52 @@
# This workflow automates the release process when a release is created on GitHub
# It uses Maven release plugin to manage versions and deploys to Maven Central
# 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 release in GitHub UI with tag format: vX.Y.Z (e.g., v1.2.0)
# 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 commits
# - Use Maven release:prepare to update versions and create release commit
# - Use Maven release:perform to build and deploy artifacts to Maven Central
# - Move the tag to point to the actual release commit
# - 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] # Trigger when release is created
types: [created] # Only fire when a release is created

permissions:
contents: write # Required to push commits and update tags
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 "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: Delete user-created tag
run: |
TAG_NAME="${{ github.event.release.tag_name }}"

# Delete the tag created by the user (will be recreated by release:prepare)
git tag -d "$TAG_NAME" || true
git push origin ":refs/tags/$TAG_NAME" || true

echo "Deleted user-created tag $TAG_NAME"

- 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"

# Run release:prepare with explicit release version
# Maven will automatically calculate the next development version
# Only prepare production modules, exclude all sample modules
# Pass -pl/-am to forked Maven invocations via -Darguments
./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"

# Run release:perform to build and deploy
# Only release production modules, exclude all sample modules
# Pass -pl/-am to forked Maven invocations via -Darguments
./mvnw -B release:perform \
-DlocalCheckout=true \
-DeployAtEnd=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
run: |
TARGET_BRANCH="${{ steps.target_branch.outputs.target_branch }}"
TAG_NAME="${{ github.event.release.tag_name }}"

echo "Pushing changes to branch: $TARGET_BRANCH"

# Push the commits created by release:prepare
if ! git push --force-with-lease origin "HEAD:${TARGET_BRANCH}"; then
echo "::error::Failed to push release commits to ${TARGET_BRANCH} due to branch divergence."
echo "The remote branch may have new commits. Please resolve the conflict manually:"
echo " 1. Fetch the latest changes: git fetch origin"
echo " 2. Rebase or merge as needed, then push again with --force-with-lease."
exit 1
fi

# Push the tag created by release:prepare
git push origin "$TAG_NAME"

echo "Pushed release commits and tag to $TARGET_BRANCH"





Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing whitespace should be removed. The file should end cleanly after the meaningful content.

Copilot uses AI. Check for mistakes.