views:

2020

answers:

8

I've heard the phrase "deploying applications" which sounds much better/easier/more reliable than uploading individual changed files to a server, but I don't know where to begin.

I have a Zend Framework application that is under version control (in a Subversion repository). How do I go about "deploying" my application? What should I do if I have an "uploads" directory that I don't want to overwrite?

I host my application through a third party, so I don't know much other than FTP. If any of this involves logging into my server, please explain the process.

A: 

It depends on your application and how solid the tests are.

Where I work everything gets checked into the repository for review and is then released.

Auto updating out of a repository wouldn't be smart for us, as sometimes we just check in so that other developers can pull a later version and merge there changes in.

To do what you are talking about would need some sort of secondary check in and out to allow for collaboration between developers in the primary check in area. Although I don't know anything about that or if its even possible.

There is also issues with branching and other like features that would need to be handled.

jim
Well, you could have a release tag, and a post-commit hook that only deploys revisions that have been tagged as stable. I.e. commit, branch, and tag all you like, but only deploy when the stable keyword is encountered.
Martijn Heemels
+6  A: 

I wouldn't recommend automatic updating. Just because your unit tests pass doesn't mean your application is 100% working. What if someone checks in a random new feature without any new unit tests, and the feature doesn't work? Your existing unit tests might pass, but the feature could be broken anyway. Your users might see something that's half-done. With automatic deployment from a check-in, you might not notice for a few hours if something made it live that shouldn't have.

Anyhow, it wouldn't be that difficult to get an automatic deployment going if you really wanted. You'd need a post-check-in hook, and really the steps would be:

1) Do an export from the latest check-in 2) Upload export to production server 3) Unpack/config the newly uploaded export

I've always performed the last steps manually. Generally it's as simple as SVN export, zip, upload, unzip, configure, and the last two steps I just alias a couple of bash commands together to perform. Then I swap out the root app directory with the new one, ensuring I keep the old one around as a backup, and it's good to go.

If you're confident in your ability to catch errors before they'd automatically go live, then you could look at automating that procedure. It gives me the jibbly-jibblies though.

zombat
I agree with your recommendation on automatic updating.However, I would replace your manual update process by some automatic process. The fewer steps, the less can go wrong. We do a dozen or so deployments a day, and have automated it as much as possible to reduce error. I can recommend Webistrano for this, which does mostly your steps, but automatically and much more flexibly. If your needs are simpler, a script that uses rsync might be nice.
Martijn Heemels
+4  A: 

Here is an excellent article on using Subversion to deploy web projects — it answers many of your questions.

http://athleticsnyc.com/blog/entry/on-using-subversion-for-web-projects

James Skidmore
that is a good article!
Andrew
That article is mostly about the benefits of Subversion and version control, and barely touches deployment methods. It's definitely worth a read though.
Martijn Heemels
+1  A: 

This sort of thing is what you would call "Continous Integration". Atlassian Bamboo (cost), Sun Hudson (free) and Cruise Control (free) are all popular options (in order of my preference) and have support to handle PHPUnit output (because PHPUnit support JUnit output).

The deployment stuff can be done with a post build trigger. Like some other people on this thread, I would exercise great caution before doing automated deployments on checkin (and test passing).

Trey
+12  A: 

Automatic deploy + run of tests to a staging server is known as continuous integration. The idea is that if you check in something that breaks the tests, you would get notified right away. For PHP, you might want to look into Xinc or phpUnderControl

You'd generally not want to automatically deploy to production though. The normal thing to do is to write some scripts that automates the task, but that you still need to manually initiate. You can use frameworks such as Phing or other build-tools for this (A popular choice is Capistrano), but you can also just whisk a few shell-scripts together. Personally I prefer the latter.

The scripts themselves could do different things, depending on your application and setup, but a typical process would be:

  • ssh to production server. The rest of the commands are run at the production server, through ssh.
  • run svn export svn://path/to/repository/tags/RELEASE_VERSION /usr/local/application/releases/TIMESTAMP
  • stop services (Apache, daemons)
  • run unlink /usr/local/application/current && ln -s /usr/local/application/releases/TIMESTAMP /usr/local/application/current
  • run ln -s /usr/local/application/var /usr/local/application/releases/TIMESTAMP/var
  • run /usr/local/application/current/scripts/migrate.php
  • start services

(Assuming you have your application in /usr/local/application/current)

troelskn
+1  A: 

To handle uploads, the classic solution is to move the actual directory out of the main webspace, leaving it only for a fresh version to be checked out (as I do in the script below) and then using Apache to 'Alias' it back into place as part of the website.

Alias /uploads /home/user/uploads/

There are less choices to you if you don't have as much control of the server however.

I've got a script I use to deploy a given script to the dev/live sites (they both run on the same server).

#!/bin/sh

REV=2410
REVDIR=$REV.20090602-1027

REPOSITORY=svn+ssh://[email protected]/var/svn/website.com/trunk
IMAGES=$REVDIR/php/i
STATIC1=$REVDIR/anothersite.co.uk

svn export --revision $REV  $REPOSITORY $REVDIR

mkdir -p $REVDIR/tmp/templates_c
chown -R username: $REVDIR
chmod -R 777       $REVDIR/tmp $REVDIR/php/cache/
chown -R nobody:   $REVDIR/tmp $REVDIR/php/cache/ $IMAGES
dos2unix $REVDIR/bin/*sh  $REVDIR/bin/*php
chmod 755 $REVDIR/bin/*sh $REVDIR/bin/*php

# chmod -x all the non-directories in images
find $IMAGES -type f -perm -a+x | xargs -r chmod --quiet -x
find $STATIC1 -type f -perm -a+x | xargs -r chmod --quiet -x

ls -l $IMAGES/* | grep -- "-x"

rm dev && ln -s $REVDIR dev

I put the revison number, and date/time which is used for the checked-out directory name. The chmod's in the middle also make sre the permissions on the images are OK as they are also symlinked to our dedicated image server.

The last thing that happens is an old symlink .../website/dev/ is relinked to the newly checked out directory. The Apache config then has a doc-root of .../website/dev/htdocs/

There's also a matching .../website/live/htdocs/ docroot, and again, 'live' is another symlink. This is my other script that will remove the live symlink, and replace it with whatever dev points to.

#!/bin/sh
# remove live, and copy the dir pointed to by dev, to be the live symlink
rm live && cp -d dev live

I'm only pushing a new version of the site every few dats, so you might not want to be using this several times a day (my APC cache wouldn't like more than a few versions of the site around), but for me, I find this to be very much problem-free for my own deployment.

Alister Bulman
+1  A: 

check fredistrano, it's a capistrano clone works great (litle bit confusing installing but after all runs great)

http://code.google.com/p/fredistrano/

jipipayo
+4  A: 

At my webdev company we recently started using Webistrano, which is a Web GUI to the popular Capistrano tool.

We wanted an easy to use, fast deployment tool with a centralized interface, accountability (who deployed which version), rollback to previous versions and preferably free. Capistrano is well-known as a deployment tool for Ruby on Rails applications, but not centralized and targeted mainly to Rails apps. Webistrano enhances it with a GUI, accountability, and adds basic support for PHP deployment (use the 'pure file' project type).

Webistrano is itself a Ruby on Rails app, that you install on a development or staging server. You add a project for each of your websites. To each project you add stages, such as Prod and Dev.

Each stage can have different servers to deploy to, and different settings. Write (or modify) a 'recipe', which is a ruby script that tells capistrano what to do. In our case I just used the supplied recipe and added a command to create a symlink to a shared uploads dir, just like you mentioned.

When you click Deploy, Webistrano SSHs into your remote server(s), does an svn checkout of the code, and any other tasks that you require such as database migrations, symlinking or cleanup of previous versions. All this can be tweaked of course, after all, it's simply scripted.

We're very happy with it, but it took me a few days to learn and set up, especially since I wasn't familiar with Ruby and Rails. Still, I can highly recommend it for production use in small and medium companies, since it's proven very reliable, flexible and has saved us many times the initial investment. Not only by speeding up deployments, but also by reducing mistakes/accidents.

Martijn Heemels