天天看點

使用Maven和Docker進行持續傳遞中的版本号管理動機解決方案:利用Git送出哈希實作開放問題和讨論

動機

我們來思考下持續傳遞的原則。

  • 每次建構的結果可能是一個潛在的發行版本
  • 消除手動瓶頸
  • 盡可能自動化

這三點正是我們想要實作的,但是在實作之前,我們先來看下在典型的Maven釋出流程和經典方式版本号管理上的具體問題。

沒有自動化

通常來說,一次送出會觸發一個快照建構,然後生成一個快照構件(“8.1.2-SNAPSHOP”)。當開發者感覺軟體到達穩定狀态後,他會觸發一次專用釋出建構。是以,他預先配置設定版本号(“8.2.0”)

使用Maven和Docker進行持續傳遞中的版本号管理動機解決方案:利用Git送出哈希實作開放問題和讨論

人員必須配置設定版本号然後觸發釋出建構

這種方式有什麼缺點:

  • 我們需要手動觸發專用的釋出工作流程
  • 版本号需要人為手動配置設定
  • 此外,僅看版本号“8.2.0”并不清晰,比如這個版本号的構件中包含了哪些送出(代碼)。我們需要一個Git标簽

任意快照

此外,快照引起了許多問題。

使用Maven和Docker進行持續傳遞中的版本号管理動機解決方案:利用Git送出哈希實作開放問題和讨論

不清晰的内容變動

  • 不可追蹤。我們不能說,有哪些送出包含在了目前的快照構件中。
  • 不可靠。快照構件可以很快速的修改。這樣很容易引起問題
  • 易出錯。不過不注意,很容易覆寫一個快照(比如:當建立Git分支的時候,忘記修改POM檔案中的版本号。從Git分支上建構會覆寫之前的快照)

讓人生氣的Maven釋出插件

最後,Maven的釋出插件也引起了許多問題:

  • 開銷。Maven釋出插件運作3次完整的構件和測試周期,展開POM檔案兩次和建立三次Git修訂(Git revisions)
  • 不具有隔離性。當其他人在釋出版本期間送出更改時,插件可能容易陷入混亂。
  • 不具有原子性。如果最後一步出現問題(比如:在構件上傳期間),突然發現緊急Bug。我們必須清理建立的Git标簽,Git修訂和修複錯誤版本

解決方案:利用Git送出哈希

我們使用Git送出哈希來作為構件的版本号

使用Maven和Docker進行持續傳遞中的版本号管理動機解決方案:利用Git送出哈希實作開放問題和讨論

使用Git送出哈希作為版本号

  • 每個建構都incident,有一個機器配置設定的唯一号碼
  • 是以,每個構件都是潛在可傳遞的。是以這裡不需要一個專用的釋出流程。
  • => 傳遞管道大大簡化和自動化
  • 可追蹤。這很明顯,哪些送出被包含到構件中。
  • 重複性。隻需檢出版本并再次進行建構構件(假設沒有快照依賴)。
  • 基本上,Git标簽不再需要了。

實作

讓我們在Maven建構中內建版本命名。下面的事例建構生成一個簡單的Spring Boot服務作為Fat Jar。此外,我們把Fat Jar包裝到Docker鏡像中,并部署鏡像。完整的源碼可以在GitHub中檢視。

為了增加人的可讀性,我們把時間戳作為Git送出哈希的字首。是以,我們的版本号如下所示:

format:  yyyyMMdd-HHmmss.abbreviatedCommitHash
example: 20160702-152019.75c54f5
           

使用Git送出哈希作為版本号

這是最重要的一步,我們使用 git-commit-id-plugin 。這個插件可以從.git目錄讀取Git送出哈希和送出時間戳,并可以在POM中可以使用Maven屬性使用。

<plugin>
    <groupId>pl.project13.maven</groupId>
    <artifactId>git-commit-id-plugin</artifactId>
    <version>2.2.1</version>
    <executions>
        <execution>
            <phase>validate</phase>
            <goals>
                <goal>revision</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <dateFormat>yyyyMMdd-HHmmss</dateFormat><!--  human-readable part of the version number -->
        <dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
        <generateGitPropertiesFile>false</generateGitPropertiesFile><!-- somehow necessary. otherwise the variables are not available in the pom -->
    </configuration>
</plugin>
           

下一步,我們可以在Maven屬性中添加包含了Git送出哈希和送出時間戳的版本号屬性。

<properties>
   <version.number>${git.commit.time}.${git.commit.id.abbrev}</version.number>
</properties>
           

現在,我們可以在version标簽中使用這個屬性。

<groupId>de.philipphauer.blog</groupId>
<artifactId>versioning-continuous-delivery</artifactId>
<version>${version.number}</version>
           

使用方式:

> mvn package # creates the jar with the desired version number
> java -jar target/versioning-continuous-delivery-20160702-180249.193a613.jar # starts the service
           

使用版本号建立、标記Docker鏡像

我們使用 io.fabric8 的docker-maven-plugin來建立鏡像。重要的部分是标簽。我們建立兩個标簽。一個标簽以送出ID命名(“20160702-153902.7c12eb”),另一個以“latest”命名。latest标簽将會簡化本地測試。

