npm發包工做流分享 | 8月更文挑戰

去往->本人博客原文git

設計思路

在公司手動 npm publish 以後工做比較麻煩,涉及到在不一樣 npm 倉庫發包,整理更新日誌,在羣裏推送更新通知等等。由於本人很懶,因此打算寫一個小工具來幫我處理上述事務。web

這些事務包含 demonpm

自動升級版本號

這裏原本設計的是直接執行自動遞增小版本,但感受不夠智能,若是用戶升級的是大版本,又得本身手動改,因此這裏支持用戶本身傳版本號,如:json

npm run release [版本號]
複製代碼

計算完新版本號後,重置 package.json,直接打 git tag,以後咱們在生成 changelog 時候會用到。promise

發佈到多個倉庫

沒有 scope 就很簡單,直接運行命令npm publish --registry=xxxx就搞定了。但若是須要在多個 npm 倉庫的某個 scope 下發布就比較複雜。markdown

npm scope

一個 registry 能夠有多個 scope,但 一個 scope 只能對應一個 registry,也就是說若是有一個包,名爲:@xx/yy要發佈到多個倉庫,就要不斷重置 scope。因此如何把這個部分自動化。數據結構

設計數據結構以下:併發

publish: {
    dir: 'dist',
    registries: [
      { url: 'http://localhost:4873/' },
      { url: 'http://npm.yonghui.cn/repository/yh-npm/', scope: '@yh' },
    ],
  }
複製代碼

這個階段的上傳工做包含:根據 scope 修改 package.json、上傳到不一樣的 npm 倉庫、統計上傳結果、收集出錯數據。原本覺得都寫成 promise 以後,直接併發就 ok 了。然而這裏有個陷阱是,由於修改的 package.json 是一份數據,promise 在實例化階段是同步執行的,因此 package.json 邊讀邊寫就出現了錯誤。工具

後來寫法改爲 generator 的方式,才得以解決這個問題,示例以下:oop

const p1 = () =>
    new Promise((resolve, reject) => {
        setTimeout(() => {
            fs.writeFileSync('./log.txt', 'aaa')
            resolve(1)
        }, 2000)
    })

const p2 = () =>
    new Promise((resolve, reject) => {
        setTimeout(() => {
            fs.writeFileSync('./log.txt', 'bbbbbbb')
            resolve(2)
        }, 1000)
    })
const ps = [p1, p2]

function* gent() {
    const f1 = yield p1()
    const f2 = yield p2()
    console.log(f1, f2)
}

function run(gen) {
    const g = gen()
    function next(data) {
        const res = g.next(data)
        if (res.done) return res.value
        res.value.then((data) => {
            next(data)
        })
    }
    next()
}

run(gent)
複製代碼

獲取 git 提交信息

git log

直接運行git log會打印不少用不到的信息,咱們想要生成 changelog 只需關注 commit 的標題(commit 的內容),因此命令行

git log --pretty=format:%s
複製代碼

format 後跟所需內容的佔位符(參考個性化你的 Git Log 的輸出格式),%s 表明 commit 標題,%b 表明 commit 內容。

如何將 git log 與版本號掛鉤?

上面的命令能夠獲取到全部的提交記錄,但這些提交與包的版本號並沒有關聯,以下:

$ git log --pretty=format:%s
fix: 修復細節 1. tableAction和tableStatus中status類型擴展number類型 2. patchConstant中對tslint的支持
feat: Table組件支持tableAction
feat: table組件添加tablestatus組件
feat: 添加校驗
feat: 添加輸入校驗
複製代碼

因此如何獲取最新版本號的提交信息呢?

git tag

獲取兩個 tag 之間的 git log(即每一個 tag 更新的內容參考文檔

git log [oldTag]..[newTag]
// 好比
git log 0.1.5..0.1.6
複製代碼

加上格式,這裏只輸出 commit 標題和提交信息,以下

git log 0.1.5..0.1.6 --pretty=format:%s__%ai
複製代碼

最終打印

fix:修復細節 1. tableAction和tableStatus中status類型擴展number類型 2. patchConstant中對tslint的支持__2021-06-24 15:08:32 +0800
feat: Table組件支持tableAction__2021-06-24 14:23:55 +0800
feat: table組件添加tablestatus組件__2021-06-24 14:11:27 +0800
複製代碼

更新的版本號,時間,和內容都有了,那咱們就能夠將其收集處理成文檔

生成 changelog

拿到信息怎麼處理成 md 格式的文本就不細說了。

這裏寫一個本身的例子,咱們根據 commit message 中相關的 flag,對 commit message 進行分類,這裏參考conventional commits的規範,只篩選 commit type 爲 feat、fix 這兩種,其他的都劃分到 other 中,由於包使用者最關注的只有新的特性和 bug fix。(同時,要攜帶版本號和發佈日期。)

這個過程就是處理文本的過程,最後生成的文本格式以下:

## FIX BUGS
==================

  * 修復細節  tableAction和tableStatus中status類型擴展number類型

## FEATURE
==================

  * Table組件支持tableAction
  * table組件添加tablestatus組件
複製代碼

插入 readme

能夠把上面的內容生成的 changelog 放在一個新頁中,或是插入到包的主頁中都 ok,這裏考慮到若是單拎出來一頁,這個文件仍是放到 git 中的,然而 git 有多是私人倉庫,因此有可能對包使用者是不可見的。因此說最終的方案仍是插入到 readme 中。

這部分的實現思路就是讀字符串,找到插入的 flag,插入到指定位置。

觸發 webhook

接着就是發送 webhook 了,這裏是用的飛書機器人,按照文檔發 https 請求就 ok 了!效果以下:

demo

相關文章
相關標籤/搜索