我想做的是这么一件事:git 每创建一个新分支,push之后自动部署的服务器的不同路径,然后根据不同端口访问不同分支的代码,以方便进行该分支的测试。
并且我正在学习 thinkphp 5 呢,正好测试一下。
举个栗子来说就是:当我新建了一个分支为 8081_opqnext_test,然后完成了某个功能。git add、git commit、当 git push 之后,服务器会自动拉取 8081_opqnext_test 分支上的代码到 /data/tp/8081 这个目录里,然后 访问 beta.tp.opqnext.com:8081 就会直接访问到该分支的代码。同理,当我创建看一个 8082_user_list 的分支。完成了用户列表的功能。git push 之后服务器会自动创建目录 /data/tp/8082 并且将代码到 pull 到该目录。当你访问 beta.tp.opqnext.com:8082 的时候,会访问到该分支的代码便于测试。那 master 的代码每次合并之后 都会自动部署到 /data/tp.opqnext.com/ 访问 tp.opqnext.com 即线上的代码。
然后我们分开步骤来说:
- 首先完成自动部署功能。
- 各个分支自动部署到不同路径。
- 访问不同的端口映射到不同的分支代码。
首先完成自动部署
这里我用的是 码云 git@oschina 来做的。
首先需要配置 ssh公钥,看这里:
特别提醒的是:你的 nginx 是用哪个用户跑的,那么在生产公钥之前先要切换到该用户下。比如我 nginx 是 ngxuser 用户,假如你在 root 下生产公钥并且配置到码云,你的hook是没有权限 clone 和 pull 代码的/(ㄒoㄒ)/~~
你可以按如下命令来生成sshkey:
sudo ngxuser # 你的nginx用户
ssh-keygen -t rsa -C "xxxxx@xxxxx.com"
# Generating public/private rsa key pair...
# 三次回车即可生成 ssh key
查看你的 public key,并把他添加到码云(Gitee.com)
cat ~/.ssh/id_rsa.pub
# ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6eNtGpNGwstc....
添加后,在终端(Terminal)中输入
ssh -T git@git.oschina.net
若返回
Welcome to Git@OSC, yourname!
则说明添加成功,然后去 码云后台 添加你的 ssh key
然后去配置 webhook 查看教程 配置完成 webhook 之后,你每次 push 之后就会触发这个钩子。最简单的,你写一个 auto_deploy_code.php 放到网站根目录。内容是:
<?php
echo '<pre>';
system("git pull", $var);
不用接收 webhook 给你发过来的数据,你只管 pull ,假如你只有一个分支的话。
但是我要接收呢,既然有了数据,当然要接收。
我创建了一个新的分支,这个分支名称可以规定好,比如:8081_opqnext_user (端口-开发者-开发功能)这里怎么约定,那你后面的脚本就怎么写呗。
自动部署的脚本:
<?php
/**
* GIT webHook 自动部署
* @author 郭贰小姐
* @time: 2017/7/13
*/
$hook = str_replace('\"','"',$_POST['hook']);
$res = json_decode($hook,true);
$token = '你配置的token';
if ($res['password'] != $token) {
error_log('auto_git_pull ['.date('Y-m-d H:i:s').'] token is error]');
} else {
$dir = '/data/tp/';
$branch = explode('/',$res['push_data']['ref'])[2];
$port = explode('_',$branch)[0];
$dir = '/data/tp/'.$port;
if(isset($res['push_data']['commits']) && !empty($res['push_data']['commits'])){
if($branch == 'master'){
$cmd = "cd /data/tp.opqnext.com; git pull origin master";
shell_exec($cmd);
error_log('auto_git_pull '.$res['push_data']['user_name'].' '.$branch.' msg:'.$res['push_data']['commits'][0]['message'].' =>'.date('H:i:s'));
} else {
if(!is_dir($dir)){
mkdir($dir,0777,true);
$cmd = "cd $dir; git clone -b $branch git@git.oschina.net:opqnext/thinkphp.git $dir";
} else {
$cmd = "cd $dir; git pull origin $branch";
}
shell_exec($cmd);
error_log('auto_git_pull '.$res['push_data']['user_name'].' '.$branch.' msg:'.$res['push_data']['commits'][0]['message'].' =>'.date('H:i:s'));
}
} else {
// 删除分支
$cmd = "cd /data/tp; rm -rf $port";
shell_exec($cmd);
error_log('auto_git_del_branch '.$res['push_data']['user_name'].' '.$branch.' =>'.date('H:i:s'));
}
}
首先检测 token 是否正确,获取分支名称,截取端口号,填写端口完整路径。
如果 commit 信息有内容,说明判断分支是否为 master 如果是就拉线上代码,如果是分支 commit 检测端口路径是否存在,存在即 pull 否则 clone 没了。
既然各个分支的目录都已经创建好了,代码也可以自动部署了。那再配置 nginx 就可以了,我本来以为可以写一个类似于正则匹配,匹配到哪个端口就去访问对应的路径,但是貌似不行,所以只能写多个 server 监听不同的端口,配置相应的路径。
比如 8081,8082,8083,8084…
每个开发者三五个端口,不错了。大概就是这样一个理论。我发现我写代码从来都是道理基本通,但是不能用…如果你要用的话,再修改修改就 beautiful 了。