views:

1025

answers:

8

We are having a hard time keeping Subversion and FTP in-sync. Sometimes we forget to commit changes and just push them to the web server, we have .svn folders scattered throughout our web server, some things exist one place and don't exist in the other, etc.

I want to take the time to fix this, today. What is the solution? Is there a way that SVN can be linked to our web server, so that we can commit to both the repository and to the web server via FTP? Should we ask our web host for some other system that would better sync with the SVN repository? How do we enforce that the repository and the web server are both in sync? How do we remove the .svn folders?

Just as the title says, how can we keep our SVN repository and our web server in sync?

A: 

Setup a post-commit hook that updates the FTP and exclusively use SVN for changes. This way when changes are committed, your web server will be updated.

This assumes the web server is a staging server. See comments for details.

Ben S
This is generally a bad idea as if you commit broken code to the repo it's going to be live immediately, or shortly there after. This would be a 'bad thing'.
Bryan McLemore
Or perhaps combining this with @Bryan McLemore's answer, set up a post-commit hook that triggers a svn update on the server.. Hmm...
Ricket
No it wouldn't be a bad thing. You should be updating a staging server. Use tags for stable releases and push those to the production server manually.
Ben S
Yes tagging on releases is a good idea. I'd rather not assume he was referring to a staging server.
Bryan McLemore
Yeah, I realized after a couple of downvotes that my assumption was bad :\
Ben S
+2  A: 

What I do on my server is have it be a checkout of the code on the server.

So instead of using ftp to push things to the server, I just log on to it and run an svn up. By doing this manually this way you gain several benefits, including the ability to roll back in the event of buggy code.

I'd also recommend using a db migration system (assuming you're using a database). That'll allow you to easily roll back db schema changes to make sure that your code will continue to work in the event of a rollback.

Combining these with a tool similar to Fabric or Capistrano, would give you a very robust and powerful deployment system.

Note about DVCS:

Some people here have mentioned using a distributed vcs. Some of the most popular examples of these are git and mercurial (there are several others).

Both of these have a different usage pattern than svn, but that doesn't really apply to this question directly. The biggest gain you could have there is that if you do tags for each push to the live server the cost of doing so is miniscule compared to the traditional tagging pattern for svn.

If you wished to expirement with either of those GitHub and BitBucket both offer free repository hosting for git and mercurial respectively.

That being said I am I huge proponent of using a dvcs and my personal preference is mercurial.

Bryan McLemore
If you do this, make sure to deny access to SVN meta data or you might introduce a security problem. More info: http://www.smashingmagazine.com/2009/09/25/svn-strikes-back-a-serious-vulnerability-found/
Daniel Hepper
This is true. I don't always have to deal with that since most of my websites are in python and as a result the raw files are never set up in a way in which they could be served.
Bryan McLemore
A: 

This looks like a problem tailor-made for a distributed revision control system.

T.E.D.
Why? Can you explain a little more?
Ricket
I don't see how being distributed has anything to do with it. Several people have provided answers that work with svn or any other unpopular and uncool regular old style, not the coolest, hippest git repository.
Tim
@Ricket: I added a note to my answer about DVCSs
Bryan McLemore
+5  A: 

You wouldn't want to commit changes to a live web server without any form of testing, would you?

Short answer: by performing a fresh checkout (preferably on a central server) and copying only the bits required to run the app.

I would recommend setting up continous integration, where your build server is responsible for retrieving the latest sources from the Subversion repository, performing a build and preparing the deployment packages for various environments (test/staging) and potentially FTP'ing it up to the production box once you're happy with the deployed changes in your test or staging environment.

That's the only solid way of ensuring that changes WILL have to be committed (no-brainer I know, but seems to be uncertain in your scenario) or otherwise they simply will not end up in the deployment. It enforces the process of good release management, not to forget you can add all sorts of other wonderful automation things to your build server like unit testing and functional testing.

