十、版本管理

作者: 小炼君 | 来源:发表于2017-08-29 00:22 被阅读184次

    还没写够呢,就结束了??怎么行,还有40多分钟,还可以记一篇,接着干!!!


    任性.jpg

    这篇我们来谈谈版本控制相关的东西,很实用的东西,快快藏兜里
    在团队开发过程中,我们都应该使用maven的快照版本,maven根据快照版本机制解析这种特殊的版本。当项目需要发布时,我们需要把快照版本改成发布版本,这样唯一的定位到某一个构件,太泛了?没关系,且听我娓娓道来
    项目开发过程中版本切换流程如下:

    项目开发版本流程.png

    SNAPSHOT表示的是一个开发过程,1.0,1.1,1.2表示项目发布的某一个时刻,在这个时刻项目是比较稳定的
    快照版本要切换到发布版本应该满足以下几个条件:

    1. 所有自动化测试应当全部通过
    2. 项目没有快照版本的依赖存在
    3. 项目没有快照版本的插件依赖存在
    4. 项目包含的代码已经全部提交到版本控制系统中

    项目发布与tag的关系

    版本控制系统记录着代码的每一个变化,通常这些变化都被维护在master主干上,但是当项目发布的时候就应该用tag记录这一特殊时刻的状态,这样我们就可以快速的回到项目发布的那个tag时刻

    maven版本号定义

    1.3.4-beta-2版本为例作说明,它的含义是在一个重大的版本的第三个次要版本的第四次增量版本beta-2里程碑
    以上面的例子来讲
    1 - 表示重大版本更变,包括项目的结构,比如struct1structs2
    3 - 表示次要版本,通常意味着大范围的功能功能增加变化以及bug修复,但从总体架构来说没有发生变化
    4 - 增量版本,一般表示重大的bug修复,比如1.4.0发布之后,用户反馈了一个非常重大的bug,需要立即修复,那么就需要针对1.4.0发布版开一个1.4.1-SNAPSHOT增量版本解决这个BUG并发布1.4.1版本,同时将更变同步到后面的版本开发分支中
    beta-2 - 表示一个版本的里程碑,但是相比于发布版本,这种里程碑又是不稳定的

    主干、标签、分支

    主干(master),项目开发代码的主体,从项目开始到当前都处于活动状态,所有的分支最终都会合并到主干上,在主干中可以得到所有的历史更变
    分支(branches),从主干某一个点分离出来的代码拷贝,用于独立主干进行实验性功能开发、bug修复等
    标签(tag),用于标识主干某一个点的状态,通常在发布项目的时候使用
    下面是一个项目开发流程,其中涉及了主干、分支、标签之间的相互使用:
    项目从1.0.0-SNAPSHOT开始,经过长时间的开发,1.0.0发布版上线,接着进入1.1.0-SNAPSHOT开发,又经过长时间开发,1.1.0发布版上线,项目进入1.2.0-SNAPSHOT,但是在1.1.0版本中用户反馈了一个重大bug,需要及时修复,于是从1.1.0从独立出一个1.1.1-SNAPSHOT增量分支,用于修复这个bug,修复测试完成后1.1.1发布版上线,同时将1.1.1所做的更变同步到项目1.2.0-SNAPSHOT开发中,一段时间后发布1.2.0,项目继续进入1.3.0-SNAPSHOT开发中......

    项目开发版本控制流程.png

    自动化版本发布(发布项目)

    maven提供了可以自动化发布版本的一系列插件,这样可以将项目发布这一复杂流程仅仅通过几个简单的maven命令就可以轻松搞定,其中maven-release-plugin就是专门干这事儿的插件
    release插件有三个目标:prepare,rollback,perform用于项目自动发布
    release:prepare项目发布前准备配置,具体涉及:

    1. 检查项目是否有未提交的代码,存在则报错
    2. 检查项目是否有快照版本依赖
    3. 根据用户输入将快照版本替换为发布版
    4. pom中的scm信息更新为标签地址
    5. 基于修改后的pom执行maven构建
    6. 提交pom更变
    7. 基于用户输入为项目打发布版标签
    8. 将代码从发布版更变为新的快照版
    9. 提交pom更变
      release:rollback回退release:prepare所执行的操作,pom退回至release:prepare之前的状态,但是它并不会删除生成的标签,需要手动删除:
    # 查看本地标签
    git tag -l
    # 删除本地指定的tagname标签
    git tag -d tagname
    # 删除远程仓库中生成的标签
    git push origin --delete tag tagname
    

    release:perform,执行版本发布,签出release:prepare生成的标签中的源代码,并在此基础上执行mvn deploy命令打包并部署到项目仓库中,所以这里需要为项目配置部署仓库
    为了使用maven-release-plugin进行项目的自动发布,我们的项目pom需要进行下面的配置

    1. 配置scm版本控制信息
    <project>
    ...
    <!--配置项目发布信息-->
        <scm>
            <!--项目git地址,这里是只读的-->
            <connection>scm:git:https://github.com/zl736732419/account-parent.git</connection>
            <!--项目git地址,这里是可写的-->
            <developerConnection>scm:git:https://github.com/zl736732419/account-parent.git</developerConnection>
            <!--master分支的浏览器地址,这里需要点击分支master-->
            <url>https://github.com/zl736732419/account-parent/tree/master</url>
          <tag>HEAD</tag>
        </scm>
    </project>
    

    url:是项目分支的地址,具体需要进入项目的分支页面

    github分支页面.png github分支页面1.png
    1. 配置好scm后,需要配置maven-release-plugin插件
    <!--版本发布插件-->
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-release-plugin</artifactId>
        <version>2.5.3</version>
        <configuration>
            <!--配置tag,用于版本发布,mvn release:prepare,rollback,perform-->
            <tagBase>https://github.com/zl736732419/account-parent/tags</tagBase>
            <!--用于切换分支,修复bug mvn release:branch-->
            <branchBase>https://github.com/zl736732419/account-parent/branches</branchBase>
            <!--用于解决release与gpg之间的一个bug-->
            <mavenExecutorId>forked-path</mavenExecutorId>
        </configuration>
    </plugin>
    

    注意如果直接运行mvn release:prepare可能会遇到error: no such device or address错误,这需要提供仓库的访问权限,具体通过下面方式运行prepare命令
    mvn clean release:prepare -Dusername=username -Dpassword=password -DautoVersionSubmodules=true
    autoVersionSubmodules=true表示在运行过程中,子项目版本跟随父项目变化,如果没有配置这项参数,那么在运行过程中,会让用户自己手动确认每一个子项目的发布版本以及新的快照版本
    在这个过程中我们已经在本地和远程仓库中创建了标签,可以去远程仓库项目标签页面进行查阅比如github:

    自动部署后的标签.png

    执行成功后,使用perform将项目部署到本地仓库
    mvn release:perform -Dusername=username -Dpassword=password
    通过这条命令,maven会将刚才release:prepare生成的标签对应的发布版源码进行打包部署,在项目中生成.jar -sources.jar,-javadoc.jar,后面两项是超级pom中设置的profile出发导致的结果:

    <profile>
          <id>release-profile</id>
    
          <activation>
            <property>
              <name>performRelease</name>
              <value>true</value>
            </property>
          </activation>
    
          <build>
            <plugins>
              <plugin>
                <inherited>true</inherited>
                <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>
    

    上面的这种隐式设置maven官方不推荐这么做,可能在将来pom中的这项设置会被移除,所以建议在开发时显示设置出来,这样也更清晰

    自动化创建分支(修改bug)

    在上面提到的项目开发流程中,在1.1.0发布版出现了重大bug,于是需要独立出1.1.1-SNAPSHOT增量版本对bug进行修复,这一过程通过maven-release-plugin也可以做到自动化
    需要使用到release插件的branch命令
    为了使用branch命令,所以插件需要配置分支的信息

    <!--版本发布插件-->
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-release-plugin</artifactId>
        <version>2.5.3</version>
        <configuration>
            <!--配置tag,用于版本发布,mvn release:prepare,rollback,perform-->
            <tagBase>https://github.com/zl736732419/account-parent/tags</tagBase>
            <!--用于切换分支,修复bug mvn release:branch-->
            <branchBase>https://github.com/zl736732419/account-parent/branches</branchBase>
            <!--用于解决release与gpg之间的一个bug-->
            <mavenExecutorId>forked-path</mavenExecutorId>
        </configuration>
    </plugin>
    

    mvn release:branch -DbranchName=1.1.1 -DupdateBranchVersions=true -DupdateWorkingCopyVersions=false -Dusername=username -Dpassword=password -DautoVersionSubmodules=true
    updateBranchVersions表示分支使用新的版本
    updateworkingCopyVersion 表示不更新本地代码的版本,这时本地和远程已经生成了分支,但是需要手动切换分支

    gpg签名(防盗改)

    这里有两种方式,一种是通过手动方式进行gpg验证配置,还有一种是借助maven插件完成gpg自动配置

    手动方式
    gpg主要是用于检查当前用户下载的依赖包是否是完整的,在发布过程中,是否经过非法修改,全名为pretty good privacy
    当从中央仓库中下载下来构建之后,你可能需要验证这些构件的合法性,比如是否是原版,没有被篡改过,要达到上面的验证功能,需要下载pgp,支持windowslinux多种版本
    这里我下载的是windows
    gpg工作原理是首先通过gpg生成一对公、私密匙串、通过私匙对目标文件进行签名,生成.asc二进制的签名文件,将源文件与签名文件发给用户,同时将公匙发布到公钥服务器,用户得到签名文件与源文件,再到公钥服务器下载指定的公钥验证源文件是否一致
    gpg官网地址:https://www.gnupg.org/download/index.html

    gpg下载.png 设置gpg环境变量.png

    如此gpg就可以正常使用了,我们可以在cmd中查看gpg版本进行验证
    gpg --version

    查看gpg版本.png

    安装完成后我们在为目标文件进行签名时,还需要做一步:生成一对密匙串
    gpg --gen-key
    会提示输入自己的名称、邮箱、密码
    公钥会被公开发布到公钥服务器上,所以请务必填写密码
    生成密匙之后可以通过
    gpg --list-keys
    查看本机存在的公钥

    查看本机gpg公钥.png

    通过gpg --list-secret-keys查看私钥

    查看本机gpg私钥.png

    有了公钥和私钥之后,就可以对目标文件进行签名了
    gpg -ab account-web.war
    -a表示gpg创建ascII格式的输出,-b表示gpg创建一个独立的签名文件,因此会生成一个account-web.war.asc的签名文件
    将公钥上传至公钥服务器
    gpg --keyserver hkp://pgp.mit.edu --send-keys 49CFD654
    这里的49CFD654是通过gpg --list-keys查看的公钥的id
    将源文件account-web.war,与签名文件account-web.war.asc发给用户,用户需要对
    源文件account-web.war进行签名验证,需要从公钥服务器中下载公钥
    gpg --keyserver hkp://gpg.mit.edu --recv-keys 49CFD654
    然后执行
    gpg --verify account-web.war.asc对源文件签名进行验证,如果是没有被篡改的一致的文件,则会给出Good signature,否则给出Bad signature

    插件方式
    手动配置·pgp是一项啰嗦的事情,能不能在项目发布的时候自动签名,省去用户一切烦恼,这岂不是更爽,如此maven-pgp-plugin`就发挥作用了

    1. 首先要确保的是你的pgp是可用的,也就是安装上且在命令行中可以访问
    2. 已经生成了密匙对
      为了修复release插件与pgp插件结合是的一个bug,需要提供mavenExecutorId配置
    <!--版本发布插件-->
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-release-plugin</artifactId>
        <version>2.5.3</version>
        <configuration>
            <!--配置tag,用于版本发布,mvn release:prepare,rollback,perform-->
            <tagBase>https://github.com/zl736732419/account-parent/tags</tagBase>
            <!--用于切换分支,修复bug mvn release:branch-->
            <branchBase>https://github.com/zl736732419/account-parent/branches</branchBase>
            <!--用于解决release与gpg之间的一个bug-->
            <mavenExecutorId>forked-path</mavenExecutorId>
        </configuration>
    </plugin>
    
    <project>
        ......
        <profiles>
            <!--在项目发布时对构建进行签名,这里是结合release使用-->
            <profile>
                <id>release-sign-artifacts</id>
                <activation>
                    <property>
                        <name>performRelease</name>
                        <value>true</value>
                    </property>
                </activation>
                <build>
                    <plugins>
                        <plugin>
                            <groupId>org.apache.maven.plugins</groupId>
                            <artifactId>maven-gpg-plugin</artifactId>
                            <version>1.6</version>
                            <executions>
                                <execution>
                                    <id>sign-artifacts</id>
                                    <phase>verify</phase>
                                    <goals>
                                        <goal>sign</goal>
                                    </goals>
                                </execution>
                            </executions>
                        </plugin>
                    </plugins>
                </build>
            </profile>
        </profiles>
    </project>
    

    配置完成后,需要修改release插件执行目标perform的命令
    mvn release:perform -Dusername=username -Dpassword=password -Darguments=-Dgpg.passphrase=pgp password
    下面是运行后私服中存在的asc文件

    image.png

    好啦,又折腾了2个小时,还有其他的事情要干呢,今天的笔记就到这里啦

    相关文章

      网友评论

        本文标题:十、版本管理

        本文链接:https://www.haomeiwen.com/subject/dxendxtx.html