当前位置: 首页 > 后端技术 > Node.js

Node+Git+Webhook自动化部署

时间:2023-04-03 13:10:57 Node.js

前言之前断断续续的在重构一个项目,后来发现一开始功能设计的太多了,可能要花很多时间去添加,但是核心功能基本都是完成了,于是想能不能半在线状态,然后通过update提交git,让服务器部署自动更新。之前接触过githooks是可以实现的,所以这里记录一下边鼓捣边写的文章。正文准备首先确定需要完成的内容,明确需求:1.监控指定的git提交2.执行指定的多个脚本并且因为我需要分别执行客户端和服务器目录的部署命令。所以需要特殊处理。首先在域名管理端添加一条A记录指向新的项目名。因为Webhooks需要外部域名,所以提前添加一个。new.xxx.com则需要在服务器上配置Nginx转发。我的nginx早就配置好了。在etc/nginx/conf/vhost中添加一个文件,内容如下:server{listen80;服务器名称new.xxx.com;indexindex.htmlindex.htmindex.phpdefault.htmldefault.htmdefault.php;位置/{proxy_passhttp://127.0.0.1:8801;}access_log关闭;}转发本地8801。然后重启Nginxnginx-sreload然后gitclone仓库因为项目使用的是mongodb数据库:需要创建相应的数据库,并添加权限。1.将数据库切换到abc2。指定数据库abc,权限:userAdmindb.createUser({user:"123",pwd:"123",roles:[{role:"userAdmin",db:"abc"}]})3.验证account123createdabovedb.auth('123','123')=>1其实配置webhook是最简单的,只需要在你的github对应的项目仓库右边选择settings,选择Forwebhooks,选择addwebhook和配置如下:这里需要记住你设置的secret和你定义的pushaction,这里是pushCode。在开始写脚本之前,先看看最终的目录结构:├──README.md├──clean.sh//清理缓存执行git命令├──client│├──autoClient.sh//客户端自动监控│├──build│├──config│├──package.json│├──public│├──scripts│├──src│├──tsconfig.json│├──tsconfig.test.json│├──tslint.json│├──www│├──yarn.lock├──deploy│└──index.js//监听webhook事件并执行clean.shautoClient.shautoServer.sh├──package.json├──server│├──autoServer.sh//服务器端自动监控│├──dist│├──package.json│├──src│├──tsconfig.json│├──tslint。json│└──yarn.lock由于项目原因,脚本还需要自定义。首先是客户端,因为前端使用的是typescript+React全家桶,所以打包很慢。在服务器上搭建的时候,因为阿里云内存不够,会很卡。基于这样的考虑,计划在本地bulid完成后,推送到git,服务端去gitpull。而在前端还有一个考虑就是用什么来运行前端代码。因为服务器没有安装类似的服务,所以打算使用node框架koa来启动一个HTTP服务来运行。代码如下:app.jsconstKoa=require('koa')constmorgan=require('koa-morgan')constpath=require('path');conststatic=require('koa-static')www目录下的constfs=require('fs')constapp=newKoa();//loggerapp.use(morgan(':remote-addr-:remote-user[:date[clf]]":method:urlHTTP/:http-version":status:res[content-length]:response-timems'));//staticassetsapp.use(static(path.join(__dirname,'../build')));//异步读取文件的形式//app.use(async(ctx,next)=>{//ctx.type='html';//ctx.body=awaitfs.createReadStream(path.resolve(__dirname,'..','./build','index.html'));//})module.exports=app;index.js'usestrict';constapp=require('./app');constPORT=process.环境端口||8801;console.log('clientstart')app.listen(PORT,()=>{console.log(`Applisteningonport${PORT}!`);});node./www/index.js可以监听同级构建目录。当然,这是粗略的,需要逐步完善。我们需要在客户端目录中构建autoClient.sh#!/bin/bashcd./echo'clientbuild'kill-9$(lsof-i:8801|awk'{print$2}'|tail-n2)node。/www/index.js用于自动执行监控动作。因为多次推送监控的前端端口是同一个,如果不处理就会报错。需要根据端口号8801结束进程,然后重启服务。然后是server端,因为整个后端都是用koa完成的,项目比较小,在server端实时编译也花不了多少时间,所以直接执行yarnstart("start":"yarnrunbuild&&yarnrunwatch,)用于编译和监控。在服务器目录下创建autoServer.sh#!/bin/bashcd./echo'serverstart'kill-9$(lsof-i:8866|awk'{print$2}'|tail-n2)yarnrunstartsameasus在执行监听之前,需要结束之前端口上的进程。然后我们看一下clean.sh这个shell脚本是用来清理client目录下的build文件夹的。#!/bin/bashrmrf./client/buildgitreset--hardorigin/mastergitclean-fgitpull可以看到先清理缓存,再拉取代码到服务器。最后我们看一下部署脚本deploy/index.jsvarspawn=require('child_process').spawnvarhttp=require('http')varspawn=require('child_process').spawnvarcreateHandler=require('github-webhook-handler')varhandler=createHandler({path:'/pushCode',secret:'xxx'})//填写http.createServer(function(req,res){handler(req,res,function(err){res.statusCode=404;res.end('没有这样的位置')})}).listen(7777)handler.on('error',function(err){console.error('Error:',err.message)})//监听推送事件handler.on('push',function(event){console.log('Receivedapusheventfor%sto%s',event.payload.repository.name,event.payload.ref)init()//everyRe-listeneverypull})functionrumCommand(cmd,args,cwd,callback){varchild=spawn(cmd,args,{cwd:cwd})varresponse=''child.stdout.on('data',function(buffer){响应+=buffer.toString();})child.stdout.on('end',function(){callback(response)})}functioninit(){rumCommand('sh',['../clean.sh'],'./',function(result){//清除缓存console.log(result)})rumCommand('sh',['../server/autoServer.sh'],'../server',function(result){//cClientupdateconsole.log(result)})rumCommand('sh',['../client/autoClient.sh'],'../client',function(result){//更新console.log(result)在服务器端})}init()//脚本第一次运行,默认指向一次。这里需要声明的是,多个目录下脚本的执行需要相应的环境,所以脚本是分开的。DeploymentDeployment我们只需要pm2启动deploy/index.js,本地开发后push,服务端就可以自动拉取代码并部署。