Release early, Release often, A SVN/FTP Deployment Task
Posted on 22/11/06 by Felix Geisendörfer
Deprecated post
The authors of this post have marked it as deprecated. This means the information displayed is most likely outdated, inaccurate, boring or a combination of all three.
Policy: We never delete deprecated posts, but they are not listed in our categories or show up in the search anymore.
Comments: You can continue to leave comments on this post, but please consult Google or our search first if you want to get an answer ; ).
Warning: All of this is meant for CakePHP 1.2 which is still under heavy development. People are not recommended to use 1.2 so far unless they are very experienced with CakePHP and able to fix their problems them selfs. There will be no official support for the 1.2 branch before it's released and it might go through some major changes before that.
After recently releasing my experimental little testsuite called CakeTaster it is time for me to release the next project I've been working on. This one might be even more interesting for most people, as it's already pretty advanced. Nevertheless I consider this to be an experimental release, so plz don't depend on it quite yet ; ).
As the headline says, this time it's going to be my SVN/FTP Deployment Task written for the new Bake in CakePHP 1.2. It will not work with the Cake 1.1.x.x branch, and I currently do not have time to explain the procedure to work around this.
First of all let me explain what it does (or is supposed to do). The job of this task is to SYNC a given SVN repository with a remote folder of an FTP server. It provides functions to install, update, or delete this remote copy of your application. The install/update function also allow you to specifiy a revision you want to install or update to. This way you can roll back a recent update if you discover a problem, or simply take your app back in time for the fun of it ; ).
Sounds interesting? Time to get started. First of all download the code. Then directly copy all the folders over the ones of your application. Nothing should be overwritten, but it's your responsible to double check that. Once you are done with this, go to /app/config/deployment.php and start to edit this file. You should see something like this:
class AppDeployment extends BasicDeployment
{
var $ftpConfig = array('host' => 'playground.thinkingphp.org',
'connect' => 'ftp_connect',
'login' => 'user',
'password' => 'secret-pw',
'port' => '21',
'timeout' => '30',
'base_path' => '/',
'svn_file' => '/app/webroot/revision.txt');
var $ftpActions = array('chmod_777' => array('/app/tmp'));
var $svnConfig = array('url' => 'file:///C:/Repositories/project',
'login' => '',
'password' => '',
'path' => '/trunk');
// pluse some code I added to beautify the log output and set the php time limit to infinite
}
All you have to do is to fill in your FTP / SVN information and that's it. You're ready for the first little ride. Fire up your command line / shell and navigate to /cake/scripts/. Then type in the following command.
php -q bake2.php deploy install
Now you'll see that little shell of yours becoming very busy. It will export the latest version of your application from the SVN directory you specified into a temporary folder (If you see an error, please make sure the application can write to /app/tmp). After that it will login to the FTP server, upload all files, and finally recursively chmod the remote /app/tmp to 777.
Go ahead and make some changes to your application. Save them, commit them to svn. Then run this command:
php -q bake2.php deploy update
If everything is setup correctly, the task will contact the ftp server and download the revision file in order to know what revision is located on the remote server. After it knows this information it will diff this version vs. SVN:HEAD, checkout the modified files and upload (only) them in order to overwrite the old ones. It will also delete files that have been removed in the repository.
Alright, once you are finished jumping around your work place after enjoying this delightful deployment experience it's time to get a little fancier. (In case you hit a problem before that, leave a comment and I'll try to help you to get to the happy-jumping-around part). For a simple application the default deploy behavior will be all you ever need. But as we developers tend to create space ships whenever we are asked to do something sligthly more complex then printing "Hello World", here comes some freedom: The /app/config/deployment.php contains a class called AppDeployment which extends BasicDeployment. Functionality like install/update/uninstall are actual functions inside the BasicDeployment class. This means you can overwrite them.
Just take a look at the BasicDeployment::install() function, to get a better feel for how it works:
{
$remotePath = $this->ftpConfig['base_path'];
$tmpFolder = TMP.'svn';
$this->__deleteTmpFolder($tmpFolder);
if (!$this->__svnExport($Svn, $tmpFolder, $installRevision))
return false;
if (!$this->__svnCreateRevisionFile($Svn, $tmpFolder, $installRevision))
return false;
if (!$this->__ftpConnect($Ftp))
return false;
if (!$this->__ftpUploadDir($Ftp, $tmpFolder, $remotePath, true, false))
return false;
if (!$this->__ftpExecuteActions($Ftp, $remotePath))
return false;
$this->__ftpDisconnect($Ftp);
$this->__deleteTmpFolder($tmpFolder);
$this->log('Succesfully installed app at '.$this->ftpConfig['base_path'].' (Revision '.$this->__svnResolveRevision($Svn, $installRevision).').', 'info');
return true;
}
Now it's your turn. Try out the task, start playing around with it, and let me know what yout hink about it. I've been talking with the other devs and it's not out of question for this to become part of the CakePHP core. But to make this possible I need all the testing I can get, and as much feedback as you guys can give me ; ).
-- Felix Geisendörfer aka the_undefined
You can skip to the end and add a comment.
MattC: This is mostly ment for people deploying on shared hosts without remote access. However, there is another benifit of using a DeployTask: The ability to run custom scripts in order to modify files, the DB, etc. with each update.
It's like a version of capistrano that actually makes sense! Keep up the great work Felix.
Very useful, bake2 rocks
Thanks for the reply Felix. I look forward to the release of 1.2 - I'll definatly give this a try then. My only suggestiong would be to allow for multiple deployment servers. That way if I have a QA server I can use this to push the code there first, then if everything looks good there I could push the code to the production server.
looks very ingenious. nice one felix! i think many, perhaps even the majority of cake developers deploy to shared hosts. looking forward to trying this out on my next project.
MattC: You can add a beforeFilter that modifies the values of $this->ftpConfig / $this->svnConfig on demand in order to achieve this functionality. I might add native support for this at some point, but as the workaround is very easy, I don't consider it a main prirority right now.
RosSoft: You are alive ; ). I haven't heard or let's say read you in ages! I'm glad to see you around.
Felix Geisendorfer's Blog: Release early, Release often, A SVN/FTP Development Task...
...
This is going to be a huge time saver - thanks a lot for your efforts
What, is svn update broken? Talk about re-inventing the wheel.
Garbonzo: No it's not. I've just not gotten it to work via FTP so far ... ; ). Again: This is ment for sharing hosted enviornments, if you are lucky enough that your client is paying for dedicated hosting go ahead and use svn update via SSH.
i just feel like a fool right now..... wasted so much time trying to re create something you have already done, and it is here for me to consume!!!! now i can use your code to finish my job faster. i thinks i should say thank you.. for making my life a bit more easier... :)
i was looking for an simple solution to this problem though many heavy weight solutions exist i dislike them all.. they are to heavy for my little mind....
Nice work, Felix!
Hi Felix,
let me ask You something, please:
'The ability to run custom scripts in order to modify files, the DB, etc. with each update.'
- how looks intended implementation of this functionality, please? Am I wrong with simple (example)
if (file_exists(TMP.'distro'.DS.'update.php')) {
// parse above file against current revision.txt
// if necessary, do something
}
in bootstrap/beforeFilter ?
This may be dense, but what is this line "'svn_file' => '/app/webroot/revision.txt');" ?
Where does revision.txt come from?
poLK: AppDeployment extends BasicDeployment. This means you can overwrite functions in it to use your own ones. If you need to run the normal behavior first, you can simply do: parent::update() and so on.
TJ Singleton: The 'svn_file' is a file created by the Deploy script when uploading/updating your site on an FTP server. It contains the revision number of the currently uploaded files so when you 'update' the code next time, it knows what revision-diff to apply.
Hi Felix,
thanks for answer but I still don't understand how You can call some update procedures on live server by AppDeployment's code executed in terminal and accessing target site through FTP. I am responding to Your 2nd post here with mentioned 'ability to run custom scripts in order to modify files, the DB, etc' ;)
poLK: You can't ; ). The script is running locally and all procedures it might start run local as well. You can however use the script to connect to your remote DB server in order to update it and things like that - that's what I meant when writing about it.
[...] Bruno D. has spent quite some time researching alternatives to ANT deployment and posted his results in the comments. So if you don’t like my SVN deployment task for Cake 1.2, you might find his suggestionsuseful. [...]
Hi Felix.
Great work!!
But there's a problem if there is a new folder in the repository and he want to create this folder on ftp-server.
I tried to change persmissions on ftp-server, but no chance.
Any ideas?
Cheers, Daniel
Hey D.Pape: Dunno what's going on there, but one of the things on my high-priority-when-time list is to rewrite this upload thing completely but using some new CakePHP datasources stuff that is under development. Hope you can fix your problem temporarily until then.
hi felix.
it would be great if this thing will be fixed sometime, because this ftp-svn-deployment thing is very very nice and saved a lot of time!
prost, daniel
[...] this is just a quick update for the CakePHP 1.2 SVN/FTP Deployment task I released a while ago. It fixes a problem that would sometimes cause ‘Folder could not be created’ errors to show up even so the folder was successfully created via ftp. [...]
D.Pape: Here you go, see the trackback link above ; ).
Thanks Felix!! :o)
I will try it this evening.
Will you update this task code for supporting of last cake 1.2 release?
Yevgeny: Eventually, but it's not on my schedule for now.
I've closed comments on this post b/c it just attracted spam like crazy. If you need to post something let me know (felix@thinkingphp.org).
Hi Tim, Hi Felix,
I came across this post of yours when looking for a tool to do the deployment in a live server.
Your Site engaged me for more than an hour...
Checked out some PHP best practices posts by you, checked the about section and your profiles.. I also checked out PostTask.com...
I am impressed with both of you..
My Problem is as follows...
Suppose I am working on a Project which is Live.
I make changes to one or more files.
I then need to Browse to the respective folders for each of the files and copy-paste/drag-drop each file.
I have observed that even when copying one file some Visit requests for the pages which required that file fails..
can't include file blah-blah-blah file does not exist..
I was looking at a way so that all files are first copied to some folder in the Server and when done move all the necessary files top their respective locations at one go...
This Script might be useful for me... but I may not want to deploy the whole set of files that are there in the Repository..
Perhaps I can create a Branch for the Deployment purpose but I am not sure if this is the best solution..
Any hint for the Solution I am looking for???
This post is too old. We do not allow comments here anymore in order to fight spam. If you have real feedback or questions for the post, please contact us.
Just so I'm clear: The main benefit of using this deployment method, rather than just doing an SVN checkout/update on the remote server is not having the .SVN dirs on the remote instance?