Kotlin与Java混编项目的Nexus私有仓库持续交付与集成

关于 Android 开发结合 Nexus 仓库的使用已经有很多相关文章了,但大多是纯 Java 工程的应用。我使用 Kotlin 开发已有半年多了,愈发感觉 Kotlin 好用。现在新项目的开发中,95%以上的代码使用 Kotlin 编写,旧的项目也逐渐升级。随着项目规模的不断变大,模块越来越多,每次编译都十分耗时。而新项目使用旧有模块,需要手动拷贝,版本控制也是个问题。为了解决这个问题,我们搭建了私有 Nexus 仓库。相对稳定的模块直接通过私有仓库管理,在打包上传包含 Kotlin 的模块时,遇到了一些问题,这里记录下,大家有需要可以参考下。

搭建 Nexus 仓库

搭建 Nexus 仓库的文章相比有很多,官方也提供了详细的文档。但如果想快速搭建,建议使用 Docker,只需一行命令,当然前提是你已经安装了 Docker。在 Docker hub 搜索下


Docker hub Nexus 搜索结果

显而易见 sonatype/nexus3 是首选

docker pull sonatype/nexus3

是的一个强大的私有库,只需等待这条命令执行完成就可以了。具体如何配 nexus 这里就不做详细介绍了,无论是 Google 还是百度都一大把。


Nexus仓库截图

支持 Kotlin aar 打包,包括 java 文档打包。

要想支持 Kotlin 打包,需要使用 Kotlin 官方插件 org.jetbrains.dokka:dokka-android-gradle-plugin,目前最新版本是 0.9.17,虽然还没到1.0,暂时没有发现问题。

//工程的 build.gradle
dependencies {
    ...
    classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:0.9.17"
    ...
}

repositories {
    ...
    maven {
        url "https://plugins.gradle.org/m2/"
    }
    ...
}
//库 Module 的 build.gradle
task generateSourcesJar(type: Jar) {
    group = 'jar'
    from android.sourceSets.main.java.srcDirs
    classifier = 'sources'
}

task javadoc(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}

task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) {
    outputFormat = "javadoc"
    outputDirectory = javadoc.destinationDir
}

task generateJavadoc(type: Jar, dependsOn: dokkaJavadoc) {
    group = 'jar'
    classifier = 'javadoc'
    from javadoc.destinationDir
}

artifacts {
    //在频繁打包交付测试时,可暂时注释掉文档打包,提高打包效率
    archives generateJavadoc

    archives generateSourcesJar
}

//动态获取版本名称
def POM_VERSION_NAME = getVersionName()

uploadArchives {
    repositories {
        mavenDeployer {
            snapshotRepository(url: NEXUS_REPO_SNAPSHOT_URL) {
                authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
            }
            repository(url: NEXUS_REPO_RELEASE_URL) {
                authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
            }
            pom.project {
                name POM_NAME
                version POM_VERSION_NAME
                artifactId POM_ARTIFACTID
                groupId POM_GROUP_ID
                packaging POM_PACKAGING
                description POM_DESCRIPTION
            }
        }
    }
}

def getVersionCode() {
    def versionFile = file('./version.properties')
    if (versionFile.canRead()) {
        Properties properties = new Properties()
        properties.load(new FileInputStream(versionFile))
        def versionCode = properties['VERSION_CODE'].toInteger()//读取version.properties文件存放的版本号。
        properties['VERSION_CODE'] = (++versionCode).toString()
        properties.store(versionFile.newWriter(), null)
        return versionCode
    } else {
        throw new Exception("无法读取version.properties文件!")
    }
}

//频繁测试发布时配置自动追加 -SNAPSHOT 后缀
def getVersionName() {
    def versionFile = file('./version.properties')
    if (versionFile.canRead()) {
        Properties properties = new Properties()
        properties.load(new FileInputStream(versionFile))
        //这里可以根据 gradle.startParameter.taskNames 任务名称进行判断是打包快照版本还是正式版本
        return properties['VERSION_NAME'].toString() + "." + getVersionCode() + "-SNAPSHOT"
    } else {
        throw new Exception("无法读取version.properties文件!")
    }
}

SNAPSHOT上传 版本号必须以SNAPSHOT结尾

通过上面的配置已经可以实现打包上传了。由于我的部分模块功能还处于开发阶段,就想着每次编译自动打包上传到Nexus私有仓库。显然这样频繁的上传不适用于release的仓库,应该上传至SNAPSHOT。可尝试了多种方法仍旧不能上传到SNAPSHOT,知道看到一个 官方例子
我尝试着将版本号追加SNAPSHOT后缀,然后就神奇的可以了。上面的库 Module 的 build.gradle 已经包含了这个设置。

持续打包,持续测试

原本以为这样就天高任鸟飞了,但实践时发现不是这样的。频繁发布时需要不停的修改打包以及集成的版本,真心累。Google了半天大部分的答案是做如下配置:

//在主 Module 的 build.gradle 配置
configurations.all {
    // check for updates every build
    resolutionStrategy{
        cacheDynamicVersionsFor 0, 'seconds'
    }
}

我做了上述配置还是不会自动更新。于是便另觅它法,自动升级库版本号,而主 Module 自动使用最新的版本。同样上面的库的 build.gradle 已经做了版本自增长逻辑,还需要在库 Module 根目录下增加一个 version.properties 文件,每次回追加一个自增长的数字(0.0.1 0.0.2 0.0.3 .... 0.0.n)。当做大的升级时,修改下 VERSION_NAME 并重置 VERSION_CODE=0 即可。

#Thu Jan 17 18:53:14 CST 2019
VERSION_NAME=0.0
VERSION_CODE=0

集成私有库

要想使用私有的库,需要做如下配置:
配置私有的 Nexus 仓库地址,包括 release 仓库,snapshots 仓库。

//工程的 build.gradle
maven {
    url "http://:port/repository/xxxx-releases/"
}
maven {
    url "http://:port/repository/xxxx-snapshots/"
}

在应用打包的仓库时,如果想每次获取最新的库,需要设置一个动态的版本,下面的两种形式都可以:

//主 Module 的 build.gradle
implementation '::latest.integration'
// implementation '::0.0.+-SNAPSHOT'

到这里基本就可以满足基本的需求了,欢迎大家批评指正。


你可能感兴趣的:(Kotlin与Java混编项目的Nexus私有仓库持续交付与集成)