這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 本文的起因是有在代碼倉庫發包後,同事問我“為什麼package.json 里的版本還是原來的,有沒有更新?”,這個時候我意識到,我們完全沒有必要在每次發佈的時候還特意去關註這個倉庫的版本號,只要在發佈打tag的時候同步一下即可,於是有了本 ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
本文的起因是有在代碼倉庫發包後,同事問我“為什麼package.json 里的版本還是原來的,有沒有更新?”,這個時候我意識到,我們完全沒有必要在每次發佈的時候還特意去關註這個倉庫的版本號,只要在發佈打tag的時候同步一下即可,於是有了本文的實踐。
node.js 部分,我們得有一個更改倉庫代碼的腳本留給ci執行
我們首先需要在工程目錄中的 ./script/..
目錄下增加一個 update-version.js
腳本
//update-version.js const path = require('path'); const fs = require('fs'); const newVersion = process.argv[2].replace(/^v/, '');; // 獲取命令行參數中的新版本號,並過濾v字頭 if (!newVersion) { console.log('請傳入新版本號,版本號遵循semver規範 .eg: 1.0.0, 1.0.1, 1.1.0'); process.exit(1); } // 獲取當前命令行上下文路徑 const currentDirectory = process.cwd(); // 獲取 package.json 文件中的版本號 const packageJsonPath = path.join(currentDirectory, 'package.json'); const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8'); const packageJson = JSON.parse(packageJsonContent); const currentVersion = packageJson.version; // 更新 package.json 文件中的版本號 packageJson.version = newVersion; fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); console.log(`版本號已從 ${currentVersion} 更新為 ${newVersion}`);
接下來在 package.json script 配置後可以直接使用 npm run version <version>
中觸發變更版本號腳本。當然這個前提是想要讓這個腳本保留給開發者命令行使用。
{ "name": "version workflow", "version": "1.0.0", "description": "version update demo", "main": "index.js", "scripts": { //... "version": "node ./scripts/update-version.js" }, //... }
CI :如何讓發佈包的行為直接和代碼倉庫中的版本號同步?
接下來算重頭戲,如何讓發佈包的行為直接和代碼倉庫中的版本號同步?這裡我們使用的是github 提供的github action,具體操作和語法可以查看一下官方文檔,本文就不過多展開。
我們需要在倉庫根目錄增加如下路徑的文件 .github/workflows/update-action.yml
name: Update Package Version on: release: types: [released] jobs: update: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Update package.json run: | node ./scripts/update-version.js ${{ github.event.release.tag_name }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Commit changes run: | git config user.name "Your github name" git config user.email "your github email" git add . git commit -m "Update version to ${{ github.event.release.tag_name }} for release ${{ github.ref }}" - name: Push changes uses: ad-m/github-push-action@master with: github_token: ${{ secrets.GITHUB_TOKEN }}
我們在 release
hook 中的 released
狀態下增加了一個 update job。 它會做下麵幾件事情(在腳本步驟中有)
- 【Checkout code】 切出新的代碼分支;
- 【 Update package.json】在新分支執行 update-version.js 傳入
tag_name
更新我們的工程版本號; - 【Commit changes】以你定製的 git config user 信息創建一個新提交;
- 【Push changes】推送變更回到主幹;
ps:正確來說應該在發佈執行動作前prereleased
執行我們的 job 但是沒用這個的原因如下:
Note: The
prereleased
type will not trigger for pre-releases published from draft releases, but thepublished
type will trigger. If you want a workflow to run when stable and pre-releases publish, subscribe topublished
instead ofreleased
andprereleased
.
當這個腳本推送後,執行發佈後自動更新版本,不用在關註這個版本修改問題。 你會得到下麵的效果。
在你的倉庫發佈界面填寫正確tag後發佈
觸發update job 更改完成
你可能遇到最多的坑
- action 執行失敗
Process completed with exit code 129." Node.js 12 actions are deprecated. Please update the following actions to use Node.js 16: actions/checkout@v2. For more information, see https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/.
這是由於預設action job 執行環境的nodejs 版本與actions 包中執行腳本不匹配導致,所以一定要使用 checkout@v3 版本 actions/checkout@v3
- 各種不熟悉 action 語法取值導致的問題
可以優化的地方
我們前面提交的這個流程發佈還是有個問題,你永遠有個更超前的 commit hash 在你發佈的 tag 之後
所以這個action 還有需要繼續優化的地方,那就是同步更新tag hash
name: Update Package Version on: release: types: [released] jobs: update: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Update package.json run: | node ./scripts/update-version.js ${{ github.event.release.tag_name }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Commit changes run: | git config user.name "Your github name" git config user.email "your github email" git add . git commit -m "Update version to ${{ github.event.release.tag_name }} for release ${{ github.ref }}" git_hash=$(git rev-parse --short HEAD) - name: Push changes uses: ad-m/github-push-action@master with: github_token: ${{ secrets.GITHUB_TOKEN }} - name: Tag Push changes run: | git tag -f ${{ github.event.release.tag_name }} $git_hash git push --force origin ${{ github.event.release.tag_name }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
這裡相比之前的版本增加了 Tag Push changes
這個步驟,在最後獲取這個版本更新產生的 $git_hash
強制更新到發佈的 tag 上。
我們看看效果
最後我們看版本發佈管理中的 tag hash
搞定!
可以再優化的地方
現在我們還有個問題,就是在執行 Commit changes
這個步驟時每次 git config user.name "Your github name" git config user.email "your github email"
這裡是寫死的,我們可以根據 GitHub Actions 中有一些預設的環境變數可以讀取到當前用戶的賬號和郵箱信息。通過 ${{ env.GITHUB_ACTOR }}
獲取到當前執行的 Actions 的用戶賬號,通過 ${{ env.GITHUB_ACTOR }}@users.noreply.github.com
獲取到當前執行的 Actions 的用戶郵箱(該郵箱為 noreply 郵箱,用於 GitHub 的通知,無法發送郵件)。註意,該郵箱不一定是用戶本身的真實郵箱,可能是 GitHub 預設的郵箱。
如果需要獲取當前 GitHub 賬號的真實郵箱地址,可以通過 GitHub REST API 進行查詢,具體可以參考官方文檔:
這樣我們就需要在Commit Changes
之前再加一個Set Git user
步驟
- name: Set Git user env: GITHUB_ACTOR: ${{ github.actor }} GITHUB_EMAIL: ${{ github.actor }}@users.noreply.github.com run: | git config --global user.name "${{ env.GITHUB_ACTOR }}" git config --global user.email "${{ env.GITHUB_EMAIL }}"這樣我們最終的 Github action 腳本長這樣
name: Update Package Version on: release: types: [released] jobs: update: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Update package.json run: | node ./scripts/update-version.js ${{ github.event.release.tag_name }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Set Git user env: GITHUB_ACTOR: ${{ github.actor }} GITHUB_EMAIL: ${{ github.actor }}@users.noreply.github.com run: | git config --global user.name "${{ env.GITHUB_ACTOR }}" git config --global user.email "${{ env.GITHUB_EMAIL }}" - name: Commit changes run: | git add . git commit -m "Update version to ${{ github.event.release.tag_name }} for release ${{ github.ref }}" git_hash=$(git rev-parse --short HEAD) - name: Push changes uses: ad-m/github-push-action@master with: github_token: ${{ secrets.GITHUB_TOKEN }} - name: Tag Push changes run: | git tag -f ${{ github.event.release.tag_name }} $git_hash git push --force origin ${{ github.event.release.tag_name }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}