Skip to content

Instantly share code, notes, and snippets.

@krmax44
Created August 13, 2020 19:50
Show Gist options
  • Save krmax44/571fa073ac5e9e0d7b8151fdf1074309 to your computer and use it in GitHub Desktop.
Save krmax44/571fa073ac5e9e0d7b8151fdf1074309 to your computer and use it in GitHub Desktop.
Continous deployment with Gitlab and PHP

Continous deployment with Gitlab and PHP

Use this script to auto-deploy Gitlab artifacts to your PHP server.

Usage

Set up a Gitlab CI pipeline that creates an artifact zip file, a webhook that is triggered by pipeline events set to index.php. The token should be a secure, random string and needs to be also set in config.php.

This project follows hack-driven development guidelines - please read the code thoroughly before deploying on production. No warranty provided, it might just rm -rf your life server 🤷

Tech Tip: use Gitlab's webhook testing feature to try out the deployment.

<?php
// Secret token defined in Gitlab Webhook settings
define('GITLAB_SECRET', '');
define('GITLAB_API_TOKEN', '');
define('GITLAB_REPO', '');
define('EMAIL_RECIPIENT', '');
define('SITE_DOMAIN', '');
?>
<?php
require('config.php');
if (!GITLAB_SECRET) {
die('Configuration error.');
}
function sendEmail($success, $message)
{
$headers = 'Content-type: text/plain' . '\r\n' .
'From: cd@'.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
);
}
function downloadFile($buildId) {
// File to save the contents to
$fp = fopen('staging/archive.zip', 'w+');
$url = 'https://gitlab.com/api/v4/projects/' . urlencode(GITLAB_REPO) . '/jobs/' . $buildId . '/artifacts';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Private-Token: ' . urlencode(GITLAB_API_TOKEN)
));
$data = curl_exec($ch);
curl_close($ch);
fclose($fp);
}
try {
$token = $_SERVER['HTTP_X_GITLAB_TOKEN'];
if ($token !== GITLAB_SECRET) {
header('HTTP/1.0 403 Forbidden');
die('Invalid token.');
}
$payload = file_get_contents('php://input');
// read the payload
$data = json_decode($payload);
if (is_null($data)) {
throw new Exception('Failed to decode JSON payload');
}
print_r($data);
// make sure it's a pipeline event
if ($data->object_kind !== 'pipeline') {
die('Ignoring event.');
}
// get the build id
$buildId = $data->builds[0]->id;
if (!$buildId) {
throw new Exception('Invalid build ID');
}
mkdir('staging');
mkdir('staging/files');
// download artifact
downloadFile($buildId);
// unzip artifact
$zipArchive = new ZipArchive();
$result = $zipArchive->open('staging/archive.zip');
if ($result === true) {
$zipArchive ->extractTo('staging/files');
$zipArchive ->close();
} else {
throw new Exception('Failed to unzip archive');
}
$g = glob('../**');
// delete old files
$leave_files = array('.htaccess', '_ci', '.well-known');
foreach (glob('../**') as $file) {
$base = basename($file);
if (!in_array($base, $leave_files)) {
shell_exec('rm -r ' . escapeshellarg($file));
}
}
// move new files
shell_exec('mv staging/files/dist/** ../');
// delete archive
unlink('staging/archive.zip');
$mailBody = 'Gitlab payload:\r\n'
. print_r($g, true)
. '\r\n\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('An error occured.');
}
die('Success.');
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment