作为一名”伪码农”运维工程师,在接触了开发方面的知识后;也在写项目时一直使用git,可是开发、调试、部署都是在本地进行的;在部署到服务器时也是通过手工去获取仓库的代码;
1.开发完代码提交到远程仓库;
2.登录远程服务器,并切到代码目录进行git pull;
3.重启supervisor应用(我这边开发的python web应用是supervisor进行管理);

当然如果只是一次性部署上去就不再修改的话并没啥问题,但是要是项目持续性修改迭代的话,就比较麻烦了,就在不断的重复着上面的步骤。作为一个”伪码农”,怎么允许不断的重复同样的工作,于是git webhooks闪亮登场;大家对于钩子并不陌生,同样的版本控制SVN也有钩子这个功能;只是个人更加的倾向于使用git; 然后git也催生出来了很多;比如使用最广泛的是GitHub,再其次就是Gitlab,最后就是我这边是用的Gogs;他们都有同样的功能;只是说看需求跟习惯; gogs有个docker版本;能在2分钟之内就可以跑起来非常轻巧方便;感兴趣的请点击这里Gogs

git webhook进行自动部署

如何实现 Git webhook进行自动部署,其实原理很简单,如图所示:

1.本地代码开发完毕提交到远程仓库;

2.通过 POST 请求将订阅事件信息发送至向指定 URL 地址;

3.指定的url是使用Flask写的一个应用,触发这个URL就会进行远程仓库的代码clone/pull

4.拉取代码完毕后,重启服务

Flask web应用代码:

# -*- coding:utf-8 -*-
# 依赖包: pip install flask gitpython

from flask import Flask, request, jsonify,abort
import git, os

# 远程服务器代码地址
code_dir = "./code"

# 远程仓库地址
git_url = "git@192.168.1.105:guomaoqiu/devopscode.git"

#白名单
allow_ip=["192.168.1.105"]

app = Flask(__name__)

#重启服务
restart_services = os.system("supervisorctl -c /etc/supervisord.conf restart devops && supervisorctl -c /etc/supervisord.conf restart celery")

@app.route('/pullcode', methods=['POST'])
def pullcode():
    # 只允许指定服务器向Flask应用发起POST请求,否则直接返回403
    if request.headers.get('X-Forwarded-For', request.remote_addr) not in allow_ip:
        return abort(403)

    if request.method == 'POST':
        if os.path.isdir(code_dir):
            local_repo = git.Repo(code_dir)
            try:
                print local_repo.git.pull()
                # 重新加载代码、重启服务
                restart_services
                return jsonify({"result":True,"message":"pull success"})
            except Exception,e:
                return jsonify({"result":False,"message": "pull faild".format(e)})
        else:
            try:
                print git.Repo.clone_from(url=git_url, to_path=code_dir)
                # 重新加载代码、重启服务
                restart_services
                return jsonify({"result":True,"message":"clone success"})
            except Exception, e:
                return jsonify({"result":False,"message": "clone faild".format(e)})
if __name__ == '__main__':
    app.run(host='192.168.1.29', port=5003)

如果其他地址发起POST请求那么就直接返回403,这样就避免了其他人乱来的情况:

总结起来也就是:
本地仓库推送代码到远程仓库后,一旦本地仓库变更提交就会触发webhook发送post请求,驱动自动部署、重启服务等。
这样一来只需要本地开发好代码提交后直接访问服务器就可以验证我们的应用程序了;