JReleaser+Gradle将SDK发布到maven central

正式写之前纠结了很久,因为心里有无数个声音在阻止我——都啥年代了还写博客?写了有人看吗?现在遇到问题都用AI,谁还会看博客……但最终还是下定决心写起来。不管是给AI做饲料也好,有没有人看也罢,一来是对知识点的重新梳理,二来是做个备份以备后续查阅,三来是希望以后回头再看自己写的内容能勾起我的回忆。

言归正传。

最近来了个新活,基于三方的API开发了一套SDK,除了公司内部使用以外,外部合作单位也需要用。打包出来的制品不能放内部的maven仓库,因为别人访问不了我们的内网,最终决定放到maven central。

上传到内部Nexus仓库的配置很简单,主要配好仓库的url和用户名密码就行。上传到maven central就复杂多了:

1、完整的的POM信息。

2、完整的制品。

3、需要对制品签名。

POM信息就是gradle的配置信息,可以借助gradle插件maven-publish生成完整的制品,最后需要对制品进行GPG签名。

官方推荐的JReleaser插件能够帮助我们完成第2、3步。当然还有很多可选的方案,文档都有列出来https://central.sonatype.org/publish/publish-portal-gradle/

首先准备工作要做好,注册sonatype 账号,创建namespace。

然后生成GPG签名并上传,详细的生成步骤参考这篇博客

将公钥和私钥导文件出来,后面gradle配置需要用到:

gpg --output public.pgp --armor --export xxx@xxx.com

gpg --output private.pgp --armor --export-secret-key xxx@xxx.com

接着导出私钥环文件(生成 secring.gpg),后面签名的时候也要用到:

gpg --export-secret-keys -o ~/.jreleaser/secring.gpg

最后要在github或者其他git平台也行,创建个项目,后面gradle配置POM的时候需要用到。

以上准备工作做好后就可以开始配置gradle了,首先配置maven-publish相关信息,目的是生成制品,以下是我项目的配置,仅供参考。

//以下内容写到根build.gradle中

import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.plugins.signing.SigningExtension

subprojects {

    val projectName = name
    val projectDescription = "Android SDK for Netease Music integration"

    val smartVersion = findProperty("MAVEN_CENTRAL_VERSION") as String
    val smartGroupId = findProperty("SMART_GROUP_ID") as String
    val smartUser = findProperty("SMART_USER") as String
    val smartEmail = findProperty("SMART_EMAIL") as String

    apply(plugin = "com.android.library")
    apply(plugin = "maven-publish")
    apply(plugin = "signing")

    afterEvaluate {
        // 在外部脚本中,使用 configure<PublishingExtension> 代替原生的 publishing {} 块
        configure<PublishingExtension> {
            publications {
                create<MavenPublication>("maven") {
                    from(components["release"])
                    groupId = smartGroupId
                    artifactId = projectName
                    version = smartVersion
                    pom {
                        name.set(projectName)
                        description.set(projectDescription)
                        url.set("https://github.com/longdw/netease-music-sdk.git")
                        licenses {
                            license {
                                name.set("The Apache License, Version 2.0")
                                url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
                            }
                        }
                        developers {
                            developer {
                                name.set(smartUser)
                                email.set(smartEmail)
                            }
                        }
                        scm {
                            connection.set("scm:git:https://github.com/longdw/netease-music-sdk.git")
                            developerConnection.set("scm:git:ssh://github.com/longdw/netease-music-sdk.git")
                            url.set("https://github.com/longdw/netease-music-sdk")
                        }
                    }
                }
            }
            repositories { 
                maven {
                    //将制品发布到根目录的临时文件夹,供 JREleaser 采集
                    url = uri("${rootProject.buildDir}/staging-deploy")
                }
            }
        }

        // 2. 配置签名逻辑
        configure<SigningExtension> {
            val publication = extensions.getByType<PublishingExtension>().publications["maven"]
            sign(publication)
        }
    }
}

