Skip to content

Commit 0446a10

Browse files
Use JReleaser to publish to new Maven Central API
Publishing to Maven Central using OSSRH is deprecated and is sunset on 2025-06-30. The build needs to be migrated to use the Central Publishing Portal. There is currently no support for this in Gradle's own publishing capability, and no official Sonatype Gradle publishing plugin. JReleaser is currently recommended by Sonatype for Gradle publishing to Maven Central. Signed-off-by: Mark S. Lewis <[email protected]>
1 parent fd50d8a commit 0446a10

File tree

5 files changed

+117
-97
lines changed

5 files changed

+117
-97
lines changed

.github/workflows/release.yml

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,7 @@ env:
1515
IMAGE_NAME: ${{ github.repository_owner }}/fabric-javaenv
1616

1717
jobs:
18-
# Publishing steps to both the Github Packages and the Sonatype
19-
publishjars:
20-
strategy:
21-
fail-fast: false
22-
matrix:
23-
publish_target:
24-
- publishAllPublicationsToGithubPackagesRepository
25-
- publishAllPublicationsToReleaseRepository
18+
publish-github:
2619
runs-on: ubuntu-latest
2720
permissions:
2821
contents: read
@@ -34,18 +27,38 @@ jobs:
3427
distribution: "temurin"
3528
java-version: 21
3629
- uses: gradle/actions/setup-gradle@v4
37-
- name: Push to registry ${{ matrix.publish_target }}
30+
- name: Publish to GitHub Packages
3831
run: |
39-
set -xev
40-
./gradlew -Psigning.key="${SIGNING_KEY}" -Psigning.password="${SIGNING_PASSWORD}" -PossrhUsername="${OSSRH_USER}" -PossrhPassword="${OSSRH_PASSWORD}" ${TARGET}
32+
./gradlew publishAllPublicationsToGitHubRepository
4133
env:
42-
SIGNING_PASSWORD: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
43-
SIGNING_KEY: ${{ secrets.OSSRH_GPG_SECRET_KEY }}
44-
OSSRH_USER: ${{ secrets.OSSRH_USERNAME }}
45-
OSSRH_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
46-
TARGET: ${{ matrix.publish_target }}
34+
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
35+
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.OSSRH_GPG_SECRET_KEY }}
4736
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4837

38+
publish-maven:
39+
runs-on: ubuntu-latest
40+
permissions:
41+
contents: read
42+
steps:
43+
- uses: actions/checkout@v4
44+
- uses: actions/setup-java@v4
45+
with:
46+
distribution: "temurin"
47+
java-version: 21
48+
- uses: gradle/actions/setup-gradle@v4
49+
- name: Publish to local staging
50+
run: |
51+
./gradlew publishAllPublicationsToStagingRepository
52+
env:
53+
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
54+
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.OSSRH_GPG_SECRET_KEY }}
55+
- name: Publish to Maven Central
56+
run: |
57+
./gradlew jreleaserDeploy --stacktrace
58+
env:
59+
JRELEASER_MAVENCENTRAL_USERNAME: ${{ secrets.MAVENCENTRAL_USERNAME }}
60+
JRELEASER_MAVENCENTRAL_PASSWORD: ${{ secrets.MAVENCENTRAL_PASSWORD }}
61+
4962
docker-build-push:
5063
name: Push Docker image
5164
runs-on: ${{ matrix.arch.runner }}

fabric-chaincode-shim/build.gradle

Lines changed: 82 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66

77
plugins {
88
id 'maven-publish'
9-
id 'jacoco'
109
id 'signing'
10+
id 'org.jreleaser' version '1.18.0'
11+
id 'jacoco'
1112
id 'pmd'
1213
}
1314

@@ -137,7 +138,7 @@ jacocoTestCoverageVerification {
137138
test.finalizedBy(jacocoTestReport)
138139
test.finalizedBy(jacocoTestCoverageVerification)
139140

140-
task licenseCheck {
141+
tasks.register('licenseCheck') {
141142
group = "license"
142143
description = "Checks the License part of each source file"
143144

@@ -146,29 +147,32 @@ task licenseCheck {
146147
def missing = new LinkedList<File>()
147148
sourceSets.forEach {
148149
sourceSet ->
149-
sourceSet.allSource.findAll { !it.path.contains("build") && !(it.path.contains("test") && it.path.contains("resources"))}.each {
150+
sourceSet.allSource.findAll {
151+
!it.path.contains("build") &&
152+
!(it.path.contains("test") && it.path.contains("resources"))
153+
}.each {
150154
file ->
151-
if (!file.name.contains("json")){
152-
BufferedReader r = new BufferedReader(new FileReader(file))
153-
def line, hasSPDX = false, hasTraditional = false
154-
while ((line = r.readLine()) != null) {
155-
if (line.contains("SPDX-License-Identifier")) {
156-
hasSPDX = true
157-
break
155+
if (!file.name.contains("json")) {
156+
BufferedReader r = new BufferedReader(new FileReader(file))
157+
def line, hasSPDX = false, hasTraditional = false
158+
while ((line = r.readLine()) != null) {
159+
if (line.contains("SPDX-License-Identifier")) {
160+
hasSPDX = true
161+
break
162+
}
163+
if (line.contains("http://www.apache.org/licenses/LICENSE-2.0")) {
164+
hasTraditional = true
165+
break
166+
}
158167
}
159-
if (line.contains("http://www.apache.org/licenses/LICENSE-2.0")) {
160-
hasTraditional = true
161-
break
162-
}
163-
}
164-
if (!hasSPDX) {
165-
if (hasTraditional) {
166-
noSPDX.add(file)
167-
} else {
168-
missing.add(file)
168+
if (!hasSPDX) {
169+
if (hasTraditional) {
170+
noSPDX.add(file)
171+
} else {
172+
missing.add(file)
173+
}
169174
}
170175
}
171-
}
172176
}
173177
}
174178

@@ -212,18 +216,12 @@ javadoc {
212216

213217
classpath = sourceSets.main.runtimeClasspath
214218

215-
javadoc.options.addStringOption('Xdoclint:none', '-quiet')
219+
options.addStringOption('Xdoclint:none', '-quiet')
220+
options.addStringOption('Xwerror', '-quiet')
216221
options.overview = "src/main/java/org/hyperledger/fabric/overview.html"
217-
}
218222

219-
if (JavaVersion.current().isJava8Compatible()) {
220-
project.tasks.withType(Javadoc) {
221-
options.addStringOption('Xdoclint:all', '-quiet')
222-
options.addStringOption('Xwerror', '-quiet')
223-
}
224223
}
225224

226-
227225
publishing {
228226
publications {
229227
shim(MavenPublication) {
@@ -235,10 +233,12 @@ publishing {
235233
name = 'JavaChaincodeShim'
236234
packaging = 'jar'
237235
description = 'Hyperledger Fabric Java Chaincode Shim'
238-
url = 'http://www.hyperledger.org/'
236+
url = 'https://hyperledger.github.io/fabric-chaincode-java/'
239237

240238
scm {
241-
url = 'https://github.com/hyperledger/fabric-chaincode-java.git'
239+
connection = 'scm:git:https://github.com/hyperledger/fabric-chaincode-java.git'
240+
developerConnection = 'scm:git:ssh://github.com:hyperledger/fabric-chaincode-java.git'
241+
url = 'https://github.com/hyperledger/fabric-chaincode-java'
242242
}
243243
licenses {
244244
license {
@@ -248,26 +248,16 @@ publishing {
248248
}
249249

250250
developers {
251-
developer {
252-
id = 'gennadylaventman'
253-
name = 'Gennady Laventman'
254-
255-
}
256-
developer {
257-
id = 'luiss'
258-
name = 'Luis Sanchez'
259-
260-
}
261-
developer {
262-
id = 'C0rWin'
263-
name = 'Artem Barger'
264-
265-
}
266251
developer {
267252
id = 'denyeart'
268253
name = 'David Enyeart'
269254
270255
}
256+
developer {
257+
id = 'bestbeforetoday'
258+
name = 'Mark S. Lewis'
259+
260+
}
271261
}
272262
}
273263
}
@@ -276,17 +266,12 @@ publishing {
276266

277267
repositories {
278268
maven {
279-
name = "release"
280-
url = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
281-
credentials {
282-
username = project.findProperty('ossrhUsername')
283-
password = project.findProperty('ossrhPassword')
284-
}
285-
269+
name = "Staging"
270+
url = layout.buildDirectory.dir('staging-deploy')
286271
}
287272

288273
maven {
289-
name = "GitHubPackages"
274+
name = "GitHub"
290275
url = "https://maven.pkg.github.com/hyperledger/fabric-chaincode-java"
291276
credentials {
292277
username = System.getenv("GITHUB_ACTOR")
@@ -297,25 +282,47 @@ publishing {
297282
}
298283

299284
signing {
300-
println "Signing"
301-
if (project.findProperty('signing.key')) {
302-
def signingKey = project.findProperty('signing.key')
303-
def signingPassword = project.findProperty('signing.password')
285+
println "Signing..."
286+
def signingKey = findProperty('signingKey')
287+
if (signingKey) {
288+
def signingPassword = findProperty('signingPassword')
304289
useInMemoryPgpKeys(signingKey, signingPassword)
305-
306290
sign publishing.publications.shim
307-
println "... signed"
291+
println "Signed"
308292
} else {
309-
println "... no keys to use "
293+
println "No keys to use"
294+
}
295+
}
296+
297+
jreleaser {
298+
gitRootSearch = true
299+
deploy {
300+
maven {
301+
mavenCentral {
302+
sonatype {
303+
active = 'ALWAYS'
304+
url = 'https://central.sonatype.com/api/v1/publisher'
305+
sign = false
306+
stagingRepository(layout.buildDirectory.dir('staging-deploy').get().toString())
307+
}
308+
}
309+
}
310+
}
311+
release {
312+
github {
313+
skipRelease = true
314+
skipTag = true
315+
token = 'EMPTY'
316+
}
310317
}
311318
}
312319

313320
// Need to specify the sourcesJar task BEFORE the java{withSourcesJar()} so that it picks up the duplicatesStratergy
314321
// otherwise this fails with a duplicates error.
315322
// (see https://github.com/gradle/gradle/issues/17236)
316323

317-
task sourcesJar(type: Jar) {
318-
duplicatesStrategy = 'include'
324+
tasks.register('sourcesJar', Jar) {
325+
duplicatesStrategy = DuplicatesStrategy.INCLUDE
319326
archiveClassifier = 'sources'
320327
from sourceSets.main.allSource
321328
}
@@ -332,16 +339,16 @@ build.dependsOn licenseCheck
332339
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
333340
import org.gradle.api.tasks.testing.logging.TestLogEvent
334341

335-
tasks.withType(Test) {
342+
tasks.withType(Test).configureEach {
336343

337344
environment "CORE_PEER_LOCALMSPID", "mymsp"
338345

339346
testLogging {
340347
// set options for log level LIFECYCLE
341348
events TestLogEvent.FAILED,
342-
TestLogEvent.PASSED,
343-
TestLogEvent.SKIPPED,
344-
TestLogEvent.STANDARD_OUT
349+
TestLogEvent.PASSED,
350+
TestLogEvent.SKIPPED,
351+
TestLogEvent.STANDARD_OUT
345352
exceptionFormat = TestExceptionFormat.FULL
346353
showExceptions = true
347354
showCauses = true
@@ -350,22 +357,23 @@ tasks.withType(Test) {
350357
// set options for log level DEBUG and INFO
351358
debug {
352359
events TestLogEvent.STARTED,
353-
TestLogEvent.FAILED,
354-
TestLogEvent.PASSED,
355-
TestLogEvent.SKIPPED,
356-
TestLogEvent.STANDARD_ERROR,
357-
TestLogEvent.STANDARD_OUT
360+
TestLogEvent.FAILED,
361+
TestLogEvent.PASSED,
362+
TestLogEvent.SKIPPED,
363+
TestLogEvent.STANDARD_ERROR,
364+
TestLogEvent.STANDARD_OUT
358365
exceptionFormat = TestExceptionFormat.FULL
359366
}
360367
info.events = debug.events
361368
info.exceptionFormat = debug.exceptionFormat
362369

363-
afterSuite { desc, result ->
370+
afterSuite {desc, result ->
364371
if (!desc.parent) { // will match the outermost suite
365372
def output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
366373
def startItem = '| ', endItem = ' |'
367374
def repeatLength = startItem.length() + output.length() + endItem.length()
368-
println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' + ('-' * repeatLength))
375+
println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' +
376+
('-' * repeatLength))
369377
}
370378
}
371379
}

gradle/wrapper/gradle-wrapper.jar

181 Bytes
Binary file not shown.

gradlew

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ done
8686
# shellcheck disable=SC2034
8787
APP_BASE_NAME=${0##*/}
8888
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
89-
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
90-
' "$PWD" ) || exit
89+
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
9190

9291
# Use the maximum available, or set MAX_FD != -1 to use that value.
9392
MAX_FD=maximum
@@ -115,7 +114,7 @@ case "$( uname )" in #(
115114
NONSTOP* ) nonstop=true ;;
116115
esac
117116

118-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
117+
CLASSPATH="\\\"\\\""
119118

120119

121120
# Determine the Java command to use to start the JVM.
@@ -206,15 +205,15 @@ fi
206205
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
207206

208207
# Collect all arguments for the java command:
209-
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
208+
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
210209
# and any embedded shellness will be escaped.
211210
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
212211
# treated as '${Hostname}' itself on the command line.
213212

214213
set -- \
215214
"-Dorg.gradle.appname=$APP_BASE_NAME" \
216215
-classpath "$CLASSPATH" \
217-
org.gradle.wrapper.GradleWrapperMain \
216+
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
218217
"$@"
219218

220219
# Stop when "xargs" is not available.

gradlew.bat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ goto fail
7070
:execute
7171
@rem Setup the command line
7272

73-
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73+
set CLASSPATH=
7474

7575

7676
@rem Execute Gradle
77-
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
77+
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
7878

7979
:end
8080
@rem End local scope for the variables with windows NT shell

0 commit comments

Comments
 (0)