v2.1.0 #10
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | |
| 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" | |
| # Verify credentials are set | |
| if [ -z "$SONATYPE_USERNAME" ] || [ -z "$SONATYPE_PASSWORD" ]; then | |
| echo "ERROR: Sonatype credentials not set" | |
| exit 1 | |
| fi | |
| 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..." | |
| echo "This may take several minutes..." | |
| mvn deploy -P release \ | |
| -Dgpg.keyname="$KEY_ID" \ | |
| -Dgpg.passphrase="$GPG_PASSPHRASE" \ | |
| -X 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" deploy.log | tail -50 | |
| echo "" | |
| echo "=== Full error trace (last 200 lines) ===" | |
| mvn deploy -P release \ | |
| -Dgpg.keyname="$KEY_ID" \ | |
| -Dgpg.passphrase="$GPG_PASSPHRASE" \ | |
| -e 2>&1 | tail -200 | |
| exit 1 | |
| } | |
| echo "✅ Deployment completed successfully!" | |
| echo "" | |
| echo "📋 Next Steps:" | |
| echo "1. Check staging repository at: https://central.sonatype.com/" | |
| echo "2. Wait 10-30 minutes for sync to Maven Central" | |
| echo "3. Verify at: https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/" | |
| - name: Check Staging Repository Status | |
| env: | |
| SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} | |
| SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} | |
| run: | | |
| echo "Checking staging repository status..." | |
| echo "Note: This requires Sonatype Central API access" | |
| echo "" | |
| echo "To check manually:" | |
| echo "1. Go to: https://central.sonatype.com/" | |
| echo "2. Log in with your Sonatype credentials" | |
| echo "3. Check 'Staging Repositories' for your artifact" | |
| echo "4. Status should be 'Closed' or 'Released'" | |
| echo "" | |
| echo "If status is 'Open', you may need to:" | |
| echo "- Close the repository" | |
| echo "- Release the repository" | |
| echo "" | |
| echo "With autoPublish=true, this should happen automatically" | |
| - name: Wait and Verify Maven Central Sync | |
| run: | | |
| VERSION=${{ steps.get_version.outputs.version || steps.set_version.outputs.version }} | |
| echo "Waiting 30 seconds before checking Maven Central..." | |
| sleep 30 | |
| echo "Checking if artifact is available on Maven Central..." | |
| MAX_ATTEMPTS=12 | |
| ATTEMPT=0 | |
| while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do | |
| ATTEMPT=$((ATTEMPT + 1)) | |
| echo "Attempt $ATTEMPT/$MAX_ATTEMPTS: Checking Maven Central..." | |
| if curl -s -f "https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/" > /dev/null 2>&1; then | |
| echo "✅ Artifact is now available on Maven Central!" | |
| echo "URL: https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/" | |
| exit 0 | |
| else | |
| if [ $ATTEMPT -lt $MAX_ATTEMPTS ]; then | |
| echo "⏳ Not yet available. Waiting 2 minutes before next check..." | |
| sleep 120 | |
| fi | |
| fi | |
| done | |
| echo "⚠️ Artifact not yet available on Maven Central after $((MAX_ATTEMPTS * 2)) minutes" | |
| echo "This is normal - sync can take 10-30 minutes" | |
| echo "Please check manually at:" | |
| echo "https://repo1.maven.org/maven2/io/translateplus/translateplus-java/$VERSION/" | |
| echo "" | |
| echo "Also check Sonatype Central for any validation errors:" | |
| echo "https://central.sonatype.com/" | |
| - 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>" |