Skip to content

Maven 仓库发布

源:Gradle 官方文档 - Publishing

将 Android 库或 Kotlin 模块发布到 Maven 仓库,供其他项目使用。

Maven 发布概念

为什么发布到 Maven

共享代码

  • 团队内部共享库
  • 开源项目分发
  • 模块化架构

版本管理

  • 统一版本号
  • 依赖管理
  • 回滚支持

CI/CD 集成

  • 自动发布
  • 快照版本
  • 正式版本

Maven Publish 插件

启用插件

build.gradle.kts

kotlin
plugins {
    id("maven-publish")
}

基本发布配置

kotlin
publishing {
    publications {
        create<MavenPublication>("release") {
            groupId = "com.example"
            artifactId = "my-library"
            version = "1.0.0"
            
            from(components["release"])
        }
    }
}

Android 库发布

完整配置

kotlin
// library/build.gradle.kts
plugins {
    id("com.android.library")
    id("maven-publish")
}

android {
    namespace = "com.example.mylibrary"
    compileSdk = 34
    
    defaultConfig {
        minSdk = 24
    }
    
    publishing {
        singleVariant("release") {
            withSourcesJar()
            withJavadocJar()
        }
    }
}

publishing {
    publications {
        create<MavenPublication>("release") {
            groupId = "com.example"
            artifactId = "mylibrary"
            version = "1.0.0"
            
            // 发布 release 变体
            afterEvaluate {
                from(components["release"])
            }
            
            // POM 配置
            pom {
                name.set("My Library")
                description.set("An awesome Android library")
                url.set("https://github.com/example/mylibrary")
                
                licenses {
                    license {
                        name.set("The Apache License, Version 2.0")
                        url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
                    }
                }
                
                developers {
                    developer {
                        id.set("developer")
                        name.set("Developer Name")
                        email.set("developer@example.com")
                    }
                }
                
                scm {
                    connection.set("scm:git:git://github.com/example/mylibrary.git")
                    developerConnection.set("scm:git:ssh://github.com/example/mylibrary.git")
                    url.set("https://github.com/example/mylibrary")
                }
            }
        }
    }
}

发布目标

本地 Maven 仓库

发布到本地

kotlin
publishing {
    repositories {
        mavenLocal()
    }
}

发布命令

bash
./gradlew publishToMavenLocal

位置

~/.m2/repository/com/example/mylibrary/1.0.0/

文件系统仓库

kotlin
publishing {
    repositories {
        maven {
            name = "FileRepo"
            url = uri("file://${rootProject.projectDir}/repo")
        }
    }
}

发布

bash
./gradlew publishReleasePublicationToFileRepoRepository

远程 Maven 仓库

HTTP 仓库

kotlin
publishing {
    repositories {
        maven {
            name = "CompanyRepo"
            url = uri("https://maven.company.com/releases")
            
            credentials {
                username = providers.environmentVariable("MAVEN_USERNAME").orNull
                password = providers.environmentVariable("MAVEN_PASSWORD").orNull
            }
        }
    }
}

发布

bash
export MAVEN_USERNAME=user
export MAVEN_PASSWORD=pass
./gradlew publishReleasePublicationToCompanyRepoRepository

Maven Central 发布

准备工作

1. 注册 Sonatype 账号

2. 申请 GroupID

  • 创建 JIRA Issue
  • 验证域名所有权

3. 生成 GPG 密钥

bash
gpg --gen-key
gpg --list-keys
gpg --keyserver keyserver.ubuntu.com --send-keys <KEY_ID>

配置签名

gradle.properties

properties
signing.keyId=<LAST_8_CHARS_OF_KEY>
signing.password=<GPG_PASSWORD>
signing.secretKeyRingFile=/home/user/.gnupg/secring.gpg

ossrhUsername=<SONATYPE_USERNAME>
ossrhPassword=<SONATYPE_PASSWORD>

build.gradle.kts

kotlin
plugins {
    id("maven-publish")
    id("signing")
}

publishing {
    publications {
        create<MavenPublication>("release") {
            groupId = "com.example"
            artifactId = "mylibrary"
            version = "1.0.0"
            
            afterEvaluate {
                from(components["release"])
            }
            
            pom {
                // 必填项
                name.set("My Library")
                description.set("Description")
                url.set("https://github.com/example/mylibrary")
                
                licenses {
                    license {
                        name.set("The Apache License, Version 2.0")
                        url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
                    }
                }
                
                developers {
                    developer {
                        id.set("developer")
                        name.set("Developer Name")
                        email.set("developer@example.com")
                    }
                }
                
                scm {
                    connection.set("scm:git:git://github.com/example/mylibrary.git")
                    developerConnection.set("scm:git:ssh://github.com/example/mylibrary.git")
                    url.set("https://github.com/example/mylibrary")
                }
            }
        }
    }
    
    repositories {
        maven {
            name = "OSSRH"
            val releasesRepoUrl = uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
            val snapshotsRepoUrl = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
            url = if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl
            
            credentials {
                username = findProperty("ossrhUsername") as String?
                password = findProperty("ossrhPassword") as String?
            }
        }
    }
}

signing {
    sign(publishing.publications["release"])
}

发布到 Maven Central

bash
./gradlew publishReleasePublicationToOSSRHRepository

发布流程

  1. 上传到 Staging 仓库
  2. 登录 https://s01.oss.sonatype.org/
  3. Close Staging Repository
  4. Release to Maven Central
  5. 等待同步(2-4小时)

GitHub Packages

配置

kotlin
publishing {
    repositories {
        maven {
            name = "GitHubPackages"
            url = uri("https://maven.pkg.github.com/username/repository")
            
            credentials {
                username = providers.environmentVariable("GITHUB_ACTOR").orNull
                password = providers.environmentVariable("GITHUB_TOKEN").orNull
            }
        }
    }
}

GitHub Actions 发布

yaml
name: Publish

on:
  release:
    types: [created]

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup JDK
        uses: actions/setup-java@v3
        with:
          java-version: '17'
      
      - name: Publish
        run: ./gradlew publishReleasePublicationToGitHubPackagesRepository
        env:
          GITHUB_ACTOR: ${{ github.actor }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

版本管理

语义化版本

<major>.<minor>.<patch>[-<label>]

1.0.0         - 正式版本
1.0.0-alpha01 - Alpha 版本
1.0.0-beta01  - Beta 版本
1.0.0-rc01    - Release Candidate
1.1.0-SNAPSHOT- 快照版本

动态版本号

使用 Git Tag

kotlin
fun getVersionName(): String {
    val tag = providers.exec {
        commandLine("git", "describe", "--tags", "--always")
    }.standardOutput.asText.get().trim()
    
    return if (tag.startsWith("v")) tag.substring(1) else tag
}

publishing {
    publications {
        create<MavenPublication>("release") {
            version = getVersionName()
        }
    }
}

使用 gradle.properties

properties
VERSION_NAME=1.0.0
VERSION_CODE=1
kotlin
val versionName: String by project

publishing {
    publications {
        create<MavenPublication>("release") {
            version = versionName
        }
    }
}

实战案例

案例1:内部库发布

场景:团队内部共享工具库

配置

kotlin
// buildSrc/src/main/kotlin/publish-conventions.gradle.kts
plugins {
    id("maven-publish")
}

group = "com.company.internal"

publishing {
    publications {
        create<MavenPublication>("release") {
            from(components["java"])
        }
    }
    
    repositories {
        maven {
            name = "CompanyNexus"
            url = uri("https://nexus.company.com/repository/maven-releases/")
            credentials {
                username = providers.environmentVariable("NEXUS_USER").orNull
                password = providers.environmentVariable("NEXUS_PASS").orNull
            }
        }
    }
}

使用

kotlin
// library/build.gradle.kts
plugins {
    id("publish-conventions")
}

version = "1.2.3"

案例2:多模块发布

根项目

kotlin
// build.gradle.kts
subprojects {
    group = "com.example"
    version = "1.0.0"
    
    plugins.withId("com.android.library") {
        apply(plugin = "maven-publish")
        
        publishing {
            publications {
                create<MavenPublication>("release") {
                    afterEvaluate {
                        from(components["release"])
                    }
                }
            }
        }
    }
}

发布所有模块

bash
./gradlew publishToMavenLocal

最佳实践

版本号规范

  • 使用语义化版本
  • SNAPSHOT 用于开发
  • 正式版本不可变

POM 完整性

  • 填写所有必填字段
  • 添加开源许可
  • 提供项目 URL

凭证安全

  • 使用环境变量
  • 不提交到版本控制
  • CI 使用 Secrets

自动化发布

yaml
# GitHub Actions
on:
  push:
    tags:
      - 'v*'

发布检查清单

  • ✅ 版本号正确
  • ✅ POM 信息完整
  • ✅ 源码和文档打包
  • ✅ 签名配置(Maven Central)
  • ✅ 测试通过
  • ✅ CHANGELOG 更新