背景#
因为仓库迁移,流水线权限问题,导致流水线所用仓库无法直接在页面提 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>Update and Push Successful!</h1>
<h2>Most Recent Commits:</h2>
<pre>${recentCommits.stdout}</pre>
`)
} catch(error) {
console.error(`Failed to perform update operations: ${error}`)
res.status(500).send(`<pre>Error: ${error.stderr || error.stack}</pre>`)
}
})
function executeGitCommand(command) {
const fullCommand = `git ${command}`
console.log(`Executing command: ${fullCommand} in ${directory}`)
return cp.exec(fullCommand, {cwd: directory})
}
在这个路由中,将 git 的操作按顺序执行,并在每个命令中都进行了异常捕获以确保程序的健壮性。
启动 Express 服务#
最后一步是启动应用监听端口。
const PORT = process.env.PORT || 30035;
app.listen(PORT, () =>
console.log(`Server is running at http://localhost:${PORT}/`)
);
使用 PM2 进行守护进程管理#
为了让应用程序能够在后台稳定运行,使用 PM2 来管理。这样,就不用必须保持终端的开启
pm2 start index.js --name "git-auto-pilot"
现在,即使关闭终端或者重启机器,这个服务也会被 PM2 自动复活。
总结#
用 Node 和 PM2 的组合,可以写很多简单、实用的自动化脚本。目前这个脚本还无法处理遇到冲突的情况,但是足以解决我大部分问题,节省了很多去手动合并代码的问题。