Skip to content

Instantly share code, notes, and snippets.

@jeffam
Last active August 29, 2015 14:19
Show Gist options
  • Save jeffam/53069312ffbfc252531a to your computer and use it in GitHub Desktop.
Save jeffam/53069312ffbfc252531a to your computer and use it in GitHub Desktop.
Drupal Branch Deployer for Task Train

Sample Per-branch Drupal Deployment Scripts for Task Train

This is some (rough) boilerplate code for automated deployments of feature branches in a Drupal project. It's kind of like a poor man's http://tugboat.qa/

Requirements:

Installation

  • Create a mysql user with database create/drop priviledges
  • Place deploy.php into scripts.d/gitdeploy (see https://github.com/singlebrook/task_train#creating-task-scripts)
  • Edit deploy.php to update the db_user and db_pass settings
  • Create a bare clone of your code repo to your web/db server and add the post-receive hook
  • Add that clone as a new remote to your local repo

Usage

If all goes well, new drupal deployments will be created at [BRANCHNAME].yourwildcarddomain.com when you push new branches to the remote repo with the post-receive hook.

Pushing existing branches will simply clear caches and revert features.

Deleting remote branches will tear down the test environments.

<?php
/**
* Required arguments:
* --name=task_name
* --branch=branch_name
* --action=create|update|delete
*/
$args = getopt('', array(
'name:',
'branch:',
'action:',
'repo:',
));
if (count($args) !== 4) {
print 'Incorrect number of arguments.' . PHP_EOL;
exit(1);
}
// Ensure that the branch name is a valid git reference name.
passthru('git check-ref-format refs/heads/' . $args['branch'], $exitcode);
if ($exitcode !== 0) {
print 'Invalid git reference name for branch.' . PHP_EOL;
exit(2);
}
$name = $args['name'];
$action = $args['action'];
/*
* Connect as existing mysql user with CREATE USER, CREATE, DROP, GRANT OPTION PRIVILEGES
*/
$conf = array(
'db_user' => 'deploy_auto',
'db_pass' => 'password',
'db_host' => 'localhost', // '127.0.0.1'
'vhost_dir' => '/srv/www/',
);
$branch = array(
'name' => $args['branch'],
'repo' => $args['repo'], // escapeshellarg() ?
);
/**
* MySQL has the following limits:
* - user names: to 16 characters
* - database names: 64 chars, [0-9,a-z,A-Z$_] (http://dev.mysql.com/doc/refman/5.0/en/identifiers.html)
*/
$branch['hostname'] = preg_replace('/[^0-9a-zA-Z]/', '-', $branch['name']) . '.wildcard.example.com';
$branch['db_name'] = substr('depl_' . preg_replace('/[^0-9a-zA-Z\$_]/', '_', $branch['name']), 0, 64);
$branch['db_user'] = 'depl' . substr(sha1($branch['name']), 0, 12);
$branch['db_pass'] = md5($branch['name']);
$branch['work_tree'] = $conf['vhost_dir'] . $branch['hostname'];
if (function_exists($action)) {
call_user_func($action, $branch, $conf);
}
else {
print 'Incorrect action param.' . PHP_EOL;
exit(2);
}
function create($branch, $conf) {
printf('Creating %s...' . PHP_EOL, $branch['hostname']);
printf('Adding "%s" database...', $branch['name']);
echo $db_script = <<<EOL
mysql -u{$conf['db_user']} -p{$conf['db_pass']} -e "
CREATE DATABASE {$branch['db_name']};
CREATE USER '{$branch['db_user']}'@'{$conf['db_host']}' IDENTIFIED BY '{$branch['db_pass']}';
GRANT ALL ON {$branch['db_name']}.* TO '{$branch['db_user']}'@'{$conf['db_host']}';
FLUSH PRIVILEGES;"
EOL;
passthru($db_script, $exitcode);
print ($exitcode == 0 ? 'DONE' : 'FAILED') . PHP_EOL;
printf('Checking out branch to %s...', $branch['work_tree']);
mkdir($branch['work_tree']);
echo $git_cmd = "git --git-dir='{$branch['repo']}' --work-tree='{$branch['work_tree']}' checkout -f {$branch['name']}";
passthru($git_cmd, $exitcode);
print ($exitcode == 0 ? 'DONE' : 'FAILED') . PHP_EOL;
printf('Installing Standard profile...' . PHP_EOL);
echo $drush_cmd = "drush -y --root='{$branch['work_tree']}/docroot/' site-install standard --db-url=mysql://{$branch['db_user']}:{$branch['db_pass']}@{$conf['db_host']}/{$branch['db_name']} --site-name='{$branch['name']} Test CALS Site' --account-pass=testing";
passthru($drush_cmd, $exitcode);
print ($exitcode == 0 ? 'DONE' : 'FAILED') . PHP_EOL;
printf('Disabling performance optimizations...' . PHP_EOL);
passthru("drush -y --root='{$branch['work_tree']}/docroot/' vset preprocess_js 0", $exitcode);
passthru("drush -y --root='{$branch['work_tree']}/docroot/' vset preprocess_css 0", $exitcode);
passthru("drush -y --root='{$branch['work_tree']}/docroot/' vset cache 0", $exitcode);
// Adjust rewritebase in .htaccess
`/bin/sed -i.bak 's| # RewriteBase /$| RewriteBase /|' {$branch['work_tree']}/docroot/.htaccess`;
// Allow the web server to write to the files directory.
`/bin/chmod a+rwx {$branch['work_tree']}/docroot/sites/default/file`;
// TODO: Email site admin a one time login link. (Or let drush do it.)
// `drush --root={$branch['work_tree']}/docroot/ -l {$branch['hostname']} uli`
printf('Done!' . PHP_EOL);
}
function update($branch, $conf) {
printf('Updating %s...' . PHP_EOL, $branch['hostname']);
passthru("chmod -R +w {$branch['work_tree']}/docroot/sites/default/");
printf('Checking out branch to %s...', $branch['work_tree']);
passthru("git --git-dir='{$branch['repo']}' --work-tree='{$branch['work_tree']}' checkout -f {$branch['name']}", $exitcode);
print ($exitcode == 0 ? 'DONE' : 'FAILED') . PHP_EOL;
// Adjust rewritebase in .htaccess
`/bin/sed -i.bak 's| # RewriteBase /$| RewriteBase /|' {$branch['work_tree']}/docroot/.htaccess`;
printf('Reverting features...' . PHP_EOL);
echo $drush_cmd = "drush -y --root='{$branch['work_tree']}/docroot/' fra";
passthru($drush_cmd, $exitcode);
print ($exitcode == 0 ? 'DONE' : 'FAILED') . PHP_EOL;
printf('Running database updates...' . PHP_EOL);
echo $drush_cmd = "drush -y --root='{$branch['work_tree']}/docroot/' updb";
passthru($drush_cmd, $exitcode);
print ($exitcode == 0 ? 'DONE' : 'FAILED') . PHP_EOL;
printf('Done!' . PHP_EOL);
}
function delete($branch, $conf) {
printf('Deleting %s...' . PHP_EOL, $branch['hostname']);
printf('Removing "%s" database...' . PHP_EOL, $branch['name']);
echo $db_script = <<<EOL
mysql -u{$conf['db_user']} -p{$conf['db_pass']} -e "
DROP DATABASE {$branch['db_name']};
DROP USER '{$branch['db_user']}'@'{$conf['db_host']}'";
EOL;
passthru($db_script, $exitcode);
print ($exitcode == 0 ? 'DONE' : 'FAILED') . PHP_EOL;
// Moving for now. Can't really hurt to leave the git checkout around and rm
// commands in scripts spook me.
printf('Removing git checkout at %s...' . PHP_EOL, $branch['work_tree']);
rename($branch['work_tree'], '/tmp/' . $branch['hostname'] . '.' . uniqid());
printf('Done!' . PHP_EOL);
}
exit(0);
#!/bin/bash
# Submits feature branches to the task manager. Modify as needed, ensure that
# it is executable, and place in .git/hooks/
repo=`pwd`
# The post-receive hook receives parameters on stdin. We call them oldrev,
# newrev, and refname.
while read oldrev newrev refname
do
refname_short=${refname#refs/heads/}
#echo "DEBUG: oldrev, newrev, and refname:"
#echo $oldrev
#echo $newrev
#echo $refname
# Example: Skip deployment of master branch.
#if [ "$refname" == "refs/heads/master" ]; then
# continue
#fi
# When adding a branch, oldrev = 0000000000000000000000000000000000000000
# When removing a branch, newrev = 0000000000000000000000000000000000000000
# When updating a branch, both oldrev and newrev are commit SHA references.
if [ "$oldrev" == "0000000000000000000000000000000000000000" ]; then
curl -sX POST "http://127.0.0.1:5800/task?name=gitdeploy&branch=$refname_short&action=create&repo=$repo"
elif [ "$newrev" == "0000000000000000000000000000000000000000" ]; then
curl -sX POST "http://127.0.0.1:5800/task?name=gitdeploy&branch=$refname_short&action=delete&repo=$repo"
else
curl -sX POST "http://127.0.0.1:5800/task?name=gitdeploy&branch=$refname_short&action=update&repo=$repo"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment