Skip to content

Commit ef1dbf9

Browse files
authored
Move to Maven Central (#238)
* Change deployment.gradle to point to Maven Central directly * Add signing key decryption step to CI pipeline * Drop Bintray * Include mavenCentral() repository with higher priority than jcenter()
1 parent 71c51d0 commit ef1dbf9

8 files changed

Lines changed: 146 additions & 151 deletions

File tree

.circleci/config.yml

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ defaults: &defaults
99
cache_key: &cache_key
1010
key: jars-{{ checksum "plugin/build.gradle.kts" }}-{{ checksum "plugin/android-junit5/build.gradle.kts" }}-{{ checksum "plugin/gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "instrumentation/build.gradle.kts" }}-{{ checksum "instrumentation/runner/build.gradle.kts" }}-{{ checksum "instrumentation/sample/build.gradle.kts" }}-{{ checksum "instrumentation/gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "buildSrc/src/main/kotlin/Artifacts.kt" }}-{{ checksum "buildSrc/src/main/kotlin/Dependencies.kt" }}
1111

12+
commands:
13+
construct_signing_key:
14+
description: Construct GPG Signing Key
15+
steps:
16+
- run: base64 -d \<<< $SIGNING_KEY_RING_FILE_CONTENTS > $SIGNING_KEY_RING_FILE
17+
1218
version: 2
1319
jobs:
1420
build_plugin:
@@ -71,7 +77,7 @@ jobs:
7177
sudo gcloud firebase test android run \
7278
--type instrumentation \
7379
--app instrumentation/sample/build/outputs/apk/debug/sample-debug.apk \
74-
--test instrumentation/core/build/outputs/apk/androidTest/debug/android-test-core-debug-androidTest.apk \
80+
--test instrumentation/core/build/outputs/apk/androidTest/debug/core-debug-androidTest.apk \
7581
--environment-variables runnerBuilder=de.mannodermaus.junit5.AndroidJUnit5Builder \
7682
--test-runner-class androidx.test.runner.AndroidJUnitRunner \
7783
--device model=sailfish,version=28,locale=en_US,orientation=portrait \
@@ -105,9 +111,13 @@ jobs:
105111
at: ~/root
106112
- restore_cache:
107113
<<: *cache_key
114+
- construct_signing_key
115+
- run:
116+
name: (Plugin) Build Artifacts
117+
command: cd plugin && ./gradlew androidSourcesJar javadocJar
108118
- run:
109119
name: (Plugin) Deploy
110-
command: cd plugin && ./gradlew deploy --stacktrace --no-daemon
120+
command: cd plugin && ./gradlew deploy --max-workers 1 --stacktrace --no-daemon
111121
- store_artifacts:
112122
path: plugin/android-junit5/build/publications
113123
destination: plugin/publications/snapshots
@@ -119,9 +129,13 @@ jobs:
119129
at: ~/root
120130
- restore_cache:
121131
<<: *cache_key
132+
- construct_signing_key
133+
- run:
134+
name: (Plugin) Build Artifacts
135+
command: cd instrumentation && ./gradlew androidSourcesJar javadocJar
122136
- run:
123137
name: (Instrumentation) Deploy
124-
command: cd instrumentation && ./gradlew deploy --stacktrace --no-daemon
138+
command: cd instrumentation && ./gradlew deploy --max-workers 1 --stacktrace --no-daemon
125139
- store_artifacts:
126140
path: instrumentation/core/build/publications
127141
destination: instrumentation-core/publications/snapshots

buildSrc/src/main/kotlin/Artifacts.kt

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ object Artifacts {
4747
platform = Java,
4848
groupId = "de.mannodermaus.gradle.plugins",
4949
artifactId = "android-junit5",
50-
currentVersion = "1.7.0.1-SNAPSHOT",
50+
currentVersion = "1.7.1.0-SNAPSHOT",
5151
latestStableVersion = "1.7.0.0",
5252
license = license,
5353
description = "Unit Testing with JUnit 5 for Android."
@@ -85,10 +85,12 @@ object Artifacts {
8585

8686
class DeployedCredentials(private val project: Project) {
8787

88-
val bintrayUser: String?
89-
val bintrayKey: String?
90-
val sonatypeUser: String?
91-
val sonatypePass: String?
88+
var signingKeyId: String?
89+
var signingPassword: String?
90+
var signingKeyRingFile: String?
91+
var ossrhUsername: String?
92+
var ossrhPassword: String?
93+
var sonatypeStagingProfileId: String?
9294

9395
init {
9496
// Populate deployment credentials in an environment-aware fashion.
@@ -104,9 +106,14 @@ class DeployedCredentials(private val project: Project) {
104106
}
105107
}
106108

107-
this.bintrayUser = properties.getProperty("BINTRAY_USER", System.getenv("bintrayUser"))
108-
this.bintrayKey = properties.getProperty("BINTRAY_KEY", System.getenv("bintrayKey"))
109-
this.sonatypeUser = properties.getProperty("SONATYPE_USER", System.getenv("sonatypeUser"))
110-
this.sonatypePass = properties.getProperty("SONATYPE_PASS", System.getenv("sonatypePass"))
109+
this.signingKeyId = properties.getOrEnvvar("SIGNING_KEY_ID")
110+
this.signingPassword = properties.getOrEnvvar("SIGNING_PASSWORD")
111+
this.signingKeyRingFile = properties.getOrEnvvar("SIGNING_KEY_RING_FILE")
112+
this.ossrhUsername = properties.getOrEnvvar("OSSRH_USERNAME")
113+
this.ossrhPassword = properties.getOrEnvvar("OSSRH_PASSWORD")
114+
this.sonatypeStagingProfileId = properties.getOrEnvvar("SONATYPE_STAGING_PROFILE_ID")
111115
}
116+
117+
private fun Properties.getOrEnvvar(key: String): String? =
118+
getProperty(key, System.getenv(key))
112119
}

buildSrc/src/main/kotlin/Dependencies.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,10 @@ object Plugins {
3333
)
3434

3535
// Documentation
36-
const val dokkaCore: Lib = "org.jetbrains.dokka:dokka-gradle-plugin:0.9.18"
37-
const val dokkaAndroid: Lib = "org.jetbrains.dokka:dokka-android-gradle-plugin:0.9.18"
36+
const val dokkaCore: Lib = "org.jetbrains.dokka:dokka-gradle-plugin:1.4.20"
3837

3938
// Publishing
40-
const val androidMavenGradle: Lib = "com.github.dcendents:android-maven-gradle-plugin:2.1"
41-
const val androidMavenPublish: Lib = "digital.wup:android-maven-publish:3.6.2"
42-
const val bintray: Lib = "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4"
39+
const val nexusStaging: Lib = "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.22.0"
4340
}
4441

4542
/**

buildSrc/src/main/kotlin/Versions.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ object Versions {
3333

3434
const val java_semver: String = "0.9.0"
3535

36-
const val gradle_bintray_plugin: String = "1.8.4"
37-
3836
const val truth: String = "0.43"
3937

4038
const val truth_android: String = "1.1.0"

deployment.gradle

Lines changed: 99 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,134 @@
1-
// Common logic shared across modules whose artifacts are provided to jCenter and Sonatype OSS.
1+
// Common logic shared across modules whose artifacts are provided to Maven Central.
22
//
33
// This script expects an extra named "deployConfig" to exist on the Project instance.
44
// Its type is defined within the buildSrc module of this project.
5-
6-
// Access Map properties
75
if (!project.ext.has("deployConfig")) {
86
throw new IllegalStateException("Deployed module '$name' requires a 'deployConfig'")
97
}
108

11-
final def deployConfig = project.ext.deployConfig
12-
final def deployCredentials = project.ext.deployCredentials
13-
final String targetPlatform = deployConfig.platform.name
14-
final String groupId = deployConfig.groupId
15-
final String artifactId = deployConfig.artifactId
16-
final String versionNumber = deployConfig.currentVersion
17-
final String license = deployConfig.license
18-
final String description = deployConfig.description
19-
20-
// Apply required plugins
21-
apply plugin: "com.jfrog.bintray"
22-
23-
if (targetPlatform == "java") {
24-
// Releases
25-
apply plugin: "maven"
26-
// Snapshots
27-
apply plugin: "maven-publish"
28-
} else if (targetPlatform == "android") {
29-
// Releases
30-
apply plugin: "com.github.dcendents.android-maven"
31-
// Snapshots
32-
apply plugin: "digital.wup.android-maven-publish"
33-
}
9+
final Deployed deployConfig = project.ext.deployConfig
10+
final DeployedCredentials deployCredentials = project.ext.deployCredentials
11+
final boolean isAndroid = project.plugins.findPlugin("com.android.library") != null
3412

35-
// ------------------------------------------------------------------------------------------------
36-
// Artifacts Configuration
37-
// ------------------------------------------------------------------------------------------------
13+
apply plugin: "maven-publish"
14+
apply plugin: "signing"
15+
apply plugin: "org.jetbrains.dokka"
3816

39-
// Include sources.jar archive in each release
40-
if (targetPlatform == "java") {
41-
task sourcesJar(type: Jar, dependsOn: classes) {
42-
baseName = artifactId
43-
classifier = "sources"
44-
from sourceSets.main.allSource
45-
}
46-
} else {
47-
task sourcesJar(type: Jar) {
48-
baseName = artifactId
49-
classifier = "sources"
17+
// Create artifact tasks
18+
task androidSourcesJar(type: Jar) {
19+
archiveClassifier.set("sources")
20+
if (isAndroid) {
5021
from android.sourceSets.main.java.srcDirs
22+
} else {
23+
from sourceSets.main.java.srcDirs
5124
}
5225
}
5326

54-
// Include javadoc.jar archive in each release
55-
if (targetPlatform == "android") {
56-
apply plugin: "org.jetbrains.dokka-android"
57-
} else {
58-
apply plugin: "org.jetbrains.dokka"
27+
task javadocJar(type: Jar, dependsOn: dokkaJavadoc) {
28+
archiveClassifier.set("javadoc")
29+
from dokkaJavadoc.outputDirectory
5930
}
6031

61-
task javadocJar(type: Jar, dependsOn: dokka) {
62-
baseName = artifactId
63-
classifier = "javadoc"
64-
from dokka.outputDirectory
32+
artifacts {
33+
archives androidSourcesJar
34+
archives javadocJar
6535
}
6636

67-
// ------------------------------------------------------------------------------------------------
68-
// Publication Configuration
69-
// ------------------------------------------------------------------------------------------------
37+
// Setup publication details
38+
group = deployConfig.groupId
39+
version = deployConfig.currentVersion
7040

71-
group = groupId
72-
archivesBaseName = artifactId
73-
version = versionNumber
41+
final def isSnapshot = version.endsWith("SNAPSHOT")
7442

7543
publishing {
7644
publications {
77-
library(MavenPublication) { p ->
78-
p.from components.getByName(targetPlatform)
79-
p.artifact sourcesJar
80-
p.artifact javadocJar
81-
p.groupId groupId
82-
p.artifactId artifactId
83-
p.version version
84-
p.pom.withXml {
85-
def root = asNode()
86-
root.appendNode("description", description)
87-
root.appendNode("name", artifactId)
88-
root.appendNode("url", Artifacts.githubUrl)
45+
release(MavenPublication) {
46+
groupId deployConfig.groupId
47+
artifactId deployConfig.artifactId
48+
version deployConfig.currentVersion
49+
50+
if (isAndroid) {
51+
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
52+
} else {
53+
artifact("$buildDir/libs/${project.getName()}-${version}.jar")
8954
}
90-
}
91-
}
92-
}
93-
94-
// Copy POM to location expected by Bintray
95-
task copyPom(type: Copy) {
96-
from "build/publications/library"
97-
into "build/poms"
98-
include "pom-default.xml"
99-
}
55+
artifact androidSourcesJar
56+
artifact javadocJar
57+
58+
pom {
59+
name = deployConfig.artifactId
60+
description = deployConfig.description
61+
url = Artifacts.githubRepo
62+
63+
licenses {
64+
license {
65+
name = Artifacts.license
66+
url = "${Artifacts.githubUrl}/blob/main/LICENSE"
67+
}
68+
}
10069

101-
// ------------------------------------------------------------------------------------------------
102-
// Target Configuration
103-
// ------------------------------------------------------------------------------------------------
70+
developers {
71+
developer {
72+
id = "mannodermaus"
73+
name = "Marcel Schnelle"
74+
}
75+
}
10476

105-
// Unified task for snapshots & releases
106-
task deploy() {
107-
}
77+
scm {
78+
connection = "scm:git:${Artifacts.githubRepo}.git"
79+
developerConnection = "scm:git:ssh://github.com/${Artifacts.githubRepo}.git"
80+
url = "${Artifacts.githubUrl}/tree/main"
81+
}
10882

109-
project.configure(project) {
110-
if (project.version.endsWith("-SNAPSHOT")) {
111-
// Configure deployment of snapshot versions to Sonatype OSS
112-
project.publishing {
113-
repositories {
114-
maven {
115-
name "snapshot"
116-
credentials {
117-
username deployCredentials.sonatypeUser
118-
password deployCredentials.sonatypePass
83+
// Include transitive dependencies
84+
withXml {
85+
def dependenciesNode = asNode().appendNode("dependencies")
86+
project.configurations.implementation.allDependencies.each {
87+
def dependencyNode = dependenciesNode.appendNode("dependency")
88+
dependencyNode.appendNode("groupId", it.group)
89+
dependencyNode.appendNode("artifactId", it.name)
90+
dependencyNode.appendNode("version", it.version)
11991
}
120-
url "https://oss.sonatype.org/content/repositories/snapshots"
12192
}
12293
}
12394
}
124-
project.tasks.getByName("bintrayUpload").enabled = false
125-
publish.dependsOn copyPom
126-
deploy.finalizedBy "publishLibraryPublicationToSnapshotRepository"
95+
}
12796

128-
} else {
129-
// Configure deployment of release versions to Bintray
130-
project.artifacts {
131-
archives javadocJar
132-
archives sourcesJar
133-
}
97+
repositories {
98+
maven {
99+
name = "central"
134100

135-
project.bintray {
136-
user = deployCredentials.bintrayUser
137-
key = deployCredentials.bintrayKey
138-
configurations = ["archives"]
139-
dryRun = false
140-
publish = true
141-
pkg {
142-
repo = "maven"
143-
name = artifactId
144-
desc = description
145-
licenses = [license]
146-
githubRepo = Artifacts.githubRepo
147-
websiteUrl = Artifacts.githubUrl
148-
vcsUrl = "${Artifacts.githubUrl}.git"
149-
issueTrackerUrl = "${Artifacts.githubUrl}/issues"
150-
publicDownloadNumbers = true
151-
version {
152-
name = versionNumber
153-
desc = description
154-
}
101+
def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
102+
def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
103+
url = isSnapshot ? snapshotsRepoUrl : releasesRepoUrl
104+
105+
credentials {
106+
username deployCredentials.ossrhUsername
107+
password deployCredentials.ossrhPassword
155108
}
156109
}
157-
// Very important! Otherwise, the POM will be overwritten & have missing dependencies
158-
project.tasks.getByName("install").finalizedBy copyPom
159-
deploy.finalizedBy "generatePomFileForLibraryPublication", "publish", "install", "bintrayUpload"
160110
}
161111
}
112+
113+
// Setup code signing
114+
ext["signing.keyId"] = deployCredentials.signingKeyId
115+
ext["signing.password"] = deployCredentials.signingPassword
116+
ext["signing.secretKeyRingFile"] = deployCredentials.signingKeyRingFile
117+
signing {
118+
sign publishing.publications
119+
}
120+
121+
// Setup deployment
122+
nexusStaging {
123+
packageGroup = deployConfig.groupId
124+
stagingProfileId = deployCredentials.sonatypeStagingProfileId
125+
username = deployCredentials.ossrhUsername
126+
password = deployCredentials.ossrhPassword
127+
}
128+
129+
// Catch-all deployment task for multiple modules
130+
def deploy = tasks.maybeCreate("deploy")
131+
deploy.finalizedBy "publishReleasePublicationToCentralRepository"
132+
if (!isSnapshot) {
133+
deploy.finalizedBy "closeAndReleaseRepository"
134+
}

0 commit comments

Comments
 (0)