1. 版本管理( Version Management )是指项目整体版本的演变过程管理,如从 1.0.0-SNAPSHOT 到 1.0.0 。版本控制( Version Control )是指借助版本控制工具( VCS )追踪代码的每一个变更。
2. 理 想的发布版本应该对应项目某个时刻比较稳定的状态,应满足以下条件:
1) 所有自动化测试应通过
2) 项目没有快照版本的依赖
3) 项目没有配置快照版本的插件
4) 项目包含的代码已全部提交到版本控制系统中。
3. 在 VCS 中使用标签可以明确地将某个源码版本(也就是项目的某个状态)从主干中标记出来,这样在之后的任何时刻,我们都能够快速地得到发布版本的源代码,从而能够比较各个版本的差异,甚至重新构建一个同样版本的构件。
4. 从快照版本更新至发布版本之后,应该再执行一次 Maven 构建,确保项目状态是健康的,再将更新提交到 VCS 的主干中。接着再为当前主干的状态打上标签。
5. Maven 的版本号定义为:
< 主版本 >.< 次版本 >.< 增量版本 >-< 里程碑版本 >
1) 主版本:项目重大架构变更
2) 次版本:较大范围功能变化及 Bug 修复
3) 增量版本:重大 Bug 修复
4) 里程碑版本:一个版本的 milestone ,表示不是非常稳定,还需要很多测试
Maven 对前三者的比较是基于数字的,对里程碑版本只进行简单的字符串比较。
6. VCS中有如下概念:
1) 主干( trunk ):项目开发代码的主体,从项目开始直到当前都处于活动状态,可以获得项目最新源码及所有变更历史。
2) 分支( branch ):从主干的某个点分离出来的代码拷贝,通常是为了在不影响主干的前提下进行重大 Bug 的修复或做些实验性质的开发,当分支达到预期的目的后,分支上的变更会被合并到主干上。如下图中为了不影响 1.2.0 的开发,从 1.1.0 分了一个分支出来进行 Bug 修复。
3) 标签( tag ):用来标识主干或者分支的某个点的状态,以某个稳定状态(通常是版本发布时的状态)
7. Maven Release Plugin 能完成所有版本发布所涉及的操作,它主要有三个目标:
1) release:prepare :准备版本发布,主要执行以下操作:
a) 检查项目是否有未提交代码
b) 检查项目是否有快照版本依赖
c) 根据用户输入将快照版升级为发布版
d) 将 POM 中的 SCM 信息更新为标签地址
e) 基于修改后的 POM 执行 Maven 构建
f) 提交 POM 变更
g) 基于用户输入为代码打标签
h) 将代码从发布版升级为新的快照版
i) 提交 POM 变更
2) release:rollback :回退 release:prepare 所执行的所有操作,提交回退后的 POM ,但不会删除标签
3) release:perform :执行版本发布。签出 release:prepare 生成的标签中的源代码(注意:这里是按标签地址签出原代码, POM 中的版本还是发布版本 ) ,并在此基础上执行 mvn deploy 。
POM 中的 SCM 信息会不会再变到非标签地址 ? (新的快照版本的 scm 地址)还是需要手动自己更新?
8. 可以在 POM 中( project 元素下)配置 SCM 的信息如下:
<scm> <connection>scm:svn:http://192.168.1.103/app/trunk</connection> <developerConnection>scm:svn:https://192.168.1.103/app/trunk</developerConnection> <url>http://192.168.1.103/account/trunk</url > </scm>
connection 元素表示只读的 scm 地址, developerConnection 元素表示可写的 scm 地址,两者必须以 scm 开头,冒号之后表示版本控制工具的类型,接下来才是实际 scm 地址。 url 则表示可在浏览器中访问的 scm 地址。
9. 可以在 POM 中配置 Maven Release Plugin :
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-release-plugin</artifactId> <version>2.0</version> <configuration> <tagBase>https://192.168.1.103/app/tags/</tagBase> </configuration> </plugin>
执行 mvn release:prepare ,如果项目有未提交的代码或者有快照版本依赖,则会提示出错。如果一切正确,则会提示用户输入发布版本号、标签名以及新的快照版本号( SVC 命令行工具需要自己安装)。标签地址为 <tagBase> 中的地址加上新的标签名。( https://192.168.1.103/app/tags/app-1.0.0 )
10. 在多模块项目中,如希望所有模块的发布版本和新的快照版本都保持一致,可以设置 -DautoVersionSubmodules=true 参数
11. 在超级 POM 中定义了如下配置:
<profiles> <!-- NOTE: The release profile will be removed from future versions of the super POM --> <profile> <id>release-profile</id> <activation> <property> <name>performRelease</name> <value>true</value> </property> </activation> <build> <plugins> <plugin> <inherited>true</inherite> <artifactId>maven-source-plugin</artifactId> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <inherited>true</inherited> <artifactId>maven-javadoc-plugin</artifactId> <executions> <execution> <id>attach-javadocs</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <inherited>true</inherited> <artifactId>maven-deploy-plugin</artifactId> <configuration> <updateReleaseInfo>true</updateReleaseInfo> </configuration> </plugin> </plugins> </build> </profile> </profiles>
这个 profiler 配置了三个插件,分别用来为项目生成 -source.jar ,为项目生成 -javadoc.jar 以及更新仓库中的元数据,告诉仓库该版本是最新的发布版。每个插件中值为 true 的 interited 元素表示该插件配置可以被子 POM 继承。而这个 profile 的激活条件是运行环境中有名为 performRelease 属性且值为 true 。而 release:perform 会自动生成 -DperformRelease=true 参数。由于这种隐式的配置十分令人费解,会在后面版本的 Maven 中去除,让用户自己在 POM 中显示配置这些插件。
12. Maven Release Plugin 的 branch 目标会执行以下操作:
1) 检查本地有无未提交代码
2) 为分支更改 POM 的版本
3) 将 POM 中的 SCM 信息更新为分支地址
4) 提交以上更改
5) 将主干的代码复制到分支中
6) 修改本地代码使其回退到分支之前的版本(用户可以指定新的版本)
7) 提交本地更改
为此我们还需要在 POM 中配置为 Maven Release Plugin 用 <branchBase> 元素配置分支地址。
执行 release:branch –DbranchName=1.1.1 –DupdateBranchVersions=true –DupdateWorkingCopyVersions=false 会提示用户输入新的 branch version 。
最后一个参数表示不更新本地代码(即主干)版本。
13. GnuPG (简称 GPG ,来自 http://www.gnupg.org )是 PGP ( Pretty Good Privacy )标准的一个免费实现,无论类 UNIX 平台还是 Windows 平台都可使用它。 GPG 能帮助我们为文件生成签名、管理密钥以及验证签名等。
14. 使用 gpg –gen-key 生成 GPG 密钥对。使用 gpg –list-keys 可以查看本机的所有公钥。使用 gpg –list-secret-keys 可以查看本机的所有私钥。
15. 使用 gpg –ab temp.java 可以为文件创建一个 ASCII 码的签名文件: temp.java.asc 。 -a 表示生成 ASCII 格式的输出, -b 表示创建一个独立的签名文件。将这两个文件及公钥一起给用户,用户可以用 gpg –verify temp.java.asc 来验证该文件。
16. 运行如下命令可以将公钥发布到公钥服务器中:
gpg –keyserver hkp://pgp.mit.edu –send-keys C6EED57A
这里 C6EED57A 就是用 —list-keys 看到的公钥 ID 。公钥会自动在各个服务器中被同步。
可以用如下命令获得公钥:
gpg –keyserver hkp://pgp.mit.edu –recv-keys C6EED57A
17. 可以在 POM 中配置 Maven GPG Plugin (但命令行 gpg 需要自己安装):
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-gpg-plugin</artifactId> <version>1.0</version> <executions> <execution> <id>sign-artifacts</id> <phase>verify</phase> <goals> <goal>sign</goal> <goals> </execution> </executions> </plugin>
用命令行 mvn clean deploy –Dgpg.passphrase=yourpassphrasesk 可以对你发布的构件进行自动签名。 Yourpassphrase 是你的私钥的密码(你在创建私钥的时候可以选择是否设一个密码。)
18. 用如下命令可以对已经发布的构件进行签名:
mvn gpg:sign-add-deploy-file –DpomFile=target/myapp-1.0.pom –Dfile=target/myapp-1.0.jar –Durl=http://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype_oss
该命令指定了要签名的 POM 及相关文件、 Maven 仓库的地址和 ID 。
19. 只有在项目正式发布的时候才需要签名,对日常的 SNAPSHOT 构件签名只会增加耗时。所以可以在 settings.xml 文件中新增一个 profile 来配置 GPG 插件,而 profile 的激活条件同样中 performRelease 为 true 。这样就能在执行 release:perform 时自动执行 GPG 插件了。但由于一个已知的 Maven Release Plugin 的 Bug ,执行 release:perform 过程中签名可能会 hung 住,所以需要为其在 confiuration 元素中增加:
<mavenExecutorId>forked-path</mavenExecutorId>