<plugin>
    <groupId>io.fabric8</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.15.9</version>
    <extensions>true</extensions>
    <configuration>
        <authConfig> <!-- or use "docker login" up front to store the credentials on the local machine. -->
            <username>phauer</username>
            <password>docker123</password>
        </authConfig>
        <images>
            <image>
                <name>${docker.repository.name}:${version.number}</name>
                <alias>${project.artifactId}</alias>
                <build>
                    <from>anapsix/alpine-java:jre8</from>
                    <tags><!-- define additional tags for the image -->
                        <tag>latest</tag>
                    </tags>
                    <assembly>
                        <descriptor>assembly.xml</descriptor>
                    </assembly>
                    <ports>
                        <port>8080</port>
                    </ports>
                    <cmd>
                        <shell>
                            java -jar /maven/${project.artifactId}-${version.number}.jar
                        </shell>
                    </cmd>
                </build>
            </image>
        </images>
    </configuration>
    <executions>
        <execution>
            <id>build-docker-image</id>
            <phase>package</phase>
            <goals>
                <goal>build</goal>
            </goals>
        </execution>
        <execution>
            <id>push-docker-image-to-registry</id>
            <phase>deploy</phase>
            <goals>
                <goal>push</goal>
            </goals>
        </execution>
    </executions>
</plugin>
           

不要忘記assembly.xml和如下的屬性:

<docker.repository.name>phauer/${project.artifactId}</docker.repository.name>
           

用法:

> mvn package # creates a docker image and installs it to the local repository

> docker images
REPOSITORY                                                TAG                              IMAGE ID            CREATED             SIZE
phauer/versioning-continuous-delivery                     20160702-174649.28b5299          12d7a526c506        2 seconds ago       135.8 MB
phauer/versioning-continuous-delivery                     latest                           12d7a526c506        2 seconds ago       135.8 MB

> docker-compose up # starts the local image with the tag "latest"

> mvn deploy # pushes the image to the docker registry
           

完整的pom.xml和docker-compose.yml可以在GitHub中檢視。

開放問題和讨論

部署構件的Git标簽

有時,在真正部署的時候,使用專用的Git标簽來标記一個構件是非常友善的。你可以在部署後自由标記相應的Git修訂版本。你可以手動執行此操作,也可以在最終的deploy流程中內建。後者使工作流程自動化。

構件泛濫問題的處理

每次建構都會帶出一個新的構件,我們在我們的存儲庫中面臨着大量的構件。是以,我們必須清理:

  • 但是我們怎麼知道已經部署了哪些版本?我們不想删除目前正在生産環境的構件。是以,我們必須維護已部署的版本清單,并在清理期間跳過他們。我們可以通過使用Git标簽來實作此目的,即當構件部署的時候,我們建立一個Git标簽。我們也可以在任意地方儲存版本号清單。
  • 說實話,删除曾經是生産中的構件沒有問題。你曾復原到一年前的構件過嗎?通常來說,你隻需要目前部署的構件和它之前幾個。

檢查快照依賴關系

當發現快照依賴時,maven-release-plugin會中止建構。這基本上沒問題,因為快照依賴阻止了建構的可重複性。我們缺乏這種檢查。但是,我認為這在實踐中不是什麼大問題。

  • 這很少發生。通常開發人員在釋出快照依賴之前會注意并删除快照依賴。
  • 當我們對我們的庫應用建議的版本号概念時,我們根本沒有快照。
  • 即使我們的構件包含快照,快照仍然捆綁在構件(fat jar或者Docker鏡像)中。構件儲存在系統資料庫中,然後測試到最終釋出。如果我們在我們的系統資料庫中有建構的構件,我們真的需要重複建構嗎?

使用建構時間戳替換Git送出哈希

有一種版本方式是使用建構的時間戳來替換送出哈希。因為下面的原因,我更傾向于送出哈希:

  • 顯示的跟蹤版本号送出
  • 基本上不需要Git标簽
  • 基于給定修訂,可在現構件

Docker是此版本控制方法所必須的嗎?

基本上不是。如果你的Maven建構隻生成一個jar,也可以應用建議的方法。在這種情況下,我們還是使用Git送出哈希作為Jar的版本号。

但是,有一個問題,有git-commit-id-plugin插件建立的預設屬性不會被maven-install-plugin和maven-deploy-plugin插件解析到。這裡有一個解決方案。

此外,Docker讓事情變得更簡單。Maven隻允許一個構件隻能有一個版本号。Docker允許一個鏡像有多個标簽。你可以使用“7d1dcc”和“latest”共同标記一個鏡像。latest對于本地測試非常有用。你可以一直使用latest鏡像,而不是永遠的提升版本号(比如在本地docker-compose.yml中)

----------------------------------------------------------------------------------------------------

原文:https://blog.philipphauer.de/version-numbers-continuous-delivery-maven-docker/

版權聲明:本文為CSDN部落客「weixin_33862041」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。

原文連結:https://blog.csdn.net/weixin_33862041/article/details/93719335