views:

1154

answers:

5

Hello,

How can I best set up my PHP (LAMP) development environment so that I have development, staging and production servers. One-"click" deployment to any of those, as well as one-click rollback to any revision. Rollback should also rollback the database schema and data to how it was when that source code was current.

Right now I've done all of this (except the DB rollback ability) for one application using shell scripts. I'm curious to know how others' environments are setup, and also if there are any generic tools or best-practices out there to follow as far as layout is concerned.

So, how do you do this? What existing tools do you make use of?

Thanks!

UPDATE: Just to clarify as there is some confusion about what I'm interested in.

I really want people to chime in with how their environment is set up.

If you run a PHP project and you have your DB schema in version control, how do you do it? What tools do you use? Are they in-house or can we all find them on the web somewhere?

If you run a PHP project and you do automated testing on commit (and/or nightly), how do you do it? What source versioning system do you use? Do you use SVN and run your tests in post-commit hooks?

If you run a PHP project with multiple dev servers, a staging server and production server(s), how do you organize them and how do you deploy?

What I hope to get out of this is a good idea of how others glue everything together.

+1  A: 

I noticed this wasn't getting much exposure. It's also something I'm interested in. Are you aware of Phing? Have you tried it?

Andrew

Andrew Taylor
Thanks for the answer! I'm aware of Phing but have yet to try it. The build system itself be it Phing, mere shell scripts or something else, is part of what I'm interested in. The other part is how PHP guys are handling DB versioning and if there are any tools out there for it.
noob source
+10  A: 

Our production environment includes the following:

  • 3 frontends who serve our website
  • 2 database backends (Master-Slave, replication)
  • 1 mixed which runs httpd and database for adserving

Our development environment is a single server running both database and httpd, configuration-wise we have different workspaces for everyone setup and our VC is subversion. Staging is rather simple too - it runs on one of the frontends.

Database changes

Initially we spent a lot of time on the database design and it seems to have really paid off. We haven't changed anything major in five months now. Most of the changes we deploy are on the frontend. Now, so far we run all the changes to the database manually and I always wrote a small script to revert.

If I had more of those, I'd use phpDoctrine and Migrations here. I've never actually had the chance to use them in production but I've played with those extensively already and they seem very powerful.

Deployment

So whenever we deploy a new version we create a tag of the code which we check out on staging, then go through a couple lists of checks etc. and then we deploy the code on the production frontends. For doing all of the deployment, I have a couple tasks setup in Capistrano.

Check out this sample capfile:

role :www, "web01", "web02", "web03"
role :web, "web01", "web02", "web03", "web04"
role :db, "db01", "db02"

desc "Deploy sites"
task :deploy, :roles => :www do
    run "cd /usr/www/website && sudo svn --username=deploy --password=foo update"
end

Capistrano also allows you to run any other command without defining a task:

cap invoke COMMAND="uptime" ROLES=web

(Requires the role "web" to be setup. See example above.)

Coding style and documentation

We pretty much adhere to the PEAR Coding standard, which we check using PHP_CodeSniffer (phpcs). When I say pretty much, I mean that I forked the sniffs provided and added a few exceptions of my own gusto.

On top of coding style, phpcs checks on inline documentation as well. This documentation is created by phpDocumentor in the end.

CI

I have both of those tools setup in our CI-server (continuos-integration), which is phpUnderControl using the above and CruiseControl, phpUnit, Xdebug (a couple code metrics...), etc..

unit-testing is something we currently lack. But what we do right now is that with each bug we find in our parsing engine (we parse text into certain formats), we write a test to make sure it doesn't come back. I've also written some basic tests to check the URL-routing and the internal XMLRPC API but this is really subject to improvement. We employ both phpUnit-style tests and phpt as well.

The CI-server builds a new version a couple times per day, generates graphs, docs and all kinds of reports.

On top of all of the tools mentioned, we also use Google Apps (primarily for email) and keep a Google Sites wiki with all other documentation. For example, deployment procedure, QA test lists, etc..

Till
This is *exactly* what I was interested in! I don't have time to read it right now but thanks, I can't wait to sit down and read it properly.
noob source
You're welcome. Let me know if you have any other questions.
Till
A: 

@andrew : I've tried Phing and ended up with phpUnderControl. The problem with Phing is that to manage code coverage, it has to actually include all the files in you project, which for our project just does not do it. The approach of CruiseControl worked better for us. Give them a try, they are both easy to setup - the hard work is to build the tests....

Bertrand Gorge
+1  A: 

For database changes, we have a directory in the VCS:

+ dbchanges
|_ 01_database
|_ 02_table
|_ 03_data
|_ 04_constraints
|_ 05_functions
|_ 06_triggers
|_ 07_indexes

When you make a change to the database you put the .sql file into the correct directory, and run the integration script that goes through these directories in order, and import every change into the db.

The sql files have to have to start with a comment, which is displayed to the user when the integration scripts imports the change, describing what it does. It logs every imported sql file's name to a file, so when you run the script next time, it won't apply the same change again.

This way, all the developers can simply run the script to get the db up to date.

WishCow
but can you easily rollback the schema changes?
philfreo
Unfortunately, no. You have to store the opposite of the operation too, if you want that, but that's not possible for statements like DELETE.
WishCow