Skip to content

Instantly share code, notes, and snippets.

@Nilpo
Forked from webjay/gh_hook.php
Last active August 29, 2015 14:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nilpo/fa4209b1c9e1c6551ee6 to your computer and use it in GitHub Desktop.
Save Nilpo/fa4209b1c9e1c6551ee6 to your computer and use it in GitHub Desktop.
<?php
/**
* This file serves as a post receive hook for a GitHub repository. It should be placed in the root of the repository.
*
* To begin, you will need to store a secret key in an environmental variable on the server.
*
* export SECRET_TOKEN=your_token
*
*
* Next, you should ignore tracking for this file in your local git repository.
*
* git update-index --assume-unchanged gh_hook.php
*
*
* Finally, you need to enable the webhook through the GitHub web interface. If you are unable to add environmental
* variables for whatever reason, you should implement an IP check to be sure that requests are coming from a
* GitHub server.
*
* Copyright (c) 2014 Robert Dunham
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @remarks An improved GitHub post receive webhook processor based on a Gist by webjay.
* @author webjay <https://gist.github.com/webjay/3915531>
* @author Robert Dunham <contact@robdunham.info>
* @website http://www.robdunham.info
* @version 0.1.0
* @date 20140822
* @copyright Copyright (c) 2014, Robert Dunham
*/
// 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);
// exit();
// }
define('SECRET', getenv('SECRET_TOKEN'));
ignore_user_abort(true);
$hmac_header = $_SERVER['HTTP_X_LINKEDSTORE_HMAC_SHA256'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header);
if ($_POST && isset($_POST['payload']) && $verified) {
$payload = json_decode($_POST['payload']);
// which branch was comitted?
$branch = substr($payload->ref, strrpos($payload->ref, '/') + 1);
if ($branch == git_current_branch($cwd)) {
// pull from $branch
$cwd = dirname(__FILENAME__);
$cmd = sprinf('git pull origin %s', $branch);
$result = syscall($cmd, $cwd);
$output = '';
// append commits
foreach ($payload->commits as $commit) {
$output .= "{$commit->author->name} ({$commit->author->username})";
$output .= PHP_EOL;
foreach (array('added', 'modified', 'removed') as $action) {
if (count($commit->{$action})) {
$output .= sprintf('%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 (extension_loaded('apc') && ini_get('apc.enabled')) {
if (apc_clear_cache('opcode') == false || apc_clear_cache('user') == false) {
mail('root', 'Unable to apc_clear_cache', '');
}
}
}
}
}
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];
}
}
function verify_webhook($data, $hmac_header) {
return $hmac_header == hash_hmac('sha256', $data, SECRET);
}
// EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment