Skip to content

v2.1.3

v2.1.3 #14

Workflow file for this run

name: Publish to Maven Central
on:
release:
types: [created]
workflow_dispatch:
inputs:
version:
description: 'Version to publish (e.g., 1.0.0)'
required: true
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up JDK 11
uses: actions/setup-java@v4
with:
java-version: '11'
distribution: 'temurin'
cache: maven
- name: Configure GPG
id: gpg_setup
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
mkdir -p ~/.gnupg
chmod 700 ~/.gnupg
echo "pinentry-mode loopback" > ~/.gnupg/gpg.conf
chmod 600 ~/.gnupg/gpg.conf
# Import the private key
echo "Importing GPG private key..."
echo "$GPG_PRIVATE_KEY" | gpg --batch --import
# List keys for debugging
echo "=== GPG Keys After Import ==="
gpg --list-secret-keys --keyid-format LONG
# Extract key ID from the imported key (always extract, don't use secret)
# Try multiple methods to extract the key ID
KEY_ID=$(gpg --list-secret-keys --keyid-format LONG 2>/dev/null | grep -E "^sec" | head -1 | sed -n 's/.*\/\([A-F0-9]\{16\}\).*/\1/p')
if [ -z "$KEY_ID" ]; then
# Fallback: try with different format
KEY_ID=$(gpg --list-secret-keys --keyid-format LONG 2>/dev/null | grep -E "^sec" | head -1 | awk -F'/' '{print $2}' | awk '{print $1}')
fi
if [ -z "$KEY_ID" ]; then
# Last resort: try with pub
KEY_ID=$(gpg --list-secret-keys --keyid-format LONG 2>/dev/null | grep -E "^pub" | head -1 | sed -n 's/.*\/\([A-F0-9]\{16\}\).*/\1/p')
fi
if [ -z "$KEY_ID" ]; then
echo "ERROR: Could not extract GPG key ID from imported key"
echo "=== Full key listing ==="
gpg --list-secret-keys --keyid-format LONG
echo "=== Full key listing (SHORT format) ==="
gpg --list-secret-keys --keyid-format SHORT
exit 1
fi
echo "Extracted GPG Key ID: $KEY_ID"
# Verify the key exists
if ! gpg --list-secret-keys --keyid-format LONG | grep -q "$KEY_ID"; then
echo "ERROR: Extracted key ID $KEY_ID not found in keyring"
echo "=== Full key listing ==="
gpg --list-secret-keys --keyid-format LONG
exit 1
fi
# Trust the imported key (ultimate trust)
echo "Trusting key $KEY_ID..."
echo "$KEY_ID:6:" | gpg --import-ownertrust || true
# Verify trust
gpg --check-trustdb || true
echo "key_id=$KEY_ID" >> $GITHUB_OUTPUT
echo "✅ GPG Key ID configured: $KEY_ID"
- name: Extract version from tag
id: get_version
if: github.event_name == 'release'
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Extracted version: $VERSION"
- name: Set version from input
id: set_version
if: github.event_name == 'workflow_dispatch'
run: |
echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
- name: Update version in pom.xml
run: |
VERSION=${{ steps.get_version.outputs.version || steps.set_version.outputs.version }}
mvn versions:set -DnewVersion=$VERSION
mvn versions:commit
- name: Run tests
run: mvn clean test
- name: Build project
run: mvn clean package -DskipTests
- name: Configure Maven Settings
env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
run: |
mkdir -p ~/.m2
# Sonatype Central tokens come as username/password pairs
# The username is the token identifier and password is the token secret
if [ -z "$SONATYPE_USERNAME" ] || [ -z "$SONATYPE_PASSWORD" ]; then
echo "ERROR: Sonatype credentials not set"
echo ""
echo "Sonatype Central requires token-based authentication."
echo "To generate a token:"
echo "1. Go to https://central.sonatype.com/"
echo "2. Log in and go to your profile/settings"
echo "3. Generate a new User Token"
echo "4. You'll receive a username and password pair"
echo "5. Add them as GitHub secrets:"
echo " - SONATYPE_USERNAME: (token username)"
echo " - SONATYPE_PASSWORD: (token password/secret)"
exit 1
fi
# Create Maven settings.xml with Sonatype Central credentials
# The server ID must be 'central' to match pom.xml publishingServerId
cat > ~/.m2/settings.xml <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>central</id>
<username>${SONATYPE_USERNAME}</username>
<password>${SONATYPE_PASSWORD}</password>
</server>
</servers>
</settings>
EOF
echo "✅ Maven settings.xml configured with token authentication"
echo "✅ Sonatype credentials configured"
- name: Publish to Maven Central
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
KEY_ID=${{ steps.gpg_setup.outputs.key_id }}
if [ -z "$KEY_ID" ]; then
echo "ERROR: GPG Key ID is empty"
gpg --list-secret-keys --keyid-format LONG
exit 1
fi
echo "Using GPG Key ID: $KEY_ID"
# Final verification: key must exist
if ! gpg --list-secret-keys --keyid-format LONG 2>/dev/null | grep -q "$KEY_ID"; then
echo "ERROR: Key $KEY_ID not found in keyring"
echo "=== Available keys ==="
gpg --list-secret-keys --keyid-format LONG
exit 1
fi
# Test signing with the key
echo "Testing GPG signing..."
echo "test" | gpg --batch --yes --pinentry-mode loopback --sign --local-user "$KEY_ID" --output /dev/null 2>&1 || {
echo "WARNING: GPG signing test failed, but continuing..."
}
# Verify artifacts are built before deploying
echo "Verifying artifacts before deployment..."
mvn clean package -P release \
-Dgpg.keyname="$KEY_ID" \
-Dgpg.passphrase="$GPG_PASSPHRASE" \
-DskipTests
echo "Checking generated artifacts..."
ls -lah target/*.jar target/*.asc target/*.pom 2>/dev/null || echo "No artifacts found in target/"
# Check if version already exists
VERSION=${{ steps.get_version.outputs.version || steps.set_version.outputs.version }}
echo "Checking if version $VERSION already exists..."
if curl -s "https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/" | grep -q "$VERSION"; then
echo "⚠️ WARNING: Version $VERSION may already exist on Maven Central"
echo "Continuing anyway (will fail if version truly exists)..."
fi
echo "Publishing to Maven Central using central-publishing-maven-plugin..."
echo "This plugin handles upload, validation, and release automatically."
echo "With autoPublish=true, it will:"
echo " 1. Upload artifacts to staging"
echo " 2. Automatically close and validate"
echo " 3. Automatically release to Maven Central"
echo " 4. Wait until published (waitUntil=published)"
echo ""
echo "This may take 5-10 minutes..."
# Use central-publishing-maven-plugin which handles everything
# It will upload, sign, validate, and publish automatically
mvn clean deploy -P release \
-Dgpg.keyname="$KEY_ID" \
-Dgpg.passphrase="$GPG_PASSPHRASE" \
2>&1 | tee deploy.log || {
echo "=== Deployment failed ==="
echo "=== Last 100 lines of deploy.log ==="
tail -100 deploy.log
echo ""
echo "=== Searching for error messages ==="
grep -i "error\|fail\|exception\|401\|unauthorized" deploy.log | tail -50
echo ""
echo "=== Authentication check ==="
if grep -qi "401\|unauthorized\|token" deploy.log; then
echo ""
echo "⚠️ AUTHENTICATION ERROR DETECTED"
echo ""
echo "Sonatype Central requires token-based authentication."
echo "To fix this:"
echo "1. Go to https://central.sonatype.com/"
echo "2. Log in and navigate to your profile/settings"
echo "3. Generate a new User Token"
echo "4. Add it as SONATYPE_TOKEN secret in GitHub repository settings"
echo "5. The workflow will automatically use the token if available"
echo ""
fi
echo ""
echo "=== Full error trace (last 200 lines) ==="
mvn clean deploy -P release \
-Dgpg.keyname="$KEY_ID" \
-Dgpg.passphrase="$GPG_PASSPHRASE" \
-e 2>&1 | tail -200
exit 1
}
echo ""
echo "Checking deployment status..."
if grep -qi "published\|released\|successfully published" deploy.log; then
echo "✅✅✅ SUCCESS! Artifacts have been published to Maven Central!"
echo ""
echo "The central-publishing-maven-plugin with autoPublish=true has:"
echo " ✅ Uploaded artifacts to staging"
echo " ✅ Closed and validated the staging repository"
echo " ✅ Released to Maven Central"
echo " ✅ Waited until published"
echo ""
VERSION=${{ steps.get_version.outputs.version || steps.set_version.outputs.version }}
echo "📦 Published version: $VERSION"
echo "🔗 Maven Central URL: https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/"
echo ""
echo "⏱️ Sync time: Usually available immediately, but can take up to 10 minutes"
elif grep -q "central-publishing-maven-plugin" deploy.log; then
echo "✅ central-publishing-maven-plugin executed"
echo "⚠️ Publishing may still be in progress. Check logs above for status."
echo ""
VERSION=${{ steps.get_version.outputs.version || steps.set_version.outputs.version }}
echo "📋 Next Steps:"
echo "1. Check staging repository at: https://central.sonatype.com/"
echo "2. Verify at: https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/"
else
echo "⚠️ Note: Check logs above for central-publishing-maven-plugin execution"
echo ""
VERSION=${{ steps.get_version.outputs.version || steps.set_version.outputs.version }}
echo "📋 Manual verification:"
echo "1. Check staging repository at: https://central.sonatype.com/"
echo "2. Verify at: https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/"
fi
- name: Verify Publication Status
run: |
VERSION=${{ steps.get_version.outputs.version || steps.set_version.outputs.version }}
echo "🔍 Verifying publication status..."
echo ""
echo "With autoPublish=true and waitUntil=published, the central-publishing-maven-plugin"
echo "should have automatically handled the entire publication process."
echo ""
echo "If the deployment succeeded, your artifact should be:"
echo " ✅ Published to Maven Central"
echo " ✅ Available at: https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/"
echo ""
echo "If you need to manually verify or troubleshoot:"
echo "1. Go to: https://central.sonatype.com/"
echo "2. Log in with your Sonatype credentials"
echo "3. Navigate to 'Staging Repositories'"
echo "4. Look for repository with groupId 'io.translateplus' and version '$VERSION'"
echo "5. Check the status:"
echo " - 'Released' = ✅ Successfully published (syncing to Maven Central)"
echo " - 'Closed' = ⚠️ Validated but not released (click 'Release')"
echo " - 'Open' = ⚠️ Not validated (click 'Close', then 'Release')"
echo ""
echo "Note: With autoPublish=true, status should be 'Released' automatically."
- name: Check Sonatype Central Staging Status
env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
run: |
VERSION=${{ steps.get_version.outputs.version || steps.set_version.outputs.version }}
echo "🔍 Checking Sonatype Central staging repository status..."
echo ""
echo "⚠️ IMPORTANT: Manual verification required"
echo ""
echo "Please check your staging repository status at:"
echo "👉 https://central.sonatype.com/"
echo ""
echo "Steps to verify:"
echo "1. Log in with your Sonatype credentials"
echo "2. Go to 'Staging Repositories' or 'Staging Profiles'"
echo "3. Search for 'io.translateplus' or 'translateplus-java'"
echo "4. Check the status of the repository:"
echo ""
echo " Status: 'Open'"
echo " → Action: Click 'Close' button (validates artifacts)"
echo " → Wait for validation to complete"
echo ""
echo " Status: 'Closed'"
echo " → Action: Click 'Release' button (publishes to Maven Central)"
echo " → This will make it available on Maven Central"
echo ""
echo " Status: 'Released'"
echo " → ✅ Success! Artifact is being synced to Maven Central"
echo " → Wait 10-30 minutes for sync to complete"
echo ""
echo " Status: 'Failed' or shows errors"
echo " → Check the 'Activity' tab for validation errors"
echo " → Common issues:"
echo " - GPG signature not found on keyserver"
echo " - Missing sources/javadoc"
echo " - POM validation errors"
echo ""
echo "If the repository is still 'Open' or 'Closed', the autoPublish"
echo "may not have worked. You'll need to manually close and release it."
- name: Wait and Verify Maven Central Sync
run: |
VERSION=${{ steps.get_version.outputs.version || steps.set_version.outputs.version }}
echo "⏳ Waiting 2 minutes before checking Maven Central..."
echo "(This gives time for Sonatype Central to process the release)"
sleep 120
echo ""
echo "🔍 Checking if artifact is available on Maven Central..."
echo "URL: https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/"
echo ""
MAX_ATTEMPTS=15
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
ATTEMPT=$((ATTEMPT + 1))
echo "Attempt $ATTEMPT/$MAX_ATTEMPTS: Checking Maven Central..."
# Check if the version directory exists
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/")
if [ "$HTTP_CODE" = "200" ]; then
echo ""
echo "✅✅✅ SUCCESS! Artifact is now available on Maven Central! ✅✅✅"
echo ""
echo "📦 Published version: $VERSION"
echo "🔗 URL: https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/"
echo ""
echo "📝 Maven dependency:"
echo "<dependency>"
echo " <groupId>io.translateplus</groupId>"
echo " <artifactId>translateplus-java</artifactId>"
echo " <version>$VERSION</version>"
echo "</dependency>"
echo ""
echo "🎉 Publication complete!"
exit 0
elif [ "$HTTP_CODE" = "404" ]; then
if [ $ATTEMPT -lt $MAX_ATTEMPTS ]; then
echo "⏳ Not yet available (404). Waiting 3 minutes before next check..."
echo " (Sync typically takes 10-30 minutes after release)"
sleep 180
fi
else
echo "⚠️ Unexpected HTTP code: $HTTP_CODE"
if [ $ATTEMPT -lt $MAX_ATTEMPTS ]; then
echo " Waiting 3 minutes before retry..."
sleep 180
fi
fi
done
echo ""
echo "⚠️ Artifact not yet available on Maven Central after $((MAX_ATTEMPTS * 3)) minutes"
echo ""
echo "This could mean:"
echo "1. The artifact hasn't been released from Sonatype Central yet"
echo "2. The sync is taking longer than usual (can take up to 2 hours)"
echo ""
echo "🔍 Please verify:"
echo "1. Check Sonatype Central: https://central.sonatype.com/"
echo " → Ensure repository status is 'Released' (not 'Open' or 'Closed')"
echo ""
echo "2. Check Maven Central directly:"
echo " → https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/"
echo ""
echo "3. If repository is still 'Open' or 'Closed' in Sonatype Central:"
echo " → Manually close and release it"
echo " → Then wait 10-30 minutes for sync"
echo ""
echo "4. Check for validation errors in Sonatype Central Activity tab"
- name: Verify publication
run: |
VERSION=${{ steps.get_version.outputs.version || steps.set_version.outputs.version }}
echo "📦 Published version: $VERSION"
echo ""
echo "🔍 Check these URLs:"
echo "1. Sonatype Central (staging): https://central.sonatype.com/"
echo "2. Maven Central (after sync): https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/"
echo ""
echo "⏱️ Sync time: Usually 10-30 minutes after release"
echo ""
echo "📝 Maven dependency:"
echo "<dependency>"
echo " <groupId>io.translateplus</groupId>"
echo " <artifactId>translateplus-java</artifactId>"
echo " <version>$VERSION</version>"
echo "</dependency>"