tags:

views:

1567

answers:

6

I work at a small php shop and I recently proposed that we move away from using our nas as a shared code base and start using subversion for source control.

I've figured out how to make sure our dev server gets updated with every commit to our development branch... and I know how to merge into trunk and have that update our staging server, because we have direct access to both of these, but my biggest question is how to write a script that will update the production server, which we many times only have ftp access to. I don't want to upload the entire site every time... is there any way to write a script that is smart enough to upload only what has changed to the web server when we execute it (don't want it to automatically be uploading to the production enviroment, we want to execute it manually)?

Does my question even make sense?

+1  A: 

It doesn't sound like SVN plays well with FTP, but if you have http access, that may prove sufficient to push changes using svnsync. That's how we push changes to our production severs -- we use svnsync to keep a read-only mirror of the repository available.

Frank Farmer
What if the server isn't running subversion?
Boushley
A: 

I'm going to make an assumption here and say you are using a post-commit hook to do your merging/updating of your staging server. This may work, but I would strongly recommend you look into a Continuous Integration solution. The following are some that I am aware of:

  1. Xinc - http://code.google.com/p/xinc/ (PHP Specific)
  2. CruiseControl - http://cruisecontrol.sourceforge.net/ (Wildly popular.) PHP integration made possible with http://phpundercontrol.org/about.html
  3. Hudson - [https://hudson.dev.java.net/] (Appears to be Java based, but allows for plugins/extensions)
Jordan S. Jones
What would be the benefit of using one of these tools over the post commit tool that I have set up?
Boushley
+2  A: 

Basically, your issue is that you can't use subversion on the production server. What you need to do is keep, on a separate (ideally identically configured) server a copy of your production checkout, and copy that through whatever method to the production server. You could think of this as your staging server, actually, since it will also be useful for doing final tests on releases before rolling them out.

As far as the copy goes, if your provider supports rsync, you're set. If you have only FTP you'll have to find some method of doing the equivalant of rsync via FTP. This is not the first time anybody's had that need; a web search will help you out there. But if you can't find anything, drop me a note and I'll look around myself a little further.

EDIT: Hope the author doesn't mind me adding this, but I think it belongs here. To do something approximately similar to rsync with ftp, look at weex http://weex.sourceforge.net/. Its a wrapper around command line ftp that uses a local mirror to keep track of whats on the remote server so that it can send only changed files. Works great for me.

Curt Sampson
And especially thanks for the edit... I had been looking around for something that worked with subversion but I guess I just needed something to sync over ftp... good point, thanks!
Boushley
Ben, I'm very pleased you added that.
Curt Sampson
A: 

LFTP is capable of synchronizing directories over ftp.

Gleb
+1  A: 

I use the following solution. Just install the SVN client on your webserver, and attach this into a privately accessible url:

 <?php

    // make sure you have a robot account that can't commit ;) 
    $username = Settings::Load()->Get('svn', 'username');
    $password = Settings::Load()->Get('svn', 'password');
    $repos = Settings::Load()->Get('svn', 'repository');

    echo '<h1>updating from svn</h1><pre>';
    // for secutity, define an array of folders that you do want to be synced from svn. The rest should be skipped.
    $svnfolders = array(    'includes/' ,'plugins/' ,'images/' ,'templates/', 'index.php' => 'index.php');

    if(!empty($_GET['justthisone']) && array_search($_GET['justthisone'], $svnfolders) !== false){ // you can also just update one of above by passing it to $_GET
        $svnfiles = array($_GET['justthisone']);
    }

    foreach($svnfiles as $targetlocation)
    {   
        echo system("svn export --username={$username} --password {$password} {$repos}{$targetlocation} ".dirname(__FILE__)."/../{$targetlocation} --force");
    }

    die("</pre><h1>Done!</h1>");
SchizoDuckie
http://www.php.net/escapeshellarg
troelskn
A: 

Just an idea:

You could hold a revision of your project on a host you have access to and where subversion is installed. This single revision reflects the production server's version. You could now write a PHP script that makes this repository update over svn and then find all files that have been changed since the rep was updated. These files you can upload.

Such a script could look like this:

$path = realpath( '/path/to/production/mirror' );
chdir( $path );

$start = time();
shell_exec( 'svn co' );

$list = array();
$i = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $path ), RecursiveIteratorIterator::SELF_FIRST );

foreach( $i as $node )
{

    if ( $node->isFile() && $node->getCTime() > $start )
    {

        $list[] = $node->getPathname();

    } 

    // directories should also be handled

}

$conn = ftp_connect( ... );

// and so on

Just as it came to my mind.

okoman
If I can't find something that does it automatically, this will be great! Thanks a ton!
Boushley