共计 3485 个字符,预计需要花费 9 分钟才能阅读完成。
前言
- 最早期方式: 前端写好代码之后本地构建, 通过服务器
xftp
或ftp
把文件上传到服务器进行更新- 使用 Git 后: 服务器通过
git clone
的项目, 在项目的根目录执行git pull origin [branch]
拉去仓库中最新的代码- 自动化部署: 通过配置
WebHook
及服务器后: 项目打包完成提交到代码库中, 服务器自动拉去 git 仓库中最新的代码
底层实现原理:
- 在 github 配置 webhook 的地方填写服务端的 url, 每次 push 代码到 github 上, github 都会向 webhook 中的 url 发送一条请求
- 服务端接收到请求后, 经过验证后执行本地的 bash 脚本, 脚本中编写从 github 拉去代码的命令。
- 使用环境:
Centos7.*
,Node
,Git
- 代码库平台:
Gitee
/Github
- Tips: 不同的操作环境可以进行不同的配置, 都可以实现
流程说明
- 一. 配置 github 项目中的 WebHook
- 二. 配置服务器, 增加 Node 项目, 运行项目
一. 配置 WebHook
1.1 进入到代码库配置 webhook 界面
这里以 github 为例
登录 github -> 进入到 repository 中 -> 找到设置 -> 进入 webhook
- 这是已经配置好的 webhook
- 点击新增 webhook
- 现在 github 中的 webhook 已经配置成功了, 接下来配置服务器
二. 配置服务器
配置环境
- 下载 git, Node 环境
- 创建一个 Node 项目, 最好保存到代码库中
- 可以参考 web-hook, 这是一个服务端 Node 项目 demo
使用 Node 编写自动化部署脚本
参考 web-hook
1. 创建 server.js 监听一个端口
server.js
const http = require('http') // http 模块
const {spawn} = require('child_process') // 子进程, 用来执行脚本
const {PORT, SECRET} = require('./src/config') // 配置文件
const {sign} = require('./src/utils') // 工具文件
const {resultString} = require('./src/resModel') // 服务端返回 JSON
const server = http.createServer((req, res) => {
// 打印进来的请求
console.log(`--- ${req.method} --- ${req.url} ---`)
// 设置 header 为 json 格式
res.setHeader('Content-Type', 'application/json')
if (req.method === 'POST' && req.url === '/webhook') {
// post /webhook 都为 github 发来的请求
console.log('--- 命中 webhook ---')
// 获取 body
let buffers = []
req.on('data', buffer => {buffers.push(buffer)
})
req.on('end', () => {let body = Buffer.concat(buffers)
// 获取 header 中 event 的字段, github 为 push, gitee 为 Push Hook
let event = req.headers['x-github-event'] || req.headers['x-gitee-event']
console.log(`--- Event 名字: ${event} ---`)
if (req.headers['user-agent'] === 'git-oschina-hook') {
// gitee
console.log('--- Gitee 平台 ---')
// SECRET 是在 config.js 中配置了
if (req.headers['x-gitee-token'] === SECRET) {if (event === 'Push Hook') {console.log('--- push 任务命中 ---')
let payload = JSON.parse(body)
console.log(`--- 任务名称: ${payload.repository.name}, 路径: ${payload.repository.path} ---`
)
// 开启子进程执行对应的脚本
// payload.repository.path 是 gitee/github 传来的 repo 的路径
// 通过 path 的值执行 sh 目录下对应的脚本
// 比如项目名字叫 web_hook path 的值就是 web_hook
// 执行的脚本就是./sh/web_hook.sh
let child = spawn('sh', [`./sh/${payload.repository.path}.sh`])
// 接收子进程传来的数据
let buffers = []
child.stdout.on('data', buffer => {console.log(`--- 接受 data ${buffer.toString()} ---`)
buffers.push(buffer)
})
child.stdout.on('end', () => {let log = Buffer.concat(buffers)
console.log(log.toString())
console.log('自动化拉取完毕')
})
}
// 返回的 json, 配置在./src/resModel 中
res.end(resultString('success', 0))
} else {
// 其他的请求返回不允许
return res.end(resultString('Not Allowed', 1))
}
} else {
// github
// 基本和上面的 gitee 一样, 多一个校验身份的步骤
console.log('--- Github 平台 ---')
let signature = req.headers['x-hub-signature']
// sign 方法配置在 utils.js 中
if (signature !== sign(body, SECRET)) {return res.end(resultString('Not Allowed', 1))
}
if (event === 'push') {console.log('--- push 任务命中 ---')
let payload = JSON.parse(body)
console.log(payload.repository.name)
let child = spawn('sh', [`./sh/${payload.repository.name}.sh`])
let buffers = []
child.stdout.on('data', buffer => {buffers.push(buffer)
})
child.stdout.on('end', () => {let log = Buffer.concat(buffers)
console.log(log.toString())
console.log('自动化拉取完毕')
})
}
res.end(resultString('success', 0))
}
})
}
res.end(resultString('Not Found', 1))
})
// 监听端口, PORT 配置在 config.js 中
server.listen(PORT, () => {console.log(`web-hook listen on http://localhost:${PORT}`)
})
Tips: 接收 github 发送来的 post 参数: Webhooks | GitHub Developer Guide
建议看 gitee 平台的说明(中文的, 参数差不多) Gitee
2. 编写 sh 文件
./sh/*.sh
#!/bin/bash
WORK_PATH="/home/wwwroot/tools/vue-back"
echo "------ 进入项目目录 ------"
cd $WORK_PATH
echo "------ 已进项目目录 ------"
echo "------ 开始清理代码 防止冲突 ------"
git reset --hard origin/master
git clean -f
echo "------ 清理代码完毕 ------"
echo "------ 拉取 master 分支代码 ------"
git pull origin master
echo "------ vue-back 持续集成完毕 ------"
- 部署到服务器
- 把写好的这个 Node 项目部署到服务器
- 阿里云服务器需要手动配置开放的自定义端口号
- Node 项目建议使用 pm2
自动部署效果图:
正文完
发表至: javascript
2019-09-03