From aaee186762630ac184fa5111a07072f2a88bce14 Mon Sep 17 00:00:00 2001 From: Oleg Samarin Date: Fri, 17 Apr 2026 10:01:42 +0300 Subject: [PATCH] Fixed Maven Central publishing timeout and retry failures Split build step into compile+test (mvn package) and deploy (mvn deploy -P release) phases. Deploy step is idempotent: reuses existing Sonatype deployment if one already exists for the version. Release job now polls until PUBLISHED instead of blocking in the build job. GitHub Release publication is also idempotent (checks isDraft before editing). Changed central-publishing-maven-plugin to autoPublish=false (removed waitUntil=published) so upload returns immediately with a deployment ID. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/build.yml | 95 ++++++++++++++++++++++++++----------- pom.xml | 4 +- 2 files changed, 69 insertions(+), 30 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 68a5b369..c4bde45a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -88,6 +88,8 @@ jobs: build: needs: calc_ver runs-on: ubuntu-latest + outputs: + deployment_id: ${{ steps.deploy.outputs.deployment_id }} steps: - uses: actions/checkout@v4 with: @@ -107,13 +109,28 @@ jobs: run: sudo apt-get install -y pandoc - name: Set version run: mvn versions:set -DnewVersion=${{ needs.calc_ver.outputs.project_ver }} --batch-mode - - name: Build + - name: Build and test # xvfb-run provides a virtual display so Swing UI tests don't throw HeadlessException + run: xvfb-run mvn package --batch-mode + - name: Deploy to Maven Central (release only) + id: deploy + if: needs.calc_ver.outputs.release_flag == 'ON' && github.repository == 'nbclaudecodegui/NetbeansClaudeCodeGui' run: | - if [[ "${{ needs.calc_ver.outputs.release_flag }}" == "ON" ]]; then - xvfb-run mvn deploy -P release -DskipTests -DskipDeploy=true --batch-mode + VERSION="${{ needs.calc_ver.outputs.project_ver }}" + AUTH=$(echo -n "$MAVEN_USERNAME:$MAVEN_PASSWORD" | base64 -w0) + + EXISTING_ID=$(curl -sf -H "Authorization: Bearer $AUTH" \ + "https://central.sonatype.com/api/v1/publisher/deployments/search?namespace=io.github.nbclaudecodegui&name=netbeans-claude-code-gui&version=$VERSION" \ + | jq -r '.deployments[0].deploymentId // empty' || echo "") + + if [[ -n "$EXISTING_ID" ]]; then + echo "Reusing existing deployment: $EXISTING_ID" + echo "deployment_id=$EXISTING_ID" >> $GITHUB_OUTPUT else - xvfb-run mvn package --batch-mode + DEPLOY_LOG=$(mktemp) + mvn deploy -P release -DskipTests --batch-mode 2>&1 | tee "$DEPLOY_LOG" + DEPLOYMENT_ID=$(grep -oP '(?<=Deployment ID: )[a-f0-9-]+' "$DEPLOY_LOG" || true) + echo "deployment_id=$DEPLOYMENT_ID" >> $GITHUB_OUTPUT fi env: MAVEN_USERNAME: ${{ secrets.CENTRAL_TOKEN_USERNAME }} @@ -137,41 +154,65 @@ jobs: target/*-docs.html upload-release-files: ${{ needs.calc_ver.outputs.release_flag == 'ON' }} release-upload-url: ${{ needs.calc_ver.outputs.release_upload_url }} - - name: Upload Central bundle - if: needs.calc_ver.outputs.release_flag == 'ON' && github.repository == 'nbclaudecodegui/NetbeansClaudeCodeGui' - uses: actions/upload-artifact@v4 - with: - name: central-bundle - path: target/central-publishing/central-bundle.zip - if-no-files-found: error release: needs: [calc_ver, build] if: needs.calc_ver.outputs.release_flag == 'ON' && github.repository == 'nbclaudecodegui/NetbeansClaudeCodeGui' runs-on: ubuntu-latest steps: - - name: Download Central bundle - uses: actions/download-artifact@v4 - with: - name: central-bundle - path: central-bundle + - name: Publish GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + REL_TAG="${{ needs.calc_ver.outputs.release_tag }}" + IS_DRAFT=$(gh release view "$REL_TAG" --json isDraft -q .isDraft 2>/dev/null || echo "true") + if [[ "$IS_DRAFT" == "false" ]]; then + echo "GitHub Release already published." + else + gh release edit "$REL_TAG" --draft=false --repo ${{ github.repository }} + fi - - name: Publish to Maven Central + - name: Publish to Maven Central and wait run: | AUTH=$(echo -n "$MAVEN_USERNAME:$MAVEN_PASSWORD" | base64 -w0) + DEPLOYMENT_ID="${{ needs.build.outputs.deployment_id }}" + + if [[ -z "$DEPLOYMENT_ID" ]]; then + echo "No deployment ID available, skipping Maven Central publication." + exit 0 + fi + + STATUS=$(curl -sf -H "Authorization: Bearer $AUTH" \ + "https://central.sonatype.com/api/v1/publisher/status?id=$DEPLOYMENT_ID" \ + | jq -r '.deploymentState' || echo "UNKNOWN") + echo "Current deployment state: $STATUS" + + if [[ "$STATUS" == "PUBLISHED" ]]; then + echo "Already published to Maven Central." + exit 0 + fi + + if [[ "$STATUS" != "PENDING" && "$STATUS" != "VALIDATED" && "$STATUS" != "UPLOADING" ]]; then + echo "Unexpected deployment state: $STATUS" && exit 1 + fi + curl --fail --location \ --request POST \ --header "Authorization: Bearer $AUTH" \ - --form "bundle=@central-bundle/central-bundle.zip" \ - "https://central.sonatype.com/api/v1/publisher/upload?publishingType=AUTOMATIC" + "https://central.sonatype.com/api/v1/publisher/publish?id=$DEPLOYMENT_ID" + + for i in $(seq 1 30); do + sleep 30 + STATUS=$(curl -sf -H "Authorization: Bearer $AUTH" \ + "https://central.sonatype.com/api/v1/publisher/status?id=$DEPLOYMENT_ID" \ + | jq -r '.deploymentState') + echo "[$i/30] State: $STATUS" + [[ "$STATUS" == "PUBLISHED" ]] && break + [[ "$STATUS" == "FAILED" ]] && echo "Sonatype publication failed." && exit 1 + done + + [[ "$STATUS" != "PUBLISHED" ]] && echo "Timed out waiting for Maven Central publication." && exit 1 + echo "Published successfully to Maven Central." env: MAVEN_USERNAME: ${{ secrets.CENTRAL_TOKEN_USERNAME }} MAVEN_PASSWORD: ${{ secrets.CENTRAL_TOKEN_PASSWORD }} - - - name: Publish GitHub Release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh release edit "${{ needs.calc_ver.outputs.release_tag }}" \ - --draft=false \ - --repo ${{ github.repository }} diff --git a/pom.xml b/pom.xml index c76667dd..47605c0e 100644 --- a/pom.xml +++ b/pom.xml @@ -517,9 +517,7 @@ true central - true - published - ${skipDeploy} + false