-
-
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 [email protected]
Here's my guide: http://technotes.tumblr.com/post/33867325150/php-hook-script-that-can-git-pull-apc-clear-cache