本教程 整体开发环境为 nodejs https://nodejs.org/en/
本教程 涉及到的2个项目的部署采用 pm2 http://pm2.keymetrics.io/
本教程 涉及到的2个项目的端口代理采用 nginx nginx news
本教程 涉及到的2个项目的 git代码托管为 码云 码云 – 开源中国
本教程 涉及到的mock项目的自动化部署基于的码云平台的webhook回调, 使用说明在这里 码云平台帮助文档_V1.2
本教程 含有2个项目, 包括:
1. mock服务器 涉及到的知识有:
- REST API服务器 json-serverhttps://github.com/typicode/json-server
- 生成随机数据 mockjsMock.js
- 自动化构建工具 gulphttp://www.gulpjs.com.cn/
2. mock服务自动化部署脚本 涉及到的知识有:
- git代码自动化部署 webhook 码云平台帮助文档_V1.2
- nodejs child_process模块 (用于执行shell命令)
- nodejs web应用框架 expressexpressjs/express
- express 中间件 body-parserexpressjs/body-parser (用于post参数的解析)
本教程 涉及的项目中 依赖库的安装均使用淘宝镜像代替npm
npm install -g cnpm --registry=https://registry.npm.taobao.org
一. mock服务器项目的实现
mock服务器项目整体目录
具体流程为:
1. 初始化一个nodejs项目
npm init
2. 项目的package.json文件如下, 在根目录执行 cnpm install 安装所有依赖库
{
"name": "mock-server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"mock": "gulp mock"
},
"repository": {
"type": "git",
"url": "git@git.oschina.net:xxx/xxx.git"
},
"author": "",
"license": "ISC",
"devDependencies": {
"json-server": "^0.11.2",
"mockjs": "^1.0.1-beta3",
"browser-sync": "^2.18.12",
"gulp": "^3.9.1",
"gulp-nodemon": "^2.2.1"
}
}
3. 在 /mock/ 目录下 创建以下3个文件
db.js 数据源文件
routes.js 接口路由
server.js json-server服务
# db.js
var Mock = require('mockjs')
var Random = Mock.Random
module.exports = {
userInfo: Mock.mock({
'code': 1,
'data': {
'uid': '582028',
'username': 'sufaith',
'phone': '12345678910'
}
})
}
# routes.js
module.exports = {
'/getUserInfo': '/userInfo'
}
# server.js
const jsonServer = require('json-server')
const db = require('./db.js')
const routes = require('./routes.js')
const port = 3000
const server = jsonServer.create()
const router = jsonServer.router(db)
const middlewares = jsonServer.defaults()
const rewriter = jsonServer.rewriter(routes)
server.use(middlewares)
// 将 POST 请求转为 GET
server.use((request, res, next) => {
request.method = 'GET'
next()
})
server.use(rewriter) // 注意:rewriter 的设置一定要在 router 设置之前
server.use(router)
server.listen(port, () => {
console.log('open mock server at localhost:' + port)
})
4.本地修改数据时为了实时查看效果, 使用gulp监听文件数据的更新,自动重启json-server
# gulpfile.js
const path = require('path')
const gulp = require('gulp')
const nodemon = require('gulp-nodemon')
const browserSync = require('browser-sync').create()
const server = path.resolve(__dirname, 'mock')
// browser-sync 配置,配置里启动 nodemon 任务
gulp.task('browser-sync', ['nodemon'], function () {
browserSync.init(null, {
proxy: 'http://localhost:3000', // web端本地测试用,这里的端口和 webpack 的端口一致
port: 3001
})
})
// browser-sync 监听文件
gulp.task('mock', ['browser-sync'], function () {
gulp.watch(['./mock/db.js', './mock/**'], ['bs-delay'])
})
// 延时刷新
gulp.task('bs-delay', function () {
setTimeout(function () {
browserSync.reload()
}, 1000)
})
// 服务器重启
gulp.task('nodemon', function (cb) {
// 设个变量来防止重复重启
var started = false
var stream = nodemon({
script: './mock/server.js',
// 监听文件的后缀
ext: 'js',
env: {
'NODE_ENV': 'development'
},
// 监听的路径
watch: [
server
]
})
stream.on('start', function () {
if (!started) {
cb()
started = true
}
}).on('crash', function () {
console.error('application has crashed!\n')
stream.emit('restart', 10)
})
})
5. 创建pm2所需的 配置文件 process.json
#process.json
{
"apps": [
{
"script": "mock/server.js",
"error_file" : "pm2_log/error.log",
"out_file" : "pm2_log/out.log",
"merge_logs" : true,
"log_date_format" : "YYYY-MM-DD HH:mm Z"
}
]
}
6. 上传至线上服务器, 进入项目根目录, 执行pm2运行命令
pm2 start process.json
然后在控制台执行 pm2 list 命令, 如果出现以下,则证明已开启后台运行
7. 使用nginx开启反向代理, 使用域名访问 (不需要的可以跳过该步奏)
二. mock服务自动化部署脚本的实现
具体流程为:
1. 新建nodejs项目, 用于接收 webhook回调
node init
2. 项目的package.json文件如下, 在根目录执行 cnpm install 安装所有依赖库
{
"name": "mock_webhook",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"body-parser": "^1.17.2",
"express": "^4.15.3"
}
}
3. 编写app.js用于接收webhook回调地址, 以及自动执行shell命令
// app.js
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
// 衍生一个 shell 并在 shell 上运行命令,当完成时会传入 stdout 和 stderr 到回调函数
const exec = require('child_process').exec
// mock服务器项目地址
const projectPath = '/usr/local/www/mock-server'
// webhook 回调时携带的密码,防止URL被恶意请求
const webhookPassword = 'test123456'
// 进入到mock服务器项目, 并执行 git pull的shell命令
const cmd_str_gitPull = `cd ${projectPath} && git pull origin master`
// 重启mock服务器的shell命令
const cmd_str_restartJsonServer = `pm2 restart server`
const hostname = '127.0.0.1'
const port = 3001
app.post('/webhook', (req, res) => {
try {
let body = req.body
if(body.hook_name === 'push_hooks') {
if(body.password === webhookPassword) {
exec(cmd_str_gitPull, (error, stdout, stderr) => {
if(error) {
res.send(`exec gitPull error ${error}`)
}else {
exec(cmd_str_restartJsonServer, (error, stdout, stderr) => {
if (error) {
res.send(`exec restartJsonServer error ${error}`)
}else {
res.send('restartJsonServer success')
}
})
}
})
}else {
res.send('hook password error')
}
}else {
res.send('hook_name is not push_hooks')
}
}catch(err) {
res.send(`exception >>>${err}`)
}
})
app.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}`)
})
4. 将该项目上传至 和mock服务同一台线上服务器中,进入项目目录, 使用pm2部署
pm2 start app.js
然后在控制台执行 pm2 list 命令, 如果出现以下,则证明已开启后台运行
5. 使用nginx开启反向代理, 使用域名访问 (不需要的可以跳过该步奏)
6. 在码云平台中, 自己的mock服务器项目 的webhook管理中,配置自动化部署的post地址及密码, 点击测试查看是否响应