天天看點

前端自動化部署的深度實踐工作流番外結語

更新日志自動生成

之前我都是手動修改

CHANGELOG.md

,用來記錄更新日志,感覺操作起來有點心累,也不是很規範。好在已有前人種樹,于是我就考慮利用

conventional-changelog-cli

自動生成和更新

CHANGELOG.md

,真的好用!

什麼是conventional-changelog

Generate a changelog from git metadata

根據

git

中繼資料生成更新日志,而

conventional-changelog-cli

則是相關的指令行工具。

安裝conventional-changelog-cli

npm install -g conventional-changelog-cli
           

複制

初始化生成CHANGELOG.md

cd my-project
conventional-changelog -p angular -i CHANGELOG.md -s
           

複制

以上指令是基于最後一次的

Feature

,

Fix

,

Performance Improvement or Breaking Changes

等類型的

commit

記錄生成或更新

CHANGELOG.md

。如果你希望根據之前所有的

commit

記錄生成完整的

CHANGELOG.md

,那麼可以試試下面這條指令:

conventional-changelog -p angular -i CHANGELOG.md -s -r 0
           

複制

工作流

代碼添加到暫存區

這一步沒有什麼特殊,日常撸代碼,然後将工作區的内容添加到暫存區。

git add .
           

複制

規範commit message

一個規範的commit message一般分為三個部分Header,Body 和 Footer。Header包含type, scope, subject等部分,分别用于描述commit類型,影響範圍,commit簡述。Body則是較長的描述,可以分多行寫。Footer主要用于描述不相容改動(Breaking Change)或者關閉issue(Closes #issue)。

格式如下:

<type>(<scope>): <subject>

<body>

<footer>
           

複制

舉個栗子:

feat(支援自動部署): 結合conventional-changelog,配合部署腳本完成部署任務

conventional-changelog是一個很好的工具,用于自動生成changelog,再配上自定義的部署腳本,整個部署流程就顯得更規範了

Breaking Change: 比較大的更新
Closes #315
           

複制

其中,

Header

是必需的,

Body

Footer

可以省略。

大緻了解規範後,就可以上工具了,這裡我們用到的是

commitizen

npm install -g commitizen
           

複制

接着在項目根目錄運作以下指令:

commitizen init cz-conventional-changelog --save --save-exact
           

複制

運作成功後,

package.json

會新增如下内容:

"devDependencies": {
  "cz-conventional-changelog": "^3.1.0"
},
"config": {
  "commitizen": {
    "path": "./node_modules/cz-conventional-changelog"
  }
}
           

複制

git commit

這一步用

git cz替代

cz

就是指

commitizen

,通過互動式指令行完成

commit

操作。

PS D:\robin\frontend\spa-blog-frontend> git cz
[email protected], [email protected]

? Select the type of change that you're committing: feat:     A new feature
? What is the scope of this change (e.g. component or file name): (press enter to skip) 支援自動部署
? Write a short, imperative tense description of the change (max 86 chars):
 (37) 結合conventional-changelog,配合部署腳本完成部署任務
? Provide a longer description of the change: (press enter to skip)

? Are there any breaking changes? No
? Does this change affect any open issues? No
[master ee41f35] feat(支援自動部署): 結合conventional-changelog,配合部署腳本完成部署任務
 3 files changed, 15 insertions(+), 3 deletions(-)
           

複制

處理版本号,更新CHANGELOG

接着我們要更新

npm

包的版本号,結合

npm version

conventional-changelog

使用,可以同時更新

CHANGELOG.md

好的,我們先準備好腳本:

"scripts": {
    "start": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "deploy": "node deploy",
    "version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md",
    "postversion": "npm run deploy"
}
           

複制

根據實際版本情況選擇更新

patch/minor/major

版本。假設我們更新的是

minor

版本号,那麼操作指令如下:

npm version minor -m '特性版本更新'
           

複制

執行這條指令會更新

package.json

中的

version

字段,

同時會執行

conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md

,更新

CHANGELOG.md

執行完這條指令後,可以看到

CHANGELOG.md

已經被修改了。

前端自動化部署的深度實踐工作流番外結語

CHANGELOG自動更新

npm鈎子觸發部署腳本

通過

postversion

鈎子觸發部署腳本

node deploy

,開始進行部署工作。

deploy.js

檔案内容如下:

const { execFile } = require('child_process');

const version = process.env.npm_package_version;

execFile('deploy.sh', [version], { shell: true }, (err, stdout, stderr) => {
    if (err) {
        throw err;
    }
    console.log(stdout);
});
           

複制

這裡利用了

nodejs

child_process

子產品執行子程序,調用了

execFile

執行了

deploy.sh

,并将

npm

包版本号作為參數傳遞給了

deploy.sh

deploy.sh

檔案内容如下:

#!/bin/bash
npm run build
htmldir="/usr/share/nginx/html"
uploadbasedir="${htmldir}/upgrade_blog_vue_ts"
appenddir=$1
uploaddir="${uploadbasedir}/${appenddir}"
projectdir="/usr/share/nginx/html/blog_vue_ts"
scp -r ./dist/. txcloud:${uploaddir}
ssh txcloud > /dev/null 2>&1 << eeooff
ln -snf ${uploaddir} ${projectdir}
exit
eeooff
echo done
           

複制

以上指令主要做的事情是:

  • npm run build

    執行建構任務
  • 将建構得到的

    dist

    檔案夾中的内容通過

    scp

    傳輸到伺服器,通過版本号區分各個版本。
  • nginx

    配置的是監聽

    80

    端口,指向

    /usr/share/nginx/html/blog_vue_ts

    ,而我通過軟連接配接将

    blog_vue_ts

    再次指向到

    upgrade_blog_vue_ts

    下的版本目錄,如

    upgrade_blog_vue_ts/0.5.4

    。每次釋出版本時,以上腳本會修改軟連接配接,指向目标版本,如

    upgrade_blog_vue_ts/0.6.0

    ,完成版本過渡。

我這裡使用了軟連接配接改進了之前的部署腳本,既可以在伺服器保留各個曆史版本檔案夾,也不用考慮處理

index.html

與靜态資源分離的問題。

lrwxrwxrwx 1 root root   47 Feb  3 21:35 blog_vue_ts -> /usr/share/nginx/html/upgrade_blog_vue_ts/0.6.0
           

複制

前端自動化部署的深度實踐工作流番外結語

linux伺服器項目版本檔案夾

如果要回退版本,也可以通過修改軟連接配接的方式實作,還是比較友善的。

推送到remote

最後别忘了把代碼

push

到遠端倉庫。

git push
           

複制

更新日志

changelog

檢視也變得很友善了,修改了什麼内容一目了然,并且可以直接跳轉到

commit

曆史,

issue

等。

前端自動化部署的深度實踐工作流番外結語

github上的changelog

番外

可以看到,我是通過

deploy.js

調用了

deploy.sh

。之前本想直接在

npm scripts

中調用

deploy.sh

并傳入版本号參數的,但是試了幾種寫法都不行,這裡也記錄一下。

"deploy": "deploy.sh npm_package_version"
           

複制

"deploy": "deploy.sh $npm_package_version"
           

複制

看起來在

npm scripts

中調用

sh

腳本時,隻能寫字面量參數,傳變量作為參數好像行不通。

下面這種字面量參數寫法是可以的,但是就有點呆呆的感覺了,而且與自動化部署的主題不符。

"deploy": "deploy.sh 0.6.0"
           

複制

是以我目前還是選擇通過

deploy.js

作為中間者來調用

deploy.sh

的。

結語

需要承認的是,我以上所述的部署流程是以我的個人項目為例說明,可能不是很規範,但是也算是通過自己的了解和摸索,完整地搞了一套部署流程,并沒有借用

jenkins

等工具。有了這段自動化部署的學習經曆後,相信學習和使用

jenkins

會變得更輕松。接下來我會繼續優化和規範自己的部署流程,

jenkins

理所當然會出現在我的計劃表中。