Git实现自动化部署
业务需求
随着项目业务越来越复杂,参与开发的人越来越多,代码管理,部署就会越来越复杂。传统手动部署变的不可靠,容易出错,而且浪费大量时间。有没有什么办法制动部署呢?这了介绍利用git hook
完成制动部署。
当然,制动化部署是DevOps的重要部分。
关于钩子(hooks)
客户端钩子
客户端钩子分为很多种。 下面把它们分为:提交工作流钩子、电子邮件工作流钩子和其它钩子。脚本写在工作区的.git/hooks
中。
提交工作流钩子
pre-commit
在键入提交信息前运行。
prepare-commit-msg
在启动提交信息编辑器之前,默认信息被创建之后运行。
commit-msg
如果该钩子脚本以非零值退出,Git将放弃提交。
post-commit
钩子在整个提交过程完成后运行。
电子邮件工作流钩子
有3个钩子,不常使用,就不介绍了。
其它客户端钩子
post-rewrite
钩子被那些会替换提交记录的命令调用。
pre-push
钩子会在 git push 运行期间
服务端钩子
服务端钩子脚本在推送到服务器之前和之后
运行。脚本是写在git服务端。
pre-receive
处理来自客户端的推送操作时,最先被调用
的脚本是pre-receive。推送到服务器前运行的钩子可以在任何时候以非零值
退出
update
update脚本和pre-receive脚本十分类似,不同之处在于它会为每一个准备更新的分支各运行一次。假如推送者同时向多个分支推送内容,pre-receive 只运行一次,相比之下 update 则会为每一个被推送的分支各运行一次。
post-receive
post-receive 挂钩在整个过程完结以后运行,该脚本无法终止推送进程。它的用途包括:发邮件,持续集成
,通知等。
服务器本地自动部署
如果使用的gitlab搭建的私有库,在项目的设置
- GIT钩子管理
中将如下代码粘贴进去即可。如果没有web界面,可以在git服务器的仓库目录中hooks
中的post-receive
中添加。
#!/bin/sh
cd /data/webdata/dev.app.cps.com.cn
unset GIT_DIR
git pull origin develop
echo `date "+%Y-%m-%d %H:%M:%S"` "cpsapp-api.git develop分支更新到测试服" >> /data/weblogs/hook.log
echo 0
修改执行权限
chmod +x post-receive
远程自动部署
如果git服务器与web服务器不是同一服务器,那么应该怎么部署呢。如果git服务器,安装了gitlab或者gitea等。那么可以使用webhooks
自动部署,
webhooks原理
- 配置gitlab当push动作的时候,访问web服务器上的一个链接。比如xxx.example.com/webhooks.php
- webhooks.php里面写着一行代码,会让服务器git pull相应项目的代码到web目录。
- pull结束,代码就部署在web目录了。
webhooks.php代码参考
<?php
$valid_token = 'secret_token';
$valid_ip = array('127.0.0.1'); //这里填你的gitlab服务器ip
$client_token = $_SERVER['HTTP_X_GITLAB_TOKEN'];
$client_ip = $_SERVER['REMOTE_ADDR'];
if ($client_token !== $valid_token) die('Token mismatch!');
if (!in_array($client_ip, $valid_ip)) die('Ip mismatch!');
exec("cd /var/www/html/; git pull origin master");
//exec("cd /var/www/html/; git pull origin master 2>&1", $output);
//var_dump($output); 这样可以用浏览器调试输出
?>
功能完善的代码
//默认是用git全局变量,有的环境可能要指明具体安装路径
$git = "/usr/bin/git";
//指定pull分支,为空就是默认分支
$branch = "";
//本地日志名称,需要有写的权限
$hookLogName = "../runtime/hook.log";
//网站根目录
$webRoot = "/home/www/wwwroot/heidou.store/";
//在GITEE设置的密码
$password = "password";
//测试模式,无需密码:true打开,false关闭$isTest = true;
$isTest = false;
$requestBody = file_get_contents("php://input");
if (empty($requestBody) && empty($isTest) && $isTest === false) {
exit('参数错误');
}
//解析gitee发过来的JSON信息
$content = json_decode($requestBody, true);
//密码验证
if($content['password'] == $password || $isTest){
if ($content['ref'] == "refs/heads/$branch" || !$branch || $isTest) {
// $cmd = "cd $webRoot && $git reset --hard && $git clean -f && $git pull $branch 2>&1";
$cmd = "cd $webRoot && $git pull $branch 2>&1";
$result = shell_exec($cmd); //关键命令,拉取代码,2>&1后台执行
$res_log = PHP_EOL."【PULL START】" .date('Y-m-d H:i:s'). PHP_EOL;
if(!empty($isTest)){
$res_log .= date('Y-m-d H:i:s') . '执行测试!'. PHP_EOL;
}else{
$res_log .= date('Y-m-d H:i:s') . '向' . $content['repository']['name'] . '项目的' . $content['ref'] . '分支push了' . $content['total_commits_count'] . '个commit:'. PHP_EOL;
}
$res_log .= $cmd. PHP_EOL;
$res_log .= $result. PHP_EOL;
$res_log .= "【PULL END】";
file_put_contents($hookLogName, $res_log, FILE_APPEND);//写入日志
if ($isTest) {
# code...
var_dump($res_log);
}
}
} else {
file_put_contents($logName, '密码错误!', FILE_APPEND);
echo '密码错误!';
}
遇到的问题
- hooks没有权限控制,不能指定某个分支中才能触发hooks,如果需要指定分支,就需要使用gitlab等工具提供的webhooks功能
最后更新于 2022-04-26 16:09:30 并被添加「git」标签,已有 1351 位童鞋阅读过。
本站使用「署名 4.0 国际」创作共享协议,可自由转载、引用,但需署名作者且注明文章出处
此处评论已关闭