其中SMART_GROUPMAVEN_CENTRAL_VERSIONSMART_GROUP_ID等信息需要根据实际情况定填写到gradle.properties文件中。

接着配置JReleaser相关信息,同样是写到build.gradle中。

plugins {
    //...

    id("org.jreleaser") version "1.23.0"
}

val smartVersion = findProperty("MAVEN_CENTRAL_VERSION") as String
jreleaser {

    // 必须:添加项目基本信息
    project {
        name = "netease-music-sdk"
        version = smartVersion
        description = "Netease Music SDK for Android"
        authors = listOf("david.long")
        license = "Apache-2.0"
        maintainers = listOf("david.long")
        website = "https://github.com/longdw/netease-music-sdk.git"
    }

    // 1. 签名配置:JREleaser 会自动处理所有 artifacts 的签名
    signing {
        pgp {
            active = org.jreleaser.model.Active.ALWAYS
            armored = true
            setMode("FILE")
            publicKey = "~/.jreleaser/public.key"
            secretKey = "~/.jreleaser/private.key"
        }
    }

    release {
        github {
            repoOwner = "longdw"
            name = "netease-music-sdk"
            // 如果你只想要发布制品而不创建 GitHub Release 页面,可以设置 skipRelease = true
            skipRelease = true
        }
        generic {
            enabled = false
        }
    }

    // 2. 发布到 Maven Central (Sonatype)
    deploy {
        maven {
            mavenCentral {
                register("release-deploy") {
                    active = org.jreleaser.model.Active.RELEASE
                    url = "https://central.sonatype.com/api/v1/publisher"
                    // 关联要发布的项目(对应 subprojects 中的 artifactId
                    stagingRepository("build/staging-deploy")

                    // 增加以下配置,防止 JREleaser 因为找不到 .jar 文件而报错
                    verifyPom = false
                    // 如果是 Central Portal,有时需要放宽本地校验规则
                    applyMavenCentralRules = false
                }
            }
        }
    }
}

最后还有几个配置非常关键,JReleaser插件默认读取~/.jreleaser/config.toml中的配置,这在文档中有说明:https://jreleaser.org/guide/latest/examples/maven/maven-central.html#_mavenconfig.toml配置文件中主要配置公私钥以及maven central用户名密码相关信息,以下是我的配置。

JRELEASER_MAVENCENTRAL_USERNAME = "sonatype网站登录用户名"
JRELEASER_MAVENCENTRAL_PASSWORD = "sonatype网站登录密码"
JRELEASER_GPG_PASSPHRASE = "gpg密钥密码"
JRELEASER_PROJECT_JAVA_GROUP_ID = "sonatype申请的namespace"
JRELEASER_GITHUB_TOKEN = "github代码上传需要用到的token"

JRELEASER_GPG_PUBLIC_KEY="""-----BEGIN PGP PUBLIC KEY BLOCK-----

mQGNxxxxxx
-----END PGP PUBLIC KEY BLOCK-----
"""

JRELEASER_GPG_SECRET_KEY="""-----BEGIN PGP PRIVATE KEY BLOCK-----

lQWGBGnrFxxxxx
-----END PGP PRIVATE KEY BLOCK-----
"""

全局的~/.gradle/gradle.properties中还需要配置私钥环文件信息:

signing.keyId=你的GPG公钥ID后8位 (例如: 1ABC2DEF)
signing.password=你的GPG私钥密码
signing.secretKeyRingFile=/Users/longdawei/.jreleaser/secring.gpg

所有配置好以后通过:

1、./gradlew jreleaserConfig 验证配置。

2、./gradlew clean publishAllPublicationsToMavenRepository 生成制品。

3、./gradlew jreleaserDeploy上传artifacts到maven central仓库。

以上命令执行都没问题的话,在sonatype网站看到如下信息:

原创不易,转载请注明出处:https://www.longdw.com