Twilio and Subversion: Have Phone, Will Deploy

Shawn CampbellA few weeks ago, I heard from Shawn Campbell that he was having problems using Twilio with Subversion. Initially, I thought he meant how he was storing and managing his source code, but I quickly figured out how wrong I was.

He had one of the most common problems out there: he works with a number of teams, so he has to deploy a lot of different code to a lot of different servers. Since deployment requires logging in, navigating to the proper directory, and running updates, it can be time consuming and disruptive.

So Shawn came up with a new solution: call the server and it deploys for him.

While he’s since developed a Version 3 (using Twilio Client no less!), I talked to him just after Version 2 was complete, so that’s what we’ll cover here.

Before we dive into the code, the most interesting thing to note is that this allows you to grant deployment access without granting server access. Now the only time someone needs to log in is at the initial installation time and to change the authorized users.

And now onto the code:

[php]
<?php
header("content-type: text/xml");
echo "<?xml version="1.0" encoding="UTF-8"?>n";
$authorized_users = array("+1NNNNNNNNNN");
$production_files = "/home/production_sites/";
$repository_location = "//var/svn/production_sites/";

if(!in_array($_REQUEST['From'], $authorized_users))
{
echo ("<Response><Reject/></Response>");
} else {
// snip for some explanation
[/php]

First off you should notice that since this is receiving a call, we don’t need our Account SID or Auth Token. Further, the main points of interest in this block are the variables:

  • $authorized_users – an array of phone numbers which are allowed to apply updates;
  • $production_files – the location on the server of the files to update;
  • $repository_location – the full SVN repository path.

The last few lines of code simply confirms that the incoming From number is in our $authorized_users array.

The key piece of this script is in his switch statement:

[php]
echo "<Response>";
switch($destination)
{
case ‘production_version’ :
?><Say>Checking the revision number of production</Say><?php
$revision_number = exec("svn info ".$production_files." | tail -7 | grep "Revision" | grep -v "Last"");
$revision_number = str_replace("Revision: ", "", $revision_number);
echo "<Say>REVISION NUMBER IS: ".$revision_number."</Say>";
break;
case ‘production_update’ :
$production_revision = svn_update($production_files);
echo "<Say>The updated revision number of production is ".$production_revision."</Say>";
break;
case ‘status’ :
$revision_number = exec("svnlook history ".$repository_location." | head -3 | tail -1");
$revision_number = str_replace("/","",$revision_number);
$revision_number = str_replace(" ","",$revision_number);

$revision_log = exec("svnlook log ".$repository_location);
$svn_author = exec("svnlook author ".$repository_location);
echo "<Say>master repository revision :".$revision_number."</Say>";
echo "<Say>Last author: ".$svn_author."</Say>";
echo "<Say>Last commit message: ".$revision_log."</Say>";
break;
default:
?>
<Gather action="subversion_update_menu.php?node=default" numDigits="1">
<Say>Welcome to the Subversion Server</Say>
<Say>For the production revision, press 1</Say>
<Say>For the production update, press 2</Say>
<Say>For the repository infomation, press 0</Say>
</Gather>
<?php
break;
}
[/php]

The different branches are simple:

  • the ‘default’ case does a simple Gather to collect the next step from the caller;
  • the ‘production_version’ case retrieves the current revision number from the deployed code but doesn’t change anything; and
  • the ‘status’ case retrieves the latest revision number from the repository but doesn’t change anything.

Using these, you can check on the current state without changing anything at all. If everything is as expected, the Caller can use the ‘production_update’ case to deploy the latest and greatest from their repository.

So how useful is this? In Shawn’s own words:

Where this was originally being billed at 0.25 hours, I am now able to get the same process completed in a matter of 3 minutes, now being billed at 0.05 hours.

Multiply that by a handful of deployments each day along with an oddball late night or “not sitting at your computer” update and suddenly deploying code is a little less annoying.

Something to think about:  How could you extend this code to deploy a specific revision of a Subversion repository? What problems would you have to overcome?

Don’t forget to visit Shawn’s site for the code and video demos of the whole Twilio/Subversion integration. His Version 3 of the tool comes with a simple config script that gets you going in under 15 minutes. Try it for your yourself!