Skip to content

Instantly share code, notes, and snippets.

@anthx
Forked from oxguy3/deploy.php
Last active May 26, 2019 08:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anthx/a949626ac3fbe5794db0f6508ad218e7 to your computer and use it in GitHub Desktop.
Save anthx/a949626ac3fbe5794db0f6508ad218e7 to your computer and use it in GitHub Desktop.
Script used to automatically deploy from GitHub to a cPanel shared hosting server

deploy.php

This is the script @oxyguy3 wrote to deploy all commits to the master branch on GitHub onto his shared hosting cPanel server for his site. Unlike the original script I forked off, I could run shell_exec on my host so removed all the SSH stuff.

I also took care to validate the secret that GitHub passes along to prevent anyone else from activating the webhook. This is something I notice a lot of the other variations of this script I've found via googling neglect to do, but it seems like a good idea so I went for it.

Installation

First, you need to put deploy.php on your server, somewhere where it's accessible to the public (I've only tested putting it right at /public_html/deploy.php, but I can't think of any reason you couldn't rename it or put it in a subdirectory). At the top of the script is a series of define() statements -- you will need to change most of these to suit your setup (they all have comments describing what they do).

You'll need to create a webhook in the settings for your repo on GitHub. Set the Payload URL to the URL of this script (i.e. "http://example.com/deploy.php"), set the Content type to "application/json", and set the Secret to the same string of random characters that you set GITHUB_SECRET to in deploy.php. Check the radio box for "Just the push event" and then save the webhook.

You also need to have already cloned your repository into ~/public_html on the cPanel server. You can do this by manually SSHing in to the server from your local machine and running the git clone command.

I think that covers it all? Tweet me @anthc if you have any issues.

<?php
/**
* deploy.php by Hayden Schiff (oxguy3) Forked by Anthony Carrick (anthx)
* Available at https://gist.github.com/oxguy3/70ea582d951d4b0f78edec282a2bebf9
*
* No rights reserved. Dedicated to public domain via CC0 1.0 Universal.
* See https://creativecommons.org/publicdomain/zero/1.0/ for terms.
*/
// random string of characters; must match the "Secret" defined in your GitHub webhook
define('GITHUB_SECRET', 'qwertyuiop1234567890');
// name of the git branch that you're deploying
define('GITHUB_BRANCH', 'master');
// your email address, where you'll receive notices of deploy successes/failures
define('EMAIL_RECIPIENT', 'johndoe@example.com');
// domain of your website
define('SITE_DOMAIN', 'example.com');
// END OF CONFIGURATION OPTIONS
/**
* Convenience function for sending emails
*
* If you want to disable email sending, just replace the content of this
* function with "return true;".
*/
function sendEmail($success, $message)
{
$headers = 'Content-type: text/plain' . "\r\n" .
'From: admin@'.SITE_DOMAIN;
$subject = '['.SITE_DOMAIN.'] ';
if ($success) {
$subject .= 'Deploy success';
} else {
$subject .= 'Deploy failure';
$headers .= "\r\n" .
'X-Priority: 1 (Highest)' . "\r\n" .
'X-MSMail-Priority: High' . "\r\n" .
'Importance: High';
}
return mail(
EMAIL_RECIPIENT,
$subject,
$message,
$headers
);
}
try {
$signature = $_SERVER['HTTP_X_GITHUB_EVENT'];
if (is_null($signature) || $signature != 'push') {
header('HTTP/1.0 400 Bad Request');
die('go away');
}
$payload = file_get_contents('php://input');
// get the signature out of the headers and split it into parts
$signature = $_SERVER['HTTP_X_HUB_SIGNATURE'];
$sigParts = explode('=', $signature);
if (sizeof($sigParts) != 2) {
throw new Exception('Bad signature: wrong number of \'=\' chars');
}
$sigAlgo = $sigParts[0];
$sigHash = $sigParts[1];
// verify that the signature is correct
$hash = hash_hmac($sigAlgo, $payload, GITHUB_SECRET);
if ($hash === false) {
throw new Exception("Unknown signature algo: $sigAlgo");
}
if ($hash != $sigHash) {
throw new Exception("Signatures didn't match. Ours: '$hash', theirs: '$sigHash'.");
}
// read the payload
$data = json_decode($payload);
if (is_null($data)) {
throw new Exception('Failed to decode JSON payload');
}
// make sure it's the right branch
$branchRef = $data->ref;
if ($branchRef != 'refs/heads/'.GITHUB_BRANCH) {
die("Ignoring push to '$branchRef'");
}
// execute git pull
$output = shell_exec('cd ~/public_html/ && git pull');
$mailBody = "GitHub payload:\r\n"
. print_r($data, true)
. "\r\n\r\n"
. "Output of `git pull`:\r\n"
. $output
. "\r\n"
. 'That\'s all, toodles!';
$mailSuccess = sendEmail(true, $mailBody);
} catch (Exception $e) {
$mailSuccess = sendEmail(false, strval($e));
}
if(!$mailSuccess) {
header('HTTP/1.0 500 Internal Server Error');
die('Failed to send email to admin!');
}
die("All good here!");
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment