-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathgh-file-hook.php
140 lines (117 loc) · 4.23 KB
/
gh-file-hook.php
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<?php
// This script is setup as Webook endpoint
// configured to notify on each push:
// https://github.com/file/file/settings/hooks
//
// The script will trigger travis build of file-tests repository passing
// commit=$commit of file repository that triggered the build
//
// References:
// https://developer.github.com/webhooks/
// https://gist.github.com/glensc/fb5b55f0d0abc962f3bfb0777ab5546a
// ruby -rsecurerandom -e 'puts SecureRandom.hex(20)'
define('GITHUB_HOOK_SECRET', '');
// obtained with 'travis login --org; travis token --org'
define('TRAVIS_CI_TOKEN', '');
// repo to trigger build on
define('TRAVIS_REPO', 'file/file-tests');
// and the branch name
define('TRAVIS_REPO_BRANCH', 'master');
set_exception_handler(function($e) {
header('HTTP/1.1 500 Internal Server Error');
error_log(basename(__FILE__, '.php') . ': '. $e->getMessage());
die("Error on line {$e->getLine()}: " . htmlspecialchars($e->getMessage()));
});
// https://developer.github.com/v3/activity/events/types/#pushevent
// X-Hub-Signature: sha1=ffd1a5f14b30eaaaca1e84499c372743302bc47d
function get_github_payload($secret, $assoc = false) {
if (!isset($_SERVER['HTTP_X_GITHUB_EVENT'])) {
throw new InvalidArgumentException('No event');
}
$eventType = $_SERVER['HTTP_X_GITHUB_EVENT'];
if ($eventType != 'push') {
throw new InvalidArgumentException("Invalid Event: $eventType");
}
if (!isset($_SERVER['HTTP_X_HUB_SIGNATURE'])) {
throw new InvalidArgumentException("HTTP header 'X-Hub-Signature' is missing");
}
if (!extension_loaded('hash')) {
throw new InvalidArgumentException("Missing 'hash' extension to check the secret code validity.");
}
# https://developer.github.com/v3/repos/hooks/#create-a-hook
# The value of this header is computed as the HMAC hex digest of the body, using the secret as the key.
list($algo, $hash) = explode('=', $_SERVER['HTTP_X_HUB_SIGNATURE'], 2);
if (!in_array($algo, hash_algos(), true)) {
throw new Exception("Hash algorithm '$algo' is not supported.");
}
$rawPost = file_get_contents('php://input');
if ($hash !== hash_hmac($algo, $rawPost, $secret)) {
throw new InvalidArgumentException("Hook secret ($algo) does not match");
}
if (isset($_POST['payload'])) {
// for urlencoded data
$payload = $_POST['payload'];
} else {
// for application/json
$payload = $rawPost;
}
return json_decode($payload, $assoc);
}
function travis_request($repo, $token, $request) {
require_once 'UrlUtil.php';
$headers = array(
"Content-Type: application/json",
"Accept: application/json",
"Travis-API-Version: 3",
"Authorization: token $token",
);
$url = sprintf("https://api.travis-ci.org/repo/%s/requests", urlencode($repo));
$body = json_encode(array('request' => $request));
$params = array();
$options = array(
CURLOPT_HTTPHEADER => $headers,
);
$res = UrlUtil::JsonRequest($url, $body, UrlUtil::HTTP_METHOD_POST, $options, $info, 1);
// handle errors, like request_limit_reached
if ($res['@type'] == 'error') {
throw new RuntimeException($res['error_message']);
}
return $res;
}
function travis_trigger_build($payload) {
$diff = $payload['compare'];
$repo = $payload['repository']['full_name'];
$commit = $payload['head_commit'];
error_log("PUSH[$repo]: $diff");
$branch = substr($payload['ref'], 11);
$commit_id = substr($commit['id'], 0, 7);
$commit_message = $commit['message'];
// use shorter username if available
if (isset($commit['author']['username'])) {
$author = "@{$commit['author']['username']}";
} else {
$author = $commit['author']['name'];
}
// remove newlines, they look better then in travis
$commit_message = preg_replace("/\s+/", ' ', $commit_message);
// build message to be displayed in travis. try to be compact
$message = "$repo $commit_id ($author) $commit_message";
// NOTE: env gets overwritten,
// so if you have any env in .travis.yml it must be specified here as well
$env = array(
'global' => array(
"repository={$payload['repository']['clone_url']}",
"commit=$commit_id",
),
);
$request = array(
'message' => $message,
'branch' => TRAVIS_REPO_BRANCH,
'config' => array(
'env' => $env,
),
);
return travis_request(TRAVIS_REPO, TRAVIS_CI_TOKEN, $request);
}
$payload = get_github_payload(GITHUB_HOOK_SECRET, 1);
$res = travis_trigger_build($payload);