原文node
如何將NPM發佈包的過程自動化,特別是當處理多個分支時,是一個大多數人都會遇到的問題,更受關注的是在CI系統中作到這些。git
當我用手動的方式作這些事情時,狀況老是很糟糕,所以我一直都是使用一種高度自動化的模式來搞定它。利用CI自動化發佈或從終端中手動發佈對這套模式來講都不是問題。shell
我有一段時間沒有手動輸入 npm publish
了,這是一個好事。npm
我對100%的測試覆蓋率有着狂熱的追求。這並不能完美地防範每個問題,但它確實能夠防止我作一些愚蠢的事情,好比說,我覺得我知道本身在幹什麼。json
我首選的測試庫是 tap ,但你可使用任何支持代碼覆蓋的測試庫。若是你使用的測試庫不支持開箱即用的代碼覆蓋測試,你也可使用 nyc 運行任何帶有覆蓋跟蹤的 Node.js 進程。安全
運行 npm i tap -D
來安裝這個測試庫,並將下面的代碼加入到 package.json 文件中:工具
{
"scripts": {
"test": "tap"
},
"tap": {
"check-coverage": true
}
}
複製代碼
npm version
命令會計算下一個版本號是什麼,並修改你的 package.json 文件,甚至使用帶標記的 tag 將其簽入 Git 中。這樣作的好處是,當 Git 工做目錄中有未跟蹤的更改時,它能夠阻止版本自增,並提供一些能夠在版本自增以前或以後執行其餘操做的鉤子腳本。post
在package.json
文件中的scripts
部分,我添加了一個preversion
腳本以便運行個人測試:測試
{
"scripts": {
"preversion": "npm test",
"test": "tap"
},
"tap": {
"check-coverage": true
}
}
複製代碼
如今,在版本自增以前npm會確保代碼能夠經過測試。若是沒有經過測試(或者它的覆蓋率不是100%),當前操做會失敗,而且 version 命令也不能執行。加密
至此,版本自增已經完成了,是時候將它分享出去了。隨着 preversion
的完成,postversion
命令會在版本自增後執行操做。因此,讓咱們勾選它來發布包。
{
"scripts": {
"postversion": "npm publish",
"preversion": "npm test",
"test": "tap"
},
"tap": {
"check-coverage": true
}
}
複製代碼
推送到npm這一步已經完成了,接下來我必須記住將變動推送到git。(有不少次我都忘記了這麼作,所以遇到了問題,一般來講這是一個很差的信號。)
很是感謝npm爲咱們提供了一個 publish
事件的鉤子,咱們能夠像這樣來使用它:
{
"scripts": {
"postpublish": "git push origin --all; git push origin --tags",
"postversion": "npm publish",
"preversion": "npm test",
"test": "tap"
},
"tap": {
"check-coverage": true
}
}
複製代碼
這裏執行了兩個命令。第一個命令將全部的分支推送到遠程,第二個將全部的標籤推送到遠程(包括表明新版本的標籤)。
我偶爾會發現本身在爲尚未準備好發佈的新版本開發一些重要的功能。
我會在功能分支中修改腳本,經過增長一個 --tag
參數到 npm publish
命令中,將該分支放入一個分發標籤中,而不是 latest
標籤。
{
"scripts": {
"postversion": "npm publish --tag=next",
"postpublish": "git push origin --all; git push origin --tags",
"preversion": "npm test",
"test": "tap"
},
"tap": {
"check-coverage": true
}
}
複製代碼
如今我可讓別人運行 npm install my-module@next
來嘗試新的預發佈版本。
另外一方面,我可能但願爲舊的版本修復 bug 或者移植功能。爲了作到這一點,我基於舊的版本建立了一個 git 分支,而後在 package.json
中加入一個 legacy
標籤。
{
"scripts": {
"postversion": "npm publish --tag=legacy",
"postpublish": "git push origin --all; git push origin --tags",
"preversion": "npm test",
"test": "tap"
},
"tap": {
"check-coverage": true
}
}
複製代碼
Git 支持用PGP簽名給 commit
打標籤。要讓npm利用這一點,請進行以下配置:
npm config set sign-git-commit true
npm config set sign-git-tag true
複製代碼
若是你以爲設置 PGP 並將它與 Git 相鏈接太麻煩了,恭喜你,你不是一我的!我是一個老電腦迷,可我也玩不轉它。此外,對於個人密鑰就存在我電腦裏的一個文本文件中,我老是憂心忡忡。而若是他們是被加密的,那我就必須一直輸入密碼,這太麻煩了。
我是Krypton的忠實粉絲。 它將你的 PGP 和 SSH 私鑰存儲在移動設備的安全存儲庫中,而後推送通知以容許它使用這些密鑰執行操做。設置很是簡單,而且很是易於使用,併爲你提供一個硬件的雙重驗證。
固然,我使用 npm version
命令來完成全部的發佈工做。修復bug,運行 npm version patch
。新的特性,運行 npm version minor
。重大變動,運行 npm version major
。
若是你使用 Conventional Commits或者相似的工具,你甚至能夠自動檢測這是什麼類型的版本,這留給做者自行練習。
這種使用 npm 腳本實現自動化的方法適用於您將要發佈和提交的任何系統。在你的下一個項目中實踐起來,不要太相信本身的手指 ^_^
你會注意到我在上面的發佈命令中用了 --tag =
。你還能夠經過許多其餘方式配置 npm。能夠設置任何配置值(包括 npm publish
中的 tag
):
--tag=whatever
NPM_CONFIG_TAG=whatever
.npmrc
文件中, 如 tag = whatever
.npmrc
文件中/usr/local/etc/npmrc
(某些系統中是 /usr/etc/npmrc on some systems
)。這些配置是繼承式的,因此列表中位置越高的設置,優先級就越高。
對於 CI/CD 系統, 這意味着你有時能夠設置環境變量來控制 npm 命令的行爲,而無需改變代碼或者添加文件。若是使用文件來控制更方便(舉個例子,將 .npmrc
文件加入 git 中),那也能夠。