Wim Hollebrandse
I'd be worth noting that a continuous integration cycle wouldn't always make the best sense. Many web languages don't even support a build phase. Having a script that crawls a testing server finding errors could be invaluable for some languages though.
Bryan McLemore
Sure, but you can trivially replicate such build server behavior by at least having a central box that performs regular checkouts and copying the appropriate artifacts plus relevant configuration files to a drops folder, where they are ready to be picked up and can be FTP'd. It doesn't need to be an expensive, overengineered solution. It could be several batch files. But it would be 100% in-line with the 'Continuous Integration' concept.
Wim Hollebrandse
This is true, and automating as many sanity checks as possible, regardless of form, is essential.
Bryan McLemore
A: 

The best way I found to do this is to ensure that nothing uncommitted can escape to the server - this is a loophole you have to fix first.

Then, set up a local checkout of the parts of your repository that you want to sync and use rsync to push the data to the server (FTP really isn't that useful in this context). rsync allows you to exclude files and directories so use that facility to ensure that the .svn directories do not get synced.

Timo Geusch
+2  A: 

I would suggest that before implementing below that you utilize a test environment where you can FTP directly, then to push live, commit that version of files and allow this task to run.

From tigris:

This is done all the time, and is easily accomplished by adding a post-commit hook script to your repository. Read about hook scripts in Chapter 5 of the book. The basic idea is to make the "live site" just an ordinary working copy, and then have your post-commit hook script run 'svn update' on it.

In practice, there are a couple of things to watch out for. The server program performing the commit (svnserve or apache) is the same program that will be running the post-commit hook script. That means that this program must have proper permissions to update the working copy. In other words, the working copy must be owned by the same user that svnserve or apache runs as -- or at least the working copy must have appropriate permissions set.

If the server needs to update a working copy that it doesn't own (for example, user joe's ~/public_html/ area), one technique is create a +s binary program to run the update, since Unix won't allow scripts to run +s. Compile a tiny C program:

#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
    execl("/usr/local/bin/svn", "svn", "update", "/home/joe/public_html/",
    (const char *) NULL);
    return(EXIT_FAILURE);
}

... and then chmod +s the binary, and make sure it's owned by user 'joe'. Then in the post-commit hook, add a line to run the binary.

If you have problems getting the hook to work, see "Why aren't my repository hooks working?".

Also, you'll probably want to prevent apache from exporting the .svn/ directories in the live working copy. Add this to your httpd.conf:

# Disallow browsing of Subversion working copy administrative dirs.
<DirectoryMatch "^/.*/\.svn/">
    Order deny,allow
    Deny from all
</DirectoryMatch>
Tegeril
+1  A: 

Springloops does exactly what you require. Give it a go. It's SVN combined with FTP. You work on you local working copy, then commit changes to repository, then via Springloops deploy them selected revision to any server (Staging or Production) via FTP.

Chris
A: 

I was just about to suggest Springloops when i scrolled down and saw Chris's suggestion. I've been using SpringLoops for the past couple of months and absolutely love it.

You can set up FTP details for staging and prod servers for each repository. Then you can publish to those servers via FTP, specifying the revision number to deploy.

Something I really like about this is that i can see at what version each server is via the deploy page in Springloops. And with everything being deployed through Springloops, you know that this is accurate.

I've actually been hunting for a solution that is a little more than just a SVN repository.. something with integrated ticketing, wiki, and timekeeping. I like Bitbucket alot, but it doesnt have the FTP deployment feature of Springloops, which rules it out for me unfortunately. For now i'll be sticking with Springloops until another service can offer FTP Deployment.

Why is FTP deployment so important to me i hear some people mumbling under their breaths.. i'll gladly tell you: I deploy to various different servers. Some are dedicated boxes, some cloud hosted VMs, and some shared hosting. I dont want to have to maintain a separate deployment methodology for each one, so the one deployment method common to all is FTP. Springloops sits really nicely between my source code and my servers. That's why :)

Gregorius
Ah, forgot to mention, Beanstalk does FTP Deployment from SVN repository too. Oh, and Beanstalk offers Git hosting if that's your preference.
Gregorius