1+ // 公共方法:获取认证信息
2+ def getSonatypeCredentials () {
3+ def username = project. findProperty(' ossrhUsername' ) ?: System . getenv(' OSSRH_USERNAME' )
4+ def password = project. findProperty(' ossrhPassword' ) ?: System . getenv(' OSSRH_PASSWORD' )
5+
6+ if (! username || ! password) {
7+ throw new GradleException (' OSSRH credentials are required for Sonatype API operations' )
8+ }
9+
10+ def auth = " ${ username} :${ password} " . bytes. encodeBase64(). toString()
11+ return " Bearer ${ auth} "
12+ }
13+
14+ // 公共方法:发送 HTTP 请求
15+ def callSonatypeApi (String method , String url , Closure responseHandler = null ) {
16+ try {
17+ def connection = new URL (" https://ossrh-staging-api.central.sonatype.com" + url). openConnection() as HttpURLConnection
18+ connection. requestMethod = method
19+ connection. setRequestProperty(" Authorization" , getSonatypeCredentials())
20+
21+ if (method == " POST" ) {
22+ connection. setRequestProperty(" Content-Type" , " application/json" )
23+ connection. doOutput = true
24+ }
25+
26+ def responseCode = connection. responseCode
27+ def responseMessage = connection. responseMessage
28+
29+ if (responseHandler) {
30+ responseHandler. call(connection, responseCode, responseMessage)
31+ } else {
32+ if (responseCode >= 200 && responseCode < 300 ) {
33+ println " Sonatype API call successful: ${ responseCode} ${ responseMessage} "
34+ def inputStream = connection. inputStream
35+ if (inputStream) {
36+ println " ${ inputStream.text} "
37+ }
38+ } else {
39+ println " Sonatype API call failed: ${ responseCode} ${ responseMessage} "
40+ def errorStream = connection. errorStream
41+ if (errorStream) {
42+ def errorText = errorStream. text
43+ println " Error details: ${ errorText} "
44+ }
45+ }
46+ }
47+
48+ return responseCode
49+ } catch (Exception e) {
50+ throw new GradleException (" Failed to call Sonatype API: ${ e.message} " , e)
51+ }
52+ }
53+
54+ // list sonatype staging repositories
55+ tasks. register(' sonatypeList' ) {
56+ group = ' publishing'
57+ description = ' List Sonatype staging repositories'
58+
59+ onlyIf {
60+ ! project. version. endsWith(' SNAPSHOT' )
61+ }
62+
63+ doLast {
64+ def url = " /manual/search/repositories?ip=any&profile_id=${ project.group} "
65+ callSonatypeApi(" GET" , url)
66+ }
67+ }
68+
69+ // notify sonatype upload
70+ tasks. register(' sonatypeUpload' ) {
71+ group = ' publishing'
72+ description = ' Notify Sonatype that upload is complete'
73+
74+ onlyIf {
75+ ! project. version. endsWith(' SNAPSHOT' )
76+ }
77+
78+ doLast {
79+ def url = " /manual/upload/defaultRepository/${ project.group} "
80+ callSonatypeApi(" POST" , url) { connection , responseCode , responseMessage ->
81+ if (responseCode >= 200 && responseCode < 300 ) {
82+ println " Successfully notified Sonatype Staging API: ${ responseCode} ${ responseMessage} "
83+ } else {
84+ println " Failed to notify Sonatype Staging API: ${ responseCode} ${ responseMessage} "
85+ def errorText
86+ def errorStream = connection. errorStream
87+ if (errorStream) {
88+ errorText = errorStream. text
89+ println " Error details: ${ errorText} "
90+ } else {
91+ errorText = " No error details available"
92+ }
93+ throw new GradleException (" Failed to notify Sonatype Staging API: ${ responseCode} ${ responseMessage} \n Error details: ${ errorText} " )
94+ }
95+ }
96+ }
97+ }
98+
99+ // 上传到指定仓库
100+ tasks. register(' sonatypeUploadToRepository' ) {
101+ group = ' publishing'
102+ description = ' Upload to a specific Sonatype repository (requires -PrepositoryKey=<key>)'
103+
104+ // 检查是否提供了 repositoryKey 参数
105+ onlyIf {
106+ if (! project. hasProperty(' repositoryKey' )) {
107+ throw new GradleException (' Repository key is required. Use -PrepositoryKey=<key>' )
108+ }
109+ return true
110+ }
111+
112+ doLast {
113+ def repositoryKey = project. property(' repositoryKey' )
114+ def url = " /manual/upload/repository/${ repositoryKey} "
115+ callSonatypeApi(" POST" , url) { connection , responseCode , responseMessage ->
116+ if (responseCode >= 200 && responseCode < 300 ) {
117+ println " Successfully uploaded to repository ${ repositoryKey} : ${ responseCode} ${ responseMessage} "
118+ } else {
119+ println " Failed to upload to repository ${ repositoryKey} : ${ responseCode} ${ responseMessage} "
120+ def errorStream = connection. errorStream
121+ if (errorStream) {
122+ def errorText = errorStream. text
123+ println " Error details: ${ errorText} "
124+ }
125+ throw new GradleException (" Failed to upload to repository ${ repositoryKey} : ${ responseCode} ${ responseMessage} " )
126+ }
127+ }
128+ }
129+ }
130+
131+ // 删除指定仓库
132+ tasks. register(' sonatypeDropRepository' ) {
133+ group = ' publishing'
134+ description = ' Drop a specific Sonatype repository (requires -PrepositoryKey=<key>)'
135+
136+ // 检查是否提供了 repositoryKey 参数
137+ onlyIf {
138+ if (! project. hasProperty(' repositoryKey' )) {
139+ throw new GradleException (' Repository key is required. Use -PrepositoryKey=<key>' )
140+ }
141+ return true
142+ }
143+
144+ doLast {
145+ def repositoryKey = project. property(' repositoryKey' )
146+ def url = " /manual/drop/repository/${ repositoryKey} "
147+ callSonatypeApi(" DELETE" , url) { connection , responseCode , responseMessage ->
148+ if (responseCode >= 200 && responseCode < 300 ) {
149+ println " Successfully dropped repository ${ repositoryKey} : ${ responseCode} ${ responseMessage} "
150+ } else {
151+ println " Failed to drop repository ${ repositoryKey} : ${ responseCode} ${ responseMessage} "
152+ def errorStream = connection. errorStream
153+ if (errorStream) {
154+ def errorText = errorStream. text
155+ println " Error details: ${ errorText} "
156+ }
157+ throw new GradleException (" Failed to drop repository ${ repositoryKey} : ${ responseCode} ${ responseMessage} " )
158+ }
159+ }
160+ }
161+ }
0 commit comments