自動產出changelog-第二節:自動產出

背景

接上一篇《自動產出changelog-第一節:規範提交代碼》調研的後續,本文將基於 angular.js格式 的提交內容圍繞自動化產出進行後續調研。研究的方向爲產出內容的工具是否支持各類自定義特性,可否幫助咱們實現團隊的風格及自動化過程當中的一些問題。前端

簡述

在調研的過程當中大量的文章都會推薦使用 conventional-changelog/conventional-changelog 進行changelog的產出,而其餘包含更豐富功能的庫背後使用的依舊是這個工具進行內容的產出。其做者還製做了 conventional-changelog/standard-versionconventional-changelog/standard-release 兩套功能更爲豐富的工具供咱們使用,standard-release具備一個規範的使用前提,因此這個規範並不符合咱們團隊的狀況,下文討論將圍繞standard-version進行。而另外一個工具叫 release-it/release-it 的近三年比 conventional-changelog更活躍,具體選擇哪一個工具好?下面將給出參考。vue

standard-version

項目安裝git

$ npm i --save-dev standard-version

package.json加上下面這段內容後,調用 npm run release 使用github

{
  "scripts": {
    "release": "standard-version"
  }
}

全局安裝vue-cli

$ npm i -g standard-version # 使用 standard-version

直接使用npm

$ npx standard-version

調用standard-version後會輸出如下內容:json

$ npx standard-version
√ bumping version in package.json from 0.2.0 to 0.2.1
√ bumping version in package-lock.json from 0.2.1 to 0.2.1
√ outputting changes to CHANGELOG.md
√ committing package-lock.json and package.json and CHANGELOG.md
√ tagging release v0.2.1
i Run `git push --follow-tags origin master && npm publish` to publish

standard-version會爲咱們作如下行爲:segmentfault

  1. 緩存當前文件變化
  2. 將歷史回退至最後一個git標籤的位置(查看package.json中提供的信息來定位git標籤)
  3. 更新版本號
  4. 產出changelog文件
  5. 提交變更
  6. 打上新版本的git-tag

產出的changlog長這個樣子:數組

# Changelog

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### 0.2.1 (2021-04-09)


### Features

* 初次化 ([9d06990](http://gogs.infzm.com:22403///commit/9d06990aa9d4c82acfe4b0fd9c28c65dbdd89715))
* 增長邏輯 ([e8667aa](http://gogs.infzm.com:22403///commit/e8667aa136bec4836765deb31b60a76c48cad017))
* 新增一行輸出 ([c747a34](http://gogs.infzm.com:22403///commit/c747a347d2d53430c676b296bb2c06aacc4de937))

預覽操做行爲(不會實際執行),可以使用 --dry-run 嘗試操做:緩存

$ npx standard-version --dry-run

到這步都是使用默認的方式進行,後面開始探討自定義內容。

自定義

上面產出的changelog內容並非每一個團隊都承認的,一定存在須要改動的指望;其次還有在CI/CD工具中須要配合其餘工具一併使用,對於standard-version豐富的功能可否跳過也是一個重要的考量;最後一個是起自動更新版本號,版本號具備必定的語意(具體參考這篇文章《使用npm命令行更新版本號》),可否支持更細化的控制,就是另外一個重要的考量了。

因此最後須要弄清楚:

  • 可否自定義產出的changelog內容?能作何種程度的自定義呢?
  • 可否跳過一些standard-version提供的行爲呢?
  • 可否自定義更新版本號呢?
自定義產出Changelog內容

官方文檔中提到,要自定義配置能夠選擇兩種方式,寫在package.json裏面,或是令建一個.versionrc文件。standard-version將會在這兩處得到配置內容。下面選用獨立文件的配置方式進行說明。

建立.versionrc文件

$ touch .versionrc

.versionrc內容爲JSON格式,影響changelog產出設置的配置內容包含如下這些:

配置項 類型 描述
header String,字符串,支持'\n' 文檔的頭部內容,默認值爲:'# Changelog\n\nAll notable changes to this project will be documented in this file. See standard-version for commit guidelines.\n'
types Array, type對象數組 用於配置輸出的內容。type對象包含:type 對應commit錄入中的type;section 展現的文字內容;hidden 是否隱藏;例子:{"type": "feat", "section": "Features", "hidden": false}
preMajor Boolean,布爾值 用於控制是否顯示1.0.0版本以前的changelog。
commitUrlFormat String,字符串 提交內容可訪問地址,默認:{{host}}/{{owner}}/{{repository}}/commit/{{hash}}
compareUrlFormat String,字符串 兩個提交對比的可訪問地址,默認:{{host}}/{{owner}}/{{repository}}/compare/{{previousTag}}...{{currentTag}}
issueUrlFormat String,字符串 提問內容地址,默認:{{host}}/{{owner}}/{{repository}}/issues/{{id}}
userUrlFormat String,字符串 提交人可訪問的地址,默認:{{host}}/{{user}}
releaseCommitMessageFormat String,字符串 用於格式化自動生成的發佈落實消息的字符串。
issuePrefixes Array<String> or String,字符串或者字符串數組 用於檢索提問內容的標識,如:#39;默認是:['#']

格式文檔來自這裏:《Conventional Changelog Configuration Spec (v2.1.0)》,上面用到的模板變量(如:{{host}})在前面格式文檔最後有提交。

整合到文件內容以下面例子:

{
    "header":"# 更新歷史 \n\n",
    "types": [
        {"type": "feat", "section": "✨ Features | 新功能"},
        {"type": "fix", "section": "🐛 Bug Fixes | Bug 修復"},
        {"type": "perf", "section":"⚡ Performance Improvements | 性能優化"},
        {"type": "revert", "section":"⏪ Reverts | 回退"},
        {"type": "chore", "section":"📦 Chores | 其餘更新"},
        {"type": "docs", "section":"📝 Documentation | 文檔"},
        {"type": "style", "section":"💄 Styles | 風格", "hidden": true},
        {"type": "refactor", "section":"♻ Code Refactoring | 代碼重構"},
        {"type": "test", "section":"✅ Tests | 測試"},
        {"type": "build", "section":"👷‍ Build System | 構建"},
        {"type": "ci", "section":"🔧 Continuous Integration | CI 配置"}
    ]
}

經過這個配置產出的文檔內容以下:

# 更新歷史 


## 0.2.0 (2021-04-12)


### 🔧 Continuous Integration | CI 配置

* 增長CI支持 ([a2c8ced](https://github.com/lpreterite/datagent/commit/a2c8ced34e83d06b01fa068c0f94b2916f1baf76))
* 更新版本號 ([f445127](https://github.com/lpreterite/datagent/commit/f4451270a124aacd105bcdc6fd28df4eb7f5be20))


### 📝 Documentation | 文檔

* 更新CHANGELOG文件 ([6146cfa](https://github.com/lpreterite/datagent/commit/6146cfa0e9149f1dbd94dd135d79dd36441cf327))
* 更新文檔 ([cd214b8](https://github.com/lpreterite/datagent/commit/cd214b87db3362f8a198a03941dc6e0f52a05d6b))
* 更新文檔 ([c9dd688](https://github.com/lpreterite/datagent/commit/c9dd688f9f3f76b1d3068cb8ea73ee50dbe6229e))


### ⚡ Performance Improvements | 性能優化

* 更新代碼 ([b45cfed](https://github.com/lpreterite/datagent/commit/b45cfedea4b695a9684f488f62188080b75e69a6))


### ✨ Features | 新功能

* 初次化 ([9d06990](https://github.com/lpreterite/datagent/commit/9d06990aa9d4c82acfe4b0fd9c28c65dbdd89715))
* 增長邏輯 ([e8667aa](https://github.com/lpreterite/datagent/commit/e8667aa136bec4836765deb31b60a76c48cad017))
* 新增一行輸出 ([c747a34](https://github.com/lpreterite/datagent/commit/c747a347d2d53430c676b296bb2c06aacc4de937))


### 👷‍ Build System | 構建

* 更新依賴 ([fb5d568](https://github.com/lpreterite/datagent/commit/fb5d568de59ccf43cb2ccecc3acc95add07999a6))
* 更新本地設置 ([6665709](https://github.com/lpreterite/datagent/commit/66657097b5592228e93e7f3865b53ab80cc5610a))


### 📦 Chores | 其餘更新

* 更新cz-config配置用於支持vscode插件配置 ([2a726a4](https://github.com/lpreterite/datagent/commit/2a726a471a12c5323a6ce5707a703f7e1af35927))
* 更新package ([eda4316](https://github.com/lpreterite/datagent/commit/eda4316722a9d03f2fd5e60f61507a6e272ddc1b))
* 更新版本至0.2.0 ([397e19c](https://github.com/lpreterite/datagent/commit/397e19c09e6c932b594e225c00a9018e1627e764))
* 移除cz-conventional-changelog配置 ([5b8cd88](https://github.com/lpreterite/datagent/commit/5b8cd88d11d1e0a3db4cc888d9115ef579937aae))

這裏基本知足大部分團隊對Changelog自定義的功能,假如還須要更深刻的個性化操做,能夠基於 conventional-changelog-conventionalcommits 這個插件templates目錄中的模板文件,而後在使用時設置 --preset 指向改動後的預設項目來知足自定義需求。反正我找了一圈官網提供的內容都沒有找到更好的配置方法,突破口也是從standard-version --help 中看到,再配合掘金網友提供的資料 (vue-cli-plugin-commitlint)才能知道門道。固然可能存在封裝好能幫助解決自定義問題的倉庫,那位朋友知道更詳細的多謝告知一下,我後續會再完善這篇文章。

跳過特定流程

standard-version 工做流程包含幾個環節,其實每一個環節均可選擇跳過,具體能夠在.versionrc 文件中增長配置來實現:

{
    "skip": {
        "bump": true, //緩存變化,並重置git狀態至最近的tag節點
        "changelog": true, //自動產出changelog文檔
        "commit": true, //提交變更
        "tag": true //在git中增長tag標識
    }
}

也能夠經過命令行來實現:

$ npx standard-version --skip.changelog false
自定義提交
$ npx standard-version --message '%s版本更新'

%s內容會被替換爲當前的版本號。

吐槽一下,官方命令行提示說 --message 已淘汰,建議使用 releaseCommitMessageFormat 。但是在其代碼中卻沒找到 releaseCommitMessageFormat 這個選項的支持。 代碼傳送門
指定語義化版本

這裏有三個命令幫助咱們解決問題:

  • --first-release 初次發佈操做。這步操做並不會遞進版本號。npx standard-version --first-release
  • --prerelease 預發佈操做。npx standard-version -- --prerelease 版本會從0.2.0變爲0.2.0-0;npx standard-version -- --prerelease alpha能夠增長前序,版本會從0.2.0變爲0.2.0-alpha.0。
  • --release-as 指定發佈操做。npx standard-version -- --release-as minor 版本從0.2.0變爲0.3.0。

流程鉤子

standard-version在流程上更進一步的自定義控制,它提供了流程的執行先後的鉤子設置,可用於運行命令行。好比standard-version不支持自定義的issues地址(見issue#48),可經過在產出changelog後運行命令行進行替換。

{
    "standard-version": {
        "scripts": {
            "postchangelog": "replace 'MY GITHUB URL' 'MY JIRA URL' CHANGELOG.md"
        }
    }
}

具體還有比較多的其餘鉤子就不細說了,官網文檔有詳細說明(見#signing-commits-and-tags),這裏只提供一個思路。

小結

總的來講standard-version仍是能知足需求的達成生成changelog的任務。因爲它是一個較老的項目了,團隊主力都去維護standard-release,對於standard-version將來功能的改善推進效率不會過高。評價就是能用

release-it

在扒完standard-version的源碼後,對於前端項目的發佈工程流程環節有了更深的瞭解。基於這樣的背景下再學習release-it這個工具感受,它真的是簡單易懂。release-it 自己是交互式的工具,而下文討論內容圍繞着在 CI/CD工具 內容運做,帶上 --ci 參數就能進入靜默模式。

安裝

# 全局安裝
$ npm i -g release-it

# 項目安裝
$ npm i -D release-it

# 直接使用
$ npx release-it

release-it具體的工做流程:

  • 同步遠端內容
  • 更新版本號
  • 產出changelog
  • 提交變更
  • 增長git tag
  • 推送tag更新至遠端

經過--dry-run更能看到詳細的行爲:

$ npx release-it --dry-run --ci

# 下面是執行過程
$ git diff --quiet HEAD
$ git rev-parse --abbrev-ref HEAD
$ git config --get branch.master.remote
$ git remote get-url origin
! git fetch
$ git describe --tags --match=* --abbrev=0
$ git symbolic-ref HEAD
$ git for-each-ref --format="%(upstream:short)" refs/heads/master
! git log --pretty=format:"* %s (%h)"
�🚀 Let's release git-flow-test (0.2.0...0.2.1)
Empty changelog
! npm version 0.2.1 --no-git-tag-version
$ git status --short --untracked-files=no
Empty changeset
! git add . --update
! git commit --message Release 0.2.1
! git tag --annotate --message Release 0.2.1 0.2.1
$ git symbolic-ref HEAD  [cached]
$ git for-each-ref --format="%(upstream:short)" refs/heads/master  [cached]
! git push --follow-tags
�🏁 Done (in 2s.)

release-it支持更多的自動化操做,包括:發佈至npm、更新github release,或是gitlab相關的支持都有,這裏流程只關注git倉庫相關的就不細說了。

自定義

討論的方向依舊是那幾樣:

  • 是否支持自定義changlog格式?
  • 是否支持跳過特定流程?
  • 是否支持自定義版本?

release-it支持內容不像standard-version文檔及配置分佈在各個項目上,在其項目的release-it.json文件中已包含所有配置內容。

自定義changelog

release-it 默認產出changelog方法是:git log --pretty=format:\"* %s (%h)\" ${from}...${to},能夠在release-it.json文件第4行中看到。而須要按 angular 提交內容格式產出changelog則須要配置release-it/conventional-changelog插件進行設置。具體設置以下:

# .release-it.json
{
    "plugins": {
      "@release-it/conventional-changelog": {
        "infile": "CHANGELOG.md",
        "preset": {
          "name": "conventionalcommits",
          "header":"# 📋 更新歷史 \n\n",
          "types": [
              {"type": "feat", "section": "✨ Features | 新功能"},
              {"type": "fix", "section": "🐛 Bug Fixes | Bug 修復"},
              {"type": "perf", "section":"⚡ Performance Improvements | 性能優化"},
              {"type": "revert", "section":"⏪ Reverts | 回退"},
              {"type": "chore", "section":"📦 Chores | 其餘更新"},
              {"type": "docs", "section":"📝 Documentation | 文檔"},
              {"type": "style", "section":"💄 Styles | 風格", "hidden": true},
              {"type": "refactor", "section":"♻ Code Refactoring | 代碼重構"},
              {"type": "test", "section":"✅ Tests | 測試"},
              {"type": "build", "section":"👷‍ Build System | 構建"},
              {"type": "ci", "section":"🔧 Continuous Integration | CI 配置"}
          ],
          "commitUrlFormat":"https://github.com/lpreterite/datagent/commit/{{hash}}"
        }
      }
    }
}

值得注意的是release-it/conventional-changelog也是用conventional-changelog做爲changelog產出核心。最終配置的格式仍是和 conventional-changelog 同樣。

這裏不知道爲什麼header沒有生效。
跳過特定流程

配置整體分爲4個部分:git、npm、github、gitlab。默認開啓git和npm環節功能。要跳過特定流程只須要在配置加上就能夠了,好比下面配置將不執行npm環節的處理:

# .release-it.json
{
    "npm":{
        "publish":false
    }
}

在命令行傳入能夠這樣使用:

$ npx release-it --no-npm.publish

某些配置是布爾值的,能夠加上no-前綴將其值設置爲false

git環節部分還可細分爲:

  • 提交變更 commit
  • 建立標籤 tag
  • 推送至遠端 push

如不須要推送至遠端的行爲能夠在配置增長下面的內容:

# .release-it.json
{
    "git":{
        "push":false
    }
}

或是在執行命令加上

$ npx release-it --no-git.push

具體細節建議查看 .release-it.json 配置文件,或是細讀官方指南

自定義提交內容

這個功能對於CI/CD工具來講是比較重要的一環就單獨拿出來講了,好比我使用的CI/CD工具 drone.io ,把[CI SKIP]寫在提交內容就能讓它避免在自動處理管道內造成循環提交的問題。

在 release-it 中能夠這樣配置:

# .release-it.json
{
    "git":{
        "commitMessage": "ci: 更新版本至 ${version} | [CI SKIP]"
    }
}

在執行命令中能夠這樣寫:

$ npx release-it --ci --git.commitMessage="ci: 更新版本至 ${version} | [CI SKIP]"
指定語義化版本

與standard-version不一樣,release-it 設計更貼近npm version命令,使用起來比較容易理解。好比發佈重大更新:

$ npx release-it major --ci

# 版本號從 0.2.0 變爲 1.0.0

預發佈部分因爲整合了好幾個功能在一個配置,這裏須要特別強調一下:

# 整合起來的命令
$ npx release-it major --preRelease=beta

# 實際執行了三步
# 1.版本號從 0.2.0 更新至 1.0.0-beta.0
# 2.npm發佈版本會打上beta標籤,能夠經過 npm i xxxx@beta 安裝
# 3.github release會打上pre-release標識

因此像我這種不須要整合功能的,須要拆開來使用

# 只響應package.json中的版本號
$ npx release-it major --preReleaseId=beta

# 設置npm發版時的標識爲beta
$ npx release-it major --npm.tag=beta

# 設置github release爲預發佈
$ npx release-it major --github.preRelease

細節能夠閱讀 pre-releases 部分的指南。

流程鉤子

這個環節設計和standard-version差很少,細節建議直接看官方文檔就好了。

結尾

在學習使用的流暢度(上手過程)來看,相對 standard-version 我可能更偏向於使用 release-it。release-it 比較年輕更有活力,定位問題我以爲仍是能簡單從源碼中找到的。調研事後,咱們團隊接下來的自定義處理將使用 release-it 進行後續工做。以後還須要對接到 tower與飛書實現任務更新及消息通知。

但願這篇文章能對你起到幫助。

相關文章
相關標籤/搜索