DevOps Zone is brought to you in partnership with:

Matthew is a Linux Consultant and Systems Administrator specialising in removing human error from configuration and deployment through the use of automation. He has supported systems of all sizes, from small businesses to home entertainment and major cloud providers. Matthew is a DZone MVB and is not an employee of DZone and has posted 9 posts at DZone. You can read more from them at their website. View Full User Profile

"Murder" for Fun and Profit - Deploying a PHP App

02.22.2012
| 5211 views |
  • submit to reddit

Deploying web applications can be a real nightmare at times, especially when you have numerous SVN repositories of code which all link together when installed on the server to create your application.

I’ve started using Murder to try and work around the headaches and apart from a very small issue (which I’ll discuss at the end!) it’s working perfectly.

I’m not going to document a “Beginners Guide” here – there are plenty online including ones for PHP Applications and the documentation on GitHub is excellent – instead I’m going to disclose a few hints/tips that I picked up in the first two days of usage which could help you deploy any web application from SVN.

I usually use git (and github) for everything, however our in-house SCM at $DAYJOB is SVN, so that’s what we’ll be referencing here.

Checking out a specific branch

The repo layout that I’m using as an example has the following structure:

MyCoolWebApp
|
\--trunk
\--releases
    |
    \-- Release-<major>.<minor>
\--tags

Based on an excellent post by Paul Gross I’ve updated my deploy.rb file to have the following at the top:

set :repository_root, "#{scm_uri}/#{application}"
set(:release) {
    Capistrano::CLI.ui.ask("Release Version to deploy (or type 'trunk' to deploy from trunk): ")
}
set(:repository) {
    (release == "trunk") ? "#{repository_root}/trunk" : "#{repository_root}/releases/Release-#{release}"
}

I then put the following at the top of my Capfile:

# Deploy Variables:
set :scm_uri, "http://svnserver/svn" # The URI of the SCM server (http://server/svn or git://server etc)
set :application, "mycoolwebapp" # The name of the application (also doubles as the repository name

This means that when I run “cap deploy” it asks me which version I want to publish.  I can type the number (“1.5″ or “3.6″ for example) and it checks out and deploys http://svnserver/svn/mycoolwebapp/release/Release-1.5.

Version Dependencies

One of our repos contains a number of libraries which are relied on by other applications.  This presents an interesting issue where if we upload an app which requires a newer version of the libraries than the ones currently deployed, we find our shipment of fail.  Thankfully we have a version file in the Zend application/configs directory which contains the version number of the currently deployed libraries.

To make use of this I created some custom code in the deploy.rb file as follows:

namespace :deploy do
    desc <<-DESC
Checks the latest version of the libraries
to make sure we're not deploying our code
onto a platform which is not prepared for it
DESC
    task :checkdeps do
        required_libs.each do | appname,version |
            current_version = capture("cat /var/www/#{appname}/application/config/version").strip()
            if version.to_f() > current_version.to_f() then
                error = CommandError.new("Deployed version of #{appname} (#{current_version}) does not match required version (#{version})")
                raise error
            end
        end
    end
end

and then in the Capfile:

# Set the dependencies for this application (format: 'application' => 'version number')
set :required_libs, {'libs' => '0.2'}

#
# Other stuff goes here...
#

#Check all dependencies before setting up and deploying
before 'deploy:setup', 'deploy:checkdeps'
before 'deploy', 'deploy:checkdeps'

So if /var/www/libs/application/configs/version contains a number greater than the version that we know we need for this application, it will deploy.  If the ‘libs’ version is lower than the one required for this application, Capistrano aborts the deployment.

The Issue…

One of the issues that I have encountered with Murder (and I’m still not 100% sure on how to fix it!) is that when you run “cap deploy” with Murder enabled it retains the .svn directories.  This is not a good thing and is something which appears to be avoided by the “:deploy_via :copy” which Murder appears to inherit, however Murder doesn’t “svn export” like “:copy” does, it performs an “svn co” for some reason.

I’m hoping to resolve this soon and as soon as I do, I’ll send a pull request to @lg.

Apart from “the issue”, I’ve found that Capistrano is massively powerful and very quick to pick up, although as with many things I feel it could take some time to master…

Source:  http://www.threedrunkensysadsonthe.net/2011/04/murder-for-fun-and-profit/

Published at DZone with permission of Matthew Macdonald-wallace, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags: