-
-
Save cowboy/619858 to your computer and use it in GitHub Desktop.
<?php | |
// Use in the "Post-Receive URLs" section of your GitHub repo. | |
if ( $_POST['payload'] ) { | |
shell_exec( 'cd /srv/www/git-repo/ && git reset --hard HEAD && git pull' ); | |
} | |
?>hi |
@sudo chmod www-data /var/www/.ssh/known_hosts"
should be sudo chown www-data /var/www/.ssh/known_hosts
.
Also make sure www-data have access to the files in /var/www/.ssh
The permission instructions were very helpfull, but the script doesn't work, so I made one that does:
https://gist.github.com/3915531
Here is a similar project with a bit more advanced options: https://github.com/Coppertino/github-webhook.
I used suPHP to make the php webhook handler execute under my user instead of web server, hence no permissions problems and file ownership changes on pull. May sound scary but if the shell command is hard coded and suPHP is enabled only for that particular script (I can put it in a separate directory) it's pretty safe (feel free to call me out if that's still very bad %))
@jorijnsmit Interesting, a different approach to the problem! Thanks for sharing.
I'm concerned about git reset --hard HEAD
... is it safe to do so? What if some tracked files are (accidentally) edited on a running server? This shouldn't happen, of course, but if it does, I think I'd rather have the change NOT propagate to the server instead of overwriting something.
just a little typo error.. it's receive not recieve.
@webjay It works, you just need to generate the web server's ssh keys. I've merged your security code with this gist and the ssh keys: https://gist.github.com/phedoreanu/11321236.
Note that your repo SHOULD NOT include files that are changed on server. Maybe /uploads
folder or app/logs
or anything. git reset --hard HEAD
will delete everything. Put such files and folders in your .gitignore
.
Just an fyi: I had to change the following before it would work:
if ( $_POST['payload'] ) {
to
if ($_SERVER['HTTP_X_GITHUB_EVENT'] == 'push') {
also, as usually shell_exec is run from the user www-data I had to change permissions by executing the following command inside /var/www/html
sudo chown www-data:www-data -R my-repo/
Thanks @lmann that worked for me:
if ($_SERVER['HTTP_X_GITHUB_EVENT'] == 'push') {
Just figured out the difference. If you use the json content-type, then $_POST['payload'] will not work. You have to use the application/x-www-form-urlencoded for $_POST['payload'] to work.
i need to use that on final of string and work nice:
2>&1
so:
shell_exec( 'cd '.$path.' && git reset --hard HEAD && git pull 2>&1' );
@izeta application/x-www-form-urlencoded got $_POST['payload']
working, cheers!
You can also shell_exec("./pull.sh")
, remembering to chmod u+x pull.sh
.
I'm on SiteGround hosting, so need to worry about www-data .
etc/suoders
:
www-data ALL = (myuser) NOPASSWD: /usr/bin/git
www-data ALL = (myuser) NOPASSWD: /usr/bin/node
www-data ALL = (myuser) NOPASSWD: /usr/bin/drush
www-data ALL = (myuser) NOPASSWD: /usr/bin/whoami
github_post_recieve.php
:
<?php
if ( isset($_POST['payload']) && $_POST['payload'] ) {
echo shell_exec('cd /var/www/mydrupal/ && sudo -u myuser git pull');
echo shell_exec('cd /var/www/mydrupal/sites/all/themes/mytheme/ && sudo -u myuser node ./node_modules/gulp/bin/gulp.js mygulptask');
// Adding the drush will cause the delivery being displayed as unsuccessful. Means GitHub doesn't wait so long. The command will run nevertheless.
echo shell_exec('cd /var/www/mydrupal/ && sudo -u myuser drush @sites cc all -y');
}
// Should return www-data
echo shell_exec('whoami');
// Should return myuser
echo shell_exec('sudo -u myuser whoami');
?>
Thx for the simple gist!
I solved my issue with my shell_exec(...
command not running by changing the directory it was in ownership to www-data
(from root
), ie: sudo chown -R www-data /var/www/
<?php
// GitHub Webhook Secret.
// Keep it the same with the 'Secret' field on your Webhooks / Manage webhook page of your respostory.
$secret = "";
// Path to your respostory on your server.
// e.g. "/var/www/respostory"
$path = "";
// Headers deliveried from GitHub
$signature = $_SERVER['HTTP_X_HUB_SIGNATURE'];
if ($signature) {
$hash = "sha1=".hash_hmac('sha1', file_get_contents("php://input"), $secret);
if (strcmp($signature, $hash) == 0) {
echo shell_exec("cd {$path} && /usr/bin/git reset --hard origin/master && /usr/bin/git clean -f && /usr/bin/git pull 2>&1");
exit();
}
}
http_response_code(404);
?>
@Luc45 thank you for the suggestion, it worked and was quite helpful !! 🙌
In addition, on my remote server, I have added a little line to the /etc/sudoers
file to allow the webserver user (usually www-data
) to execute /usr/bin/git
as the user that owns my repo files 😉
Here is my example: www-data ALL = (repo_owner) NOPASSWD : /usr/bin/git
Always be cautious when running shell commands from web scripts backpack battles for security reasons. Sanitize inputs, restrict access, and log activities to avoid potential vulnerabilities.
This seems to be the bare minimum required to get a GitHub post-receive hook up and running with PHP on a webserver, to facilitate automatic site updates with group collaboration on a small static site.
I had to create a private/public key pair, without passphrase. The public key gets added in GitHub as a "deploy key" while the private key gets saved as
/var/www/.ssh/id_rsa
. I also didsudo touch /var/www/.ssh/known_hosts && sudo chmod www-data /var/www/.ssh/known_hosts
, then ransudo -u www-data git pull
from the command line to update theknown_hosts
file.(I think that's it)
Have any improvements? Let me know!