
Maven依赖自动更新问题研究
1. 问题描述
之前在GE11项目中,APP的公共依赖从公司self-hosted的Nexus maven仓库中拉取,而依赖更新发布则是使用Gradle的maven_publish插件配合自定义脚本推送到上述仓库。
实际开发中我们遇到了一个问题,依赖有更新时只会刷新maven仓库中的制品,此时APP重新编译并不会从maven拉取最新的依赖而是直接使用本地缓存。这在项目开发初期引发了很多问题,显著阻碍了开发的进度。
2. 临时方案
在项目中后期,因为第一时间没有找到较好的解决方案且项目工期太紧,每个开发都被逼学会了编译前先删除gradle cache的hack solution,显然这样虽然解决了问题,但既耗时又不可靠。一定存在一个更合理更优雅的解决方案。
3. 研究重启
现在GE11项目第一阶段已经接近尾声,我在继续开发核心库时需要升级版本,但觉得应该使用SNAPSHOT机制来发布。简单搜索到这个理解Maven中的SNAPSHOT版本和正式版本,其中这段话勾起了我之前的痛苦回忆,想起来之前悬而未决的问题:
4. 本地模拟和问题解决
为了能更好的还原我们的开发环境,在机器上自己搭建了一个nexus来做模拟验证,同时继续疯狂Google和看gradle以及maven的文档来寻找答案。
Maven和Gradle是两个不同的构建系统,上述图片里的xml片段是项目使用maven构建时配置用的,不能用于我们开发 Android APP 使用的 Gradle。
在尝试的过程中,我发现nexus部署后默认会创建几个repo,其中就有maven-snapshots
同时Gradle文档里对snapshot相关的介绍,表示正常如果需要发布snapshot版本,要发布到单独的snapshots仓库:
于是我修改已有的发布脚本,通过判断版本名是否以SNAPSHOT
结尾来确定发布到maven的仓库类型
实验之后发现snapshots仓库可以保存所有历史发布过的同版本依赖:
那么剩下的问题就是如何保证Gradle每次构建时自动拉取最新的依赖,有人在StackOverflow上提出了类似的问题
只需要在项目的build.gradle中添加下面的配置,每次编译gradle就会拉取snapshot版本或标记了changing = true
的依赖的最新版本。
configurations.all {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
原因是Gradle默认保存changing的依赖24小时,需要使用这个配置来改为0秒,下面的回答还提到了Gradle 6+以后snapshot依赖默认changing=true(相关链接)
至此问题解决,交叉验证通过。
记得之前有尝试过在依赖后面添加 changing = true
,无效的原因现在也找到了。然而,随后我在项目的deps.gradle
里发现了这个片段,cacheChangingModulesFor
被设置为了12小时……
需要补充的是,第二个配置cacheDynamicVersionsFor
是对动态版本依赖的缓存策略配置,例如xxx:1.0+
或者xxx:latest
。具体可以看官方文档:文档1,文档2
releases仓库部署策略
值得一提的是,在用本地nexus测试的时候,我发现默认release仓库是不允许相同的版本反复修改的,如果不在后台将repo默认的部署策略配置改为Allow redeploy,我们publish是会失败的。
报错如下:
Execution failed for task ':library-core:publishReleasePublicationToMavenRepository'.
> Failed to publish publication 'release' to repository 'maven'
> Could not PUT 'http://127.0.0.1:8081/repository/maven-releases/com/pateo/app/corelib/PateoPlayerAndSessionMgr/android/PlayerAndSessionMgr_Player/1.0.0/PlayerAndSessionMgr_Player-1.0.0.jar'.
Received status code 400 from server: Repository does not allow updating assets: maven-releases
6. 结论
在开发过程中应该使用 snapshots 库,稳定后发布到 releases 库,保证开发时敏捷,发布后稳定。
使用Gradle构建时为了保证取用最新snapshot版本,需要修改
cacheChangingModulesFor
为较小数值releases库的部署策略不应该启用允许重复部署,确保版本稳定
在向制品库发布正式版本时,最好同时打Git TAG,确保可追溯(可以整合进发布脚本来实现自动化)