-
-
Save webjay/3915531 to your computer and use it in GitHub Desktop.
<?php | |
ignore_user_abort(true); | |
function syscall ($cmd, $cwd) { | |
$descriptorspec = array( | |
1 => array('pipe', 'w'), // stdout is a pipe that the child will write to | |
2 => array('pipe', 'w') // stderr | |
); | |
$resource = proc_open($cmd, $descriptorspec, $pipes, $cwd); | |
if (is_resource($resource)) { | |
$output = stream_get_contents($pipes[2]); | |
$output .= PHP_EOL; | |
$output .= stream_get_contents($pipes[1]); | |
$output .= PHP_EOL; | |
fclose($pipes[1]); | |
fclose($pipes[2]); | |
proc_close($resource); | |
return $output; | |
} | |
} | |
function git_current_branch ($cwd) { | |
$result = syscall('git branch', $cwd); | |
if (preg_match('/\\* (.*)/', $result, $matches)) { | |
return $matches[1]; | |
} | |
} | |
// make sure the request is coming from GitHub | |
// https://help.github.com/articles/what-ip-addresses-does-github-use-that-i-should-whitelist | |
/* | |
$gh_ips = array('207.97.227.253', '50.57.128.197', '108.171.174.178'); | |
if (in_array($_SERVER['REMOTE_ADDR'], $gh_ips) === false) { | |
header('Status: 403 Your IP is not on our list; bugger off', true, 403); | |
mail('root', 'GitHub hook error: bad ip', $_SERVER['REMOTE_ADDR']); | |
exit(); | |
} | |
*/ | |
// cd .. | |
// $cwd = dirname(__DIR__); | |
// GitHub will hit us with POST (http://help.github.com/post-receive-hooks/) | |
if (!empty($_POST['payload'])) { | |
$payload = json_decode($_POST['payload']); | |
// which branch was committed? | |
$branch = substr($payload->ref, strrpos($payload->ref, '/') + 1); | |
// If your website directories have the same name as your repository this would work. | |
$repository = $payload->repository->name; | |
$cwd = '/var/www/'.$repository; | |
// only pull if we are on the same branch | |
if ($branch == git_current_branch($cwd)) { | |
// pull from $branch | |
$cmd = sprintf('git pull origin %s', $branch); | |
$result = syscall($cmd, $cwd); | |
$output = ''; | |
// append commits | |
foreach ($payload->commits as $commit) { | |
$output .= $commit->author->name.' a.k.a. '.$commit->author->username; | |
$output .= PHP_EOL; | |
foreach (array('added', 'modified', 'removed') as $action) { | |
if (count($commit->{$action})) { | |
$output .= sprintf('%s: %s; ', $action, implode(',', $commit->{$action})); | |
} | |
} | |
$output .= PHP_EOL; | |
$output .= sprintf('because: %s', $commit->message); | |
$output .= PHP_EOL; | |
$output .= $commit->url; | |
$output .= PHP_EOL; | |
} | |
// append git result | |
$output .= PHP_EOL; | |
$output .= $result; | |
// send us the output | |
mail('root', 'GitHub hook `'.$cmd.'` result', $output); | |
// if you use APC, especially if you use apc.stat=0, we should clear APC | |
// if (apc_clear_cache('opcode') == false || apc_clear_cache('user') == false) { | |
// mail('root', 'Unable to apc_clear_cache', ''); | |
// } | |
} | |
} | |
?> |
Using this project you can also use ssh or ftp to sync remotely: https://github.com/Coppertino/github-webhook.
All I ever get from this is a blank $result and no results from the git pull. I've even modified your code to help me try to diagnose the problem. I followed your guide but used my own name (smart) in place of www-data as that's who already owns the repo.
$descriptorspec = array(
1 => array('pipe', 'w'), // stdout is a pipe that the child will write to
2 => array('pipe', 'w')
);
$resource = proc_open($cmd, $descriptorspec, $pipes, $cwd);
if (is_resource($resource)) {
stream_set_blocking($pipes[2], 0);
if ($err = stream_get_contents($pipes[2]))
{
return 'Process could not be started [' . $err . ']';
}
$output = stream_get_contents($pipes[1]);
fclose($pipes[1]);
proc_close($resource);
return $output;
} else {
return "No resource provided.";
}
Figured it out. I had several things going on.
- Copied .ssh folder to /var/www so apache could connect to github
- git repo-config core.sharedRepository true
- chown/chmod g+rw .git folder specifically (-R . or -R * doesn't hit the .git folder)
I also modified the function above to have better error output if there is a fatal error in the command executed.
private function _syscall ($cmd, $cwd)
{
$descriptorspec = array(
1 => array('pipe', 'w'), // stdout is a pipe that the child will write to
2 => array('pipe', 'w') //stderr will pipe back
);
$resource = proc_open($cmd, $descriptorspec, $pipes, $cwd);
if (is_resource($resource)) {
stream_set_blocking($pipes[2], 0);
if ($err = stream_get_contents($pipes[2]))
{
return 'Process could not be started [' . $err . ']';
}
$output = stream_get_contents($pipes[1]);
if ($err = stream_get_contents($pipes[2]))
{
return $err;
}
fclose($pipes[1]);
proc_close($resource);
return $output;
} else {
return "No resource provided.";
}
}
@joefresco Or you can just use [suPHP|http://www.suphp.org/Home.html] to make your php script that does git pull
execute under your user instead of apache. No more crazy chmod/chown :)
Thanks for your feedback @joefresco.
I have just recently done this again, and updated my guide.
Hey guys, I've made a stripped down version https://gist.github.com/phedoreanu/11321236.
It's worth noting that in your guide there's a more straightforward way to update your known_hosts
file that more closely follows github documentation:
sudo -u www-data ssh -T git@github.com
Here's my guide: http://technotes.tumblr.com/post/33867325150/php-hook-script-that-can-git-pull-apc-clear-cache