Someone emailed me recently, having read my book and wanting some advice. Here's a snippet of his email:
So here's my problem.
We dont know deployment. We work from same copy on one test server through ftp and then upload live on FTP.
We have some small projects and some big collaborative projects.
We host all these projects on our local shared computer which we call test server.
All guys take code from it and return it there. We show our work to clients on that machine and then upload that work to live ftp.
Do you think this is a good scenario or do we make this machine a dev server and introduce a staging server for some projects as well?
I wrote him a reply with some suggestions (and my consulting rate) attached, and we had a little email exchange about some improvements that could fit in with the existing setup, both of the hardware and of the team skills. Then I started to think ... he probably isn't the only person who is wondering if there's a better way. So here's my advice, now with pictures!
This is basically the place we begin from:
The code lives on this staging server, when you need to make a change, you copy it onto your own machine, make the change, and put it back on the staging server. From here, it can be checked over before it is put onto the live machine over FTP.
The first thing to say is: this does work, as long as you follow the process exactly. But I was asked if I thought there was a better way, and I think there is. When I work with a setup like this, there is always a moment where I have no idea if I just copied over something, or forgot to copy over something, or ... you get the picture.
Step 1: Source Control
Use source control. That's the best advice I can give anyone. Use a hosted solution, install your own, pick Subversion or Git or Mercurial, I really don't care. But use source control.
Here's the diagram with the source control in place, using SVN as an example (but it makes little difference what kind of source control you pick)
Hardly anything has moved, but we've added a piece to the middle of the puzzle. At this point, there's a central repository where things are always kept, and always backed up. We have a history of changes, and can see who changed what. The developers can collaborate on larger changesets, and those changes can be committed to the repository even before they are ready to be placed onto the staging server, so you are much less likely to lose code when a hard drive dies.
To get the code from the repository to the staging and live servers, we can export a clean copy of code each time and upload that using FTP (or go one step further, SFTP). If you really must check out from source control repositories onto public servers, then make absolutely sure you are not serving the metadata that the source control product uses - since this is only step 1, that would be OK (but keep reading).
Step 2: Branches
Now we've gone to all the trouble of implementing a source control solution, we may as well make the most of the features that are now available to us. This means it is time to learn to branch. A branch is just another copy of the code, but isolated from the first one. Using branches means you can:
- always have an exact copy of the current live code available
- work on more than one feature (or bug fix) at once
You would use the same setup as above, but branching means you are able to do a great many more things without any fear of who changed what or whether you can commit without hurting things.
I could write another thousand words about branching, but I won't (well, unless you ask very nicely, and even then it will be written another time). Instead, look around for some resources for whichever platform you chose: the Red Bean Book is a great place to start.
Step 3: Automated Deployment
This is the jewel in the crown, especially if you run multiple sites. If you only run one site, no matter how complicated it is, you will eventually learn to get the deployment mostly right, most of the time. With multiple sites, they will all have differences and they will take turns to bite you when you least expect it (or, more likely, on Friday afternoon when you are trying to do three other things before pub o'clock). Automated deployment means fast, repeatable, painless deployment every single time.
To deploy, you probably need some kind of build process. I've got it here as a separate piece of the system as it's conceptually separate, but it could easily be as simple as a few scripts running on a spare box in the office (which might also run your SVN, for example), you don't need anything fancy.
There's the build server, right in the middle. When changes are available in the version control system, the build server will know about them. When you are ready, you ask the build server to deploy the relevant code to either live or staging, and it does that. Nobody else touches live. For any reason. If they do, their changes get lost on the next deploy - and anyway, automated deployment is so easy that there's no reason not to use the process!
Exactly how the code gets deployed is up to you; personally though I like phing, which comes with lots of tasks for dealing with source control and PHP-specific tools built in. It's relatively easy to get started with and you will set it up to follow the process which is currently documented on your company wiki (it is documented, right??). Mine goes something along the lines of:
- export files from source control
- compress files
- transfer files to server
- log into server, uncompress files
- deal with database changes, upload files, and anything else which needs special attention
- make the new code live by changing the symlink that your docroot points to
Yours may be a bit different, but this is all pretty straightforward to set up with phing, or you can write your own scripts if you prefer.
Step 4: For Bonus Points
Better than FTP
I'm not advocating using cool tools just for the hype; the recommendations here are the ones I use to protect myself from my own mistakes, hardware failure, projects with changing requirements, bosses with short memory spans, and all the other things that are part of everyday work. With branches in version control and some automated deployment, I can create and publish multiple changes in little more time than it takes me to write the actual code - which is really what I'm interested in!
Does this resemble your setup? Would you have given the same advice if you received this email? Let me know in the comments! (I'm sending a link to my original enquirer so it would be useful for him to hear your thoughts!)