@@ -87,34 +87,136 @@ tasks.register('publishToMavenCentral') {
8787 dependsOn ' createCentralBundle'
8888
8989 doLast {
90- def username = project. findProperty(' mavenCentralUsername' ) ?: System . getenv(' MAVEN_CENTRAL_USERNAME' )
91- def token = project. findProperty(' mavenCentralToken' ) ?: System . getenv(' MAVEN_CENTRAL_TOKEN' )
90+ def token = (project. findProperty(' mavenCentralToken' ) ?: System . getenv(' MAVEN_CENTRAL_TOKEN' ))?. trim()
9291
93- if (! username || ! token) {
94- throw new GradleException (' Maven Central credentials not found. Set MAVEN_CENTRAL_USERNAME and MAVEN_CENTRAL_TOKEN environment variables .' )
92+ if (! token) {
93+ throw new GradleException (' Maven Central token not found. Set MAVEN_CENTRAL_TOKEN environment variable or -PmavenCentralToken property .' )
9594 }
9695
9796 def bundleFile = layout. buildDirectory. file(' distributions/central-bundle.zip' ). get(). asFile
9897
98+ if (! bundleFile. exists()) {
99+ throw new GradleException (" Bundle file not found: ${ bundleFile.absolutePath} " )
100+ }
101+
99102 def uploadUrl = ' https://central.sonatype.com/api/v1/publisher/upload?publishingType=AUTOMATIC'
100103
101104 println " Uploading bundle to Maven Central Portal..."
105+ println " Bundle file: ${ bundleFile.absolutePath} (${ bundleFile.length()} bytes)"
106+ println " Token length: ${ token.length()} characters"
107+
108+ // Create a temporary file to capture the response
109+ def responseFile = File . createTempFile(" maven-central-response" , " .json" )
110+ responseFile. deleteOnExit()
111+
112+ // Build the authorization header separately to avoid interpolation issues
113+ def authHeader = " Authorization: Bearer ${ token} "
102114
103115 def process = [
104116 ' curl' , ' -X' , ' POST' ,
105- ' -H' , " Authorization: Bearer ${ token} " ,
117+ ' --fail-with-body' ,
118+ ' -w' , ' \n %{http_code}' ,
119+ ' -o' , responseFile. absolutePath,
120+ ' -H' , authHeader,
106121 ' -F' , " bundle=@${ bundleFile.absolutePath} " ,
107122 uploadUrl
108123 ]. execute()
109124
110- process. waitForProcessOutput(System . out, System . err)
125+ def output = new StringBuilder ()
126+ def error = new StringBuilder ()
127+ process. waitForProcessOutput(output, error)
111128 def exitCode = process. exitValue()
112129
113- if (exitCode != 0 ) {
114- throw new GradleException (" Failed to upload bundle to Maven Central. Exit code: ${ exitCode} " )
130+ // Read the response
131+ def response = responseFile. text
132+ def httpCode = output. toString(). trim(). split(' \n ' ). last()
133+
134+ println " HTTP Status: ${ httpCode} "
135+ println " Response: ${ response} "
136+
137+ // Check for errors in response
138+ if (exitCode != 0 || response. contains(' "error"' )) {
139+ def errorMsg = " Failed to upload bundle to Maven Central.\n "
140+ errorMsg + = " Exit code: ${ exitCode} \n "
141+ errorMsg + = " HTTP Status: ${ httpCode} \n "
142+ errorMsg + = " Response: ${ response} \n "
143+ if (error. length() > 0 ) {
144+ errorMsg + = " Error output: ${ error.toString()} "
145+ }
146+ throw new GradleException (errorMsg)
115147 }
116148
117149 println " Bundle uploaded successfully!"
150+ println " Response: ${ response} "
151+ }
152+ }
153+
154+ // Task to test Maven Central authentication without uploading
155+ tasks. register(' testMavenCentralAuth' ) {
156+ group = ' verification'
157+ description = ' Test Maven Central Portal authentication'
158+
159+ doLast {
160+ def token = (project. findProperty(' mavenCentralToken' ) ?: System . getenv(' MAVEN_CENTRAL_TOKEN' ))?. trim()
161+
162+ if (! token) {
163+ throw new GradleException (' Maven Central token not found. Set MAVEN_CENTRAL_TOKEN environment variable or -PmavenCentralToken property.' )
164+ }
165+
166+ println " Testing Maven Central Portal authentication..."
167+ println " Token length: ${ token.length()} characters"
168+ println " Token starts with: ${ token.take(10)} ..."
169+
170+ // Test with a simple GET request to check authentication
171+ // Using the deployments list endpoint which is known to work
172+ def testUrl = ' https://central.sonatype.com/api/v1/publisher/deployments'
173+
174+ // Create a temporary file to capture the response
175+ def responseFile = File . createTempFile(" maven-central-test" , " .json" )
176+ responseFile. deleteOnExit()
177+
178+ // Build the authorization header
179+ def authHeader = " Authorization: Bearer ${ token} "
180+
181+ println " Testing authentication with GET request..."
182+ println " URL: ${ testUrl} "
183+
184+ def process = [
185+ ' curl' , ' -X' , ' GET' ,
186+ ' -v' ,
187+ ' --fail-with-body' ,
188+ ' -w' , ' \n %{http_code}' ,
189+ ' -o' , responseFile. absolutePath,
190+ ' -H' , authHeader,
191+ testUrl
192+ ]. execute()
193+
194+ def output = new StringBuilder ()
195+ def error = new StringBuilder ()
196+ process. waitForProcessOutput(output, error)
197+ def exitCode = process. exitValue()
198+
199+ // Read the response
200+ def response = responseFile. text
201+ def httpCode = output. toString(). trim(). split(' \n ' ). last()
202+
203+ println " \n === Authentication Test Results ==="
204+ println " Exit code: ${ exitCode} "
205+ println " HTTP Status: ${ httpCode} "
206+ println " Response: ${ response} "
207+ println " Curl verbose output:"
208+ println error. toString()
209+
210+ if (exitCode != 0 || response. contains(' "error"' )) {
211+ def errorMsg = " \n ❌ Authentication test FAILED\n "
212+ errorMsg + = " Exit code: ${ exitCode} \n "
213+ errorMsg + = " HTTP Status: ${ httpCode} \n "
214+ errorMsg + = " Response: ${ response} \n "
215+ throw new GradleException (errorMsg)
216+ }
217+
218+ println " \n ✅ Authentication test PASSED"
219+ println " Your token is valid and working correctly."
118220 }
119221}
120222
0 commit comments