Skip to content

Instantly share code, notes, and snippets.

@Stichoza
Last active November 3, 2017 13:52
Show Gist options
  • Save Stichoza/c4f0fddc09daef41abe7 to your computer and use it in GitHub Desktop.
Save Stichoza/c4f0fddc09daef41abe7 to your computer and use it in GitHub Desktop.
Laravel 4.2 Push-to-Deploy controller for GitHub webhooks
<?php
/**
* Deployment controller
*
* @author Stichoza <me@stichoza.com>
*/
class DeployController extends BaseController
{
const DEPLOY_SECRET_KEY = 'YOUR-GITHUB-WEBHOOK-SECRET-KEY-HERE';
private $deployStatus = false;
public static $sshLog = [];
private $errorMsg = 'Message not set';
private $payload = [];
private static $commands = [
'uptime',
'whoami',
'cd /var/www/stichoza.com',
'php artisan down',
'git reset --hard HEAD',
'git pull github master',
'php artisan migrate',
'php artisan up'
];
public static function log($str) {
self::$sshLog[] = [
'time' => microtime(1),
'output' => $str
];
}
/**
* This should be in laravel framework
*/
public static function getRequestBody() {
return @file_get_contents('php://input');
// File::get('php://input'); // This does not work!
}
/**
*
*/
private function checkHMAC() {
$sign = substr(Request::header('X-Hub-Signature', 'sha1=null'), 5);
$hmac = hash_hmac('sha1', self::getRequestBody(), self::DEPLOY_SECRET_KEY);
return $sign == $hmac;
}
private function fail($errorMsg) {
return $this->makeResponse(false, $errorMsg);
}
private function makeResponse($status = null, $errorMsg = null) {
if ($status !== null) $this->deployStatus = !!$status;
if (!empty($errorMsg)) $this->errorMsg = $errorMsg;
$response = ['deployed' => $this->deployStatus];
if (!empty($this->errorMsg)) {
$response['message'] = $this->errorMsg;
}
if (count(self::$sshLog)) {
$response['log'] = self::$sshLog;
}
return $response;
}
/**
* Deploy from github
*
* @access public
* @return array
*/
public function deploy() {
// Require HTTPS
if (!Request::secure()) return $this->fail('HTTPS required');
try {
$this->payload = json_decode(self::getRequestBody());
} catch (Exception $e) {
return $this->fail('Payload decoding failed.');
}
// Check HMAC signature
if (!$this->checkHMAC()) return $this->fail('Invalid secret key');
// Abort if pushed on nonmaster
if ($this->payload->ref != 'refs/heads/master')
return $this->fail('Not on master branch');
self::log('Deployment started');
// Execute commands and log output
SSH::into('capsule')->run(self::$commands, function($line) {
self::log(trim($line));
});
return $this->makeResponse(true, 'Deployment finnished');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment