我们通常需要在 PUSH 代码到远程仓库时,线上环境会自动进行代码同步,这时候就需要用到WebHook,它会自动回调我们设定的http地址。
通过请求我们自已编写的脚本,来拉取代码,实现与远程仓库代码的同步。
一、我们先创建一个本地仓库
1 2 3 4 | echo "# 测试" > README.md git init git add README.md git commit -m "test" |
在码云或 GitHub 上创建一个空仓库,比如:test,然后让本地仓库与远程仓库关联。
1 2 | git remote add origin https: //gitee.com/xxx/test.git git push -u origin master |
二、在本地仓库,添加WebHook文件,并提交到版本库
码云版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php $data = json_decode( file_get_contents ( 'php://input' ), true); // 码云WebHooks中配置的密码 $password = "123456" ; // 你本地的项目路径 $path = "/data/wwwroot/test" ; // 判断密码 if ( $data [ 'password' ] === $password ) { echo shell_exec( "id -a" ); echo shell_exec( "cd {$path} && /usr/bin/git reset --hard origin/master && /usr/bin/git clean -f && /usr/bin/git pull 2>&1" ); exit (); } http_response_code(404); |
GitHub版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?php // GitHub项目 Settings/Webhooks 中的 Secret $secret = "123456" ; // 你本地的项目路径 $path = "/data/wwwroot/test" ; // 验签 $signature = $_SERVER [ 'HTTP_X_HUB_SIGNATURE' ]; if ( $signature ) { $hash = "sha1=" . hash_hmac( 'sha1' , file_get_contents ( "php://input" ), $secret ); if ( strcmp ( $signature , $hash ) == 0) { echo shell_exec( "id -a" ); echo shell_exec( "cd {$path} && /usr/bin/git reset --hard origin/master && /usr/bin/git clean -f && /usr/bin/git pull 2>&1" ); exit (); } } http_response_code(404); |
三、登陆线上服务器,为用户生成 SSH 秘钥,并配置码云或GitHub的项目公钥。
配置公钥主要的作用是免去每次 git 操作时需要输入密码。
注意,这里,我们要为 www 用户或 nobody 用户生成 ssh 秘钥,别搞错了。webhook 调用时,是 php 脚本当前执行的用户。
具体是哪个用户可以通过 echo shell_exec('id -a'); 来查看。
1 2 3 | sudo mkdir -p /home/www/.ssh sudo chown -R www.www /home/www/.ssh sudo -Hu www ssh-keygen -t rsa |
一路回车,直到结束,系统会在用户的家目录,生成 id_rsa 和 id_rsa.pub 两个文件,即 id_rsa 密钥 和 id_rsa.pub 公钥。
1 | cat /home/www/.ssh/id_rsa.pub |
然后在 码云 项目管理 -> 公钥管理 -> 添加公钥 ,把 id_rsa.pub 中的内容添加。
在GitHub 账号 -> Setting -> SSH and GPG keys ,把 id_rsa.pub 中的内容添加。
然后分别在码云和 GitHub 项目配置WebHook,注意地址必须能外网访问的。
四、登陆线上服务器,并使用 ssh 协议 clone 项目
注意,我们配置了项目的 ssh 公钥,拉取项目要走 ssh 协议,而不是 https。
1 | sudo -u www git clone git@gitee.com:xxx/test.git |
注意,如果报错, fatal: 不能创建工作区目录 'test': 权限不够 ,则需要创建一个同名 test 目录,并把目录所属用户修改成 www。
1 | chown -R www.www test |
修改权限,注意你PHP运行时的用户是谁,一般为www,也有可能是 nobody
1 2 3 | sudo chown -R www . sudo chmod -R g+s . sudo -u www git pull |
在本地提交文件,就可以看到代码自动同步到线上服务器了。
五、基于不同分支,来同步不同目录下的代码
这里以gitee为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <?php $data = json_decode( file_get_contents ( 'php://input' ), true); // 码云WebHooks中配置的密码 $password = "123456" ; // 你本地的项目路径 $paths = [ 'master' => '/data/www/wwwroot/master' , 'test' => '/data/www/wwwroot/test' , 'develop' => '/data/www/wwwroot/develop' , ]; // 获取分支名 $ref = explode ( '/' , $data [ 'ref' ]); $branch = end ( $ref ); // 判断密码 if ( $data [ 'password' ] === $password && $data [ 'total_commits_count' ] > 0 && $paths [ $branch ] ) { $path = $paths [ $branch ]; echo shell_exec( "id -a" ); echo shell_exec( "cd {$path} && /usr/bin/git checkout {$branch} 2>&1" ); echo shell_exec( "cd {$path} && /usr/bin/git reset --hard origin/{$branch} && /usr/bin/git clean -f && /usr/bin/git pull origin {$branch} 2>&1" ); exit (); } http_response_code(404); |
我们在本地创建三个目录,分别对应三个分支,其中一个分支代码更新时,则自动同步。
注意,本地通过 sudo -u www git clone xxx 拉取代码后,切换分支时,也需要指定用户,不然会有权限问题。
1 | sudo -u www git checkout develop |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决