-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgit_post_receive.php
122 lines (108 loc) · 4.74 KB
/
git_post_receive.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
<?php
/**
* Respond to github post-receive JSON.
*
* Security concerns: I wish I can restrict this script to only respond to POST
* requests from github's servers, but that information isn't avaialble.
*/
// get script variables
require dirname(__FILE__) . '/config.php';
require dirname(__FILE__) . '/functions.php';
// NOTE: JSON should come preinstalled with PHP starting with 5.2
if (!function_exists('json_decode')) {
die(error_log('JSON not installed'));
}
debug('github script called by ' . $_SERVER['SERVER_ADDR']);
// github sends git post-receive hooks as a single POST param called 'payload'
/* POST param is in following JSON format:
{
:before => before,
:after => after,
:ref => ref,
:commits => [{
:id => commit.id,
:message => commit.message,
:timestamp => commit.committed_date.xmlschema,
:url => commit_url,
:added => array_of_added_paths,
:removed => array_of_removed_paths,
:modified => array_of_modified_paths,
:author => {
:name => commit.author.name,
:email => commit.author.email
}
}],
:repository => {
:name => repository.name,
:url => repo_url,
:pledgie => repository.pledgie.id,
:description => repository.description,
:homepage => repository.homepage,
:watchers => repository.watchers.size,
:forks => repository.forks.size,
:private => repository.private?,
:owner => {
:name => repository.owner.login,
:email => repository.owner.email
}
}
}
*/
if (!empty($_POST['payload'])) {
debug('got payload: ' . $_POST['payload']);
// parse payload data
$payload = json_decode($_POST['payload']);
// on error json_decode retuns null
if (empty($payload)) {
die(error_log('Invalid payload JSON sent from ' .
$_SERVER['SERVER_ADDR']));
}
// now make sure that the commit is for the branch we want to track
$sent_email = false;
if ($payload->ref === 'refs/heads/' . $tracking_branch) {
debug('payload is a commit to a tracking branch: ' . $tracking_branch);
// this is kinda convoluted, but necessary for security (?). apache
// user only has the ability to run a specified script as specified user
// so will need to execute that script as specified user. That script
// will output and exit the git pull command as if it was run here
$output = array(); $return_var = null;
$cmd = sprintf("sudo -u %s %s/gitpull.php", $repo_user, dirname(__FILE__)); // system should be setup to run gitpull.php as specified user
debug('executing command: ' . $cmd);
exec($cmd, $output, $return_var);
debug('cmd output: ' . implode("\n", $output));
// if $return_var is non-zero, then an error happened
// http://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/exitcodes.html
if (0 !== $return_var) {
// there was an error, so email the admin
debug('there was an error, emailing admin: ' . $admin_email);
$sent_email = mail($admin_email, 'git_post_receive: Failed to update ' .
'branch ' . $tracking_branch, sprintf("return_var: %d\n\ncommand line " .
"output:\n\n%s\n\njson_payload:\n\n%s", $return_var,
implode("\n", $output), print_r($payload, true)));
} else {
// update was successful, so email committer and admin
// ignore anonymous Github emails
if (strpos($payload->pusher->email, 'users.noreply.github.com') !== false) {
debug('Ignoring noreply email ' . $payload->pusher->email);
$payload->pusher->email = '';
}
// get emails of committers
$committers = array($admin_email, $payload->pusher->email);
debug('update successful, emailing pusher and admin: ' . implode(';', $committers));
$sent_email = mail(implode(',', $committers), 'git_post_receive: ' .
sprintf('Update repo with changes from %s branch', $tracking_branch),
sprintf("Updated repo at %s with latest changes from %s " .
"branch. Here is the output of the git pull " .
"\n\n%s", $repo_location, $tracking_branch,
implode("\n", $output)));
}
if (empty($sent_email)) {
error_log('Could not send email notification for git_post_receive');
}
} else {
debug('payload was not a commit to a tracking branch: ' . $tracking_branch);
}
} else {
debug('no payload found');
}
?>