ci: isolate Maven Central publish secrets from Gradle plugin graph#151
Merged
Conversation
9be743d to
edce589
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3523f52. Configure here.
3523f52 to
8a3eac7
Compare
Split the publish job in two: a `build-artifact` job that runs Gradle (and its plugin graph) but holds no credentials, and a credential-holding `publish` job that only runs curl/jq/gpg from the runner image. The publish job runs in a `maven-production` environment so secrets can move off the repo and behind a branch/reviewer gate. Also pin the `version` to a safe charset before propagating, switch to job/workflow-level env to deduplicate, add Gradle caching to setup-java, and remove the now- unused `.publish/prepare.sh` helper. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A plain shell assignment isn't inherited by the gpg subprocess, so the key imported into the default ~/.gnupg while GITHUB_ENV pointed the later signing step at the empty ephemeral directory — every signature failed. Export it in-step too. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Picks up the bundle-openapi-spec fix to fetch specs from the public bucket. No interface change to verify-openapi-spec or the sync-fern-artifacts caller. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
075214e to
4082a47
Compare
rossmpowell
approved these changes
Jun 26, 2026
rossmpowell
left a comment
Collaborator
There was a problem hiding this comment.
Looks good -- I'm sure it's already on the radar given this is essentially what this PR is doing! But Claude had flagged that we can remove the MAVEN_SIGNATURE_KID secret with this merged
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Splits the single Gradle-driven publish job into a credential-free build-artifact job (runs Gradle and its plugin graph, no secrets) and a credential-holding publish job that runs only
curl/jq/gpgfrom the runner image, behind amaven-productionenvironment. The publish job POSTs a Maven-layout bundle directly to the Sonatype Central Portal (/api/v1/publisher/upload) and polls/statusuntilPUBLISHED/FAILED, replacing thecl.franciscosolis.sonatype-central-uploadGradle plugin that previously had all fiveMAVEN_*secrets exposed to the third-party plugin graph. The two jobs hand off amaven-bundleartifact guarded by aSHA256SUMSintegrity check.Hardening along the way: the parsed
versionis validated against^[A-Za-z0-9._+-]+$before it flows into shell/URL/filesystem contexts; publish secrets and shared coordinates moved to job/workflow-levelenvto dedupe across steps;cache: gradleadded to everysetup-java;actions/checkoutbumped to v6.0.3 (other action pins already latest); and the now-unused.publish/prepare.shGradle-signing helper deleted.Follow-ups required before this can run
maven-productionGitHub Environment, restrict it torefs/heads/main, and attachMAVEN_USERNAME/MAVEN_PASSWORD/MAVEN_SIGNATURE_SECRET_KEY/MAVEN_SIGNATURE_PASSWORDat the environment level; delete the repo-level copies.MAVEN_SIGNATURE_KIDis no longer read by the workflow.Test plan
maven-productionenvironment + attach secrets*-rc1version on a branch, merge, observe the fullcompile → test → tag → build-artifact → publishpipeline🤖 Generated with Claude Code
Note
Medium Risk
Changes the production Maven Central release path and GPG signing flow; misconfiguration of the new
maven-productionenvironment or bundle layout could block or break releases, though secrets are better isolated than before.Overview
Splits release publishing into a secret-free Gradle build and a minimal publish job that talks to Sonatype Central Portal directly, instead of running
./gradlew sonatypeCentralUploadwith all Maven/GPG secrets inside the third-party plugin graph.The new
build-artifactjob assembles jars, POM, and optional module metadata (skipping Gradle publication signing), stages them underdist/with aSHA256SUMSmanifest, and uploads a short-livedmaven-bundleartifact.publishruns in themaven-productionenvironment with onlydownload-artifact, checksum verification, ephemeral GPG signing (.ascplus md5/sha1 sidecars), Maven-layout zip assembly, Portal/upload, and polling/statusuntilPUBLISHEDorFAILED. Thetagjob now exportsversionand rejects unsafe version strings before they hit shell paths or upload URLs.Hardening and housekeeping: workflow-level
ARTIFACT_ID, Gradle cache on all Java setups, pinnedcheckoutv6.0.3 and sharedverify-openapi-spec/ sync-fern at 1.0.3, and removal of.publish/prepare.sh(no longer used for Gradle signing prep).Reviewed by Cursor Bugbot for commit 4082a47. Bugbot is set up for automated code reviews on this repo. Configure here.