背景#
因為倉庫遷移,流水線權限問題,導致流水線所用倉庫無法直接在頁面提 PR。 所以,合作方的同學修改涉及到 SaaS 後端代碼需要發布,每次都要前端在本地進行一次代碼合併,非常的繁瑣和低效,因為目前每次拉取的倉庫和分支是固定的,所以想到用 Node 寫一個腳本,通過調用接口實現代碼的自動拉取。
技術棧選擇#
由於目前的需求非常簡單,就是簡單的同步,實際就是以下命令行的運行:
git checkout dev
git pull --no-rebase
git pull bkop dev_databus --no-rebase
git push
基於此,主要採取了以下幾個關鍵技術:- Node.js: 作為服務端運行的 JavaScript 運行時環境。
- Express: 一個快速、無開箱即用的 Web 應用框架,為我們的 API 服務提供支撐。
- Child Process: 用於執行 shell 命令。
- PM2: 一個具有內建負載均衡功能的 Node 應用的進程管理器。
解決方案概述#
目錄結構與依賴安裝#
首先創建項目目錄,並在其中初始化一個新的 npm 項目,然後安裝所需依賴項。
mkdir git-auto-pilot && cd $_
npm init -y
npm install express child-process-promise
這裡使用了 child-process-promise
庫來替代原生的 exec
函數,以提高錯誤處理的優雅性,並且支持 Promise 語法。
創建自動化腳本#
接下來是實現自動化邏輯的核心部分 —— 編寫一個簡單的 Express 應用程序,並通過 HTTP 接口觸發一系列 Git 操作。
主要功能模塊#
設置 Express 應用#
引入所需的模塊開始,並設置基本的 Express 應用。
// 文件路徑: index.js
const express = require('express')
const cp = require('child-process-promise')
const path = require('path')
const app = express()
const directory = 'xxx' // 文件路徑
更新操作的 GET 路由#
定義 /update
路由來執行所有的 Git 操作。
app.get('/update', async (req, res) => {
try {
await executeGitCommand('checkout dev')
await executeGitCommand('pull --no-rebase')
await executeGitCommand('pull bkop dev_databus --no-rebase')
await executeGitCommand('push')
const recentCommits = await executeGitCommand('log -n 5 --pretty=format:"%h %s"')
res.send(`
<h1>更新和推送成功!</h1>
<h2>最近的提交:</h2>
<pre>${recentCommits.stdout}</pre>
`)
} catch(error) {
console.error(`執行更新操作失敗: ${error}`)
res.status(500).send(`<pre>錯誤: ${error.stderr || error.stack}</pre>`)
}
})
function executeGitCommand(command) {
const fullCommand = `git ${command}`
console.log(`執行命令: ${fullCommand} 在 ${directory}`)
return cp.exec(fullCommand, {cwd: directory})
}
在這個路由中,將 git 的操作按順序執行,並在每個命令中都進行了異常捕獲以確保程序的健壯性。
啟動 Express 服務#
最後一步是啟動應用監聽端口。
const PORT = process.env.PORT || 30035;
app.listen(PORT, () =>
console.log(`服務正在運行於 http://localhost:${PORT}/`)
);
使用 PM2 進行守護進程管理#
為了讓應用程序能夠在後台穩定運行,使用 PM2 來管理。這樣,就不用必須保持終端的開啟。
pm2 start index.js --name "git-auto-pilot"
現在,即使關閉終端或者重啟機器,這個服務也會被 PM2 自動復活。
總結#
用 Node 和 PM2 的組合,可以寫很多簡單、實用的自動化腳本。目前這個腳本還無法處理遇到衝突的情況,但是足以解決我大部分問題,節省了很多去手動合併代碼的問題。