6
votes

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?

10

10 Answers

8
votes

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.

6
votes

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.

5
votes

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.

2
votes

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>
1
votes

Try http://svn2ftp.com - none of the project management bulk, you can just simply setup SVN repositories which will automatically sync to any number of S/FTP accounts on each commit.

0
votes

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.

0
votes

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.

0
votes

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 :)

0
votes

This site shows you how to configure Subversion to do exactly what you're looking for. http://www.itforeveryone.co.uk/svn2web.html

-2
votes

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