/ 闭门造轮子 / 通过Bitbucket的POST hook向Dreamhost上自动部署git项目

通过Bitbucket的POST hook向Dreamhost上自动部署git项目

2014-02-22 posted in [问题即经验]

大多数的PaaS服务都是用git push来进行部署,比如Heroku。其原理就是使用git提供的hook功能,这在GitHub和Bitbucket上都有提供。使用这样的方式对项目管理来说非常方便,但这次没有使用PaaS,于是准备在Dreamhost上手动配置一个hook来解决代码部署。

根据Bitbucket对POST hook的官方说明,我们可以通过创建一个POST hook来进行git项目的自动部署。

第一步:在目标机器创建接收POST hook的URL

Bitbucket的官方hook说明中提到可以使用带有Basic认证模式的URL来进行POST通知,我个人也推荐这个方法。原因是使用一个随机的用户密码以保证这个URL不被随意或错误的调用,同时用户密码只存在脚本和Bitbucket的hook配置里,其他地方不会使用,具有一定的安全性。

但在测试中发现Dreamhost不支持HTTP Basic Authentication的Header被PHP读取(官方论坛问题:PHP and PHP_AUTH_USER,也可以通过phpinfo()的信息查看),于是通过这篇文章:HTTP Authentication on PHP as CGI (like Dreamhost)的方法,在.htaccess文件中加入以下规则:

RewriteEngine on
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]

并根据文章说明在PHP脚本中使用以下语句获得Basic认证方式的用户和密码变量:

list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
	explode(':' , base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));

第二步:编写目标机器接收的处理逻辑

参考的是这篇博客Using Bitbucket for Automated Deployments里的代码。解析验证参数通过后,就可以使用这段代码执行git pull的过程。整个程序储存为git-hook.php

第三步:准备Dreamhost环境

以上两个文件上传到Dreamhost的网站目录,同时这个目录需要初始化git信息,并以ssh协议添加远端仓库:

$ git init
$ git remote add origin ssh://git@bitbucket.org/username/repo.git

复制Dreamhost上当前用户id_rsa.pub的内容(没有的话创建一个),并到Bitbucket上以此创建一个deploy key(在项目设置中)。这一步我确定是必要的(但按照Bitbucket的说明是要的),但要注意,DH上的rsa只能设置空密码,否则部署不能成功。

接下来准备项目的分支,一般直接使用master分支,我这个项目用Dreamhost主要做测试用,所以使用了dev分支。所以在使用非master分支时需要手动创建好并切换到这个分支,方便起见,切换后可以删除master分支。

第四步:从本地push到Bitbucket测试效果

准备好之前的步骤之后,不需要在Dreamhost上pull代码,而可以回到本地环境,尝试向Bitbucket push一次代码,注意push的分支是之前配置过的。

一切正常的话Dreamhost上的代码就自动pull下来了,这时可以点开网址看看效果。

注:以下是上面提到的两个文件

Update

在Linux主机上遇到的问题这篇文章比较有帮助:

Git pull from a php script, not so simple.

另外注意几点:

  1. 使用PHP函数exec('whoami')方法调用命令行时,命令行的用户是当前执行PHP的用户。
  2. exec('xxx 2>&1')可以捕获命令行的错误输出。
  3. ssh-key出现的各种验证错误问题,都需要检查是否是当前用户,~/.ssh目录权限,~/.ssh/known_hosts文件是否已添加等情况。
  4. PHP中exec()执行脚本的路径是文件所在位置的路径。

-EOF-