views:

482

answers:

6

I am currently developing a php-application for a charity organization and I am now in the stage of defining the deployment practices.

Our application is using both Zend Framework and Doctrine. The application will be rolled out to different servers, each with a different configuration file. The machines are both Windows and Linux (but all with Apache and php 5.2+).

The source is available in a subversion repository and we want to build and store our packages on a Linux server.

Preferably we want the update process to be as easy as running an update command in the application directory, where the update command also updates the database (with the doctrine scripts) and ensures dependencies of the frameworks. This update command must be a command on the machine (we can't ssh into them). Preferably we have the option of downloading a new version or providing an already downloaded tarball with a new version. (but only downloading or only tarball is also ok)

The packages with installations and updates (new versions) are also preferably build by a single command.

I have been reading a bit about phar's, pear, phing but I have no clue what the best way to do this is. A continuous integration server is not really necessary, but I think about deploying test environments automatically after building a version.

Initially only the updating of the php app has to be very easy, filling initially a configuration file when installing can be done by hand.

A: 

You said that you have a claster. We're in the same position and we use ZF and Doctrine. This is how we solved the problem:

<?xml version="1.0" encoding="UTF-8"?>
<project name="yourprojectname" basedir=".">

<target name="deploy" depends="apply-deltas,update-app01,update-app02">

</target>

<target name="update-app01">

  <sshexec host="app01"
    username="yourusername"
    password="yourpassword"
    trust="true"
    command="cd path/to/root/directory &amp;&amp;
      svn update &amp;&amp;
      php cmd/clear_cache.php
      "/>

</target>

<target name="update-app02">

  <sshexec host="app02"
      username="yourusername"
      password="yourpassword"
      trust="true"
      command="cd path/to/root/directory &amp;&amp;
      svn update &amp;&amp;
      php cmd/clear_cache.php
      "/>

</target>

  <target name="apply-deltas" depends="liquibase-prepare">
     <updateDatabase
          changeLogFile="${db.changelog.file}"
          driver="${database.driver}"
          url="${database.url}"
          username="${database.username}"
          password="${database.password}"
          promptOnNonLocalDatabase="${prompt.user.if.not.local.database}"
          dropFirst="false"
          classpathref="classpath" >
          <changeLogProperty name="table.name" value="ant_param_table"/>
     </updateDatabase>
  </target>


<target name="liquibase-prepare">
    <path id="classpath">
    <fileset dir="${basedir}/libNoPackage">
        <include name="**/*.jar" />
    </fileset>
    </path>

    <taskdef resource="liquibasetasks.properties">
        <classpath refid="classpath"/>
    </taskdef>
  </target>

</project>

This is far from ideal but it works fine for us. Hope that helps.

Links:

Apache Ant

LiquiBase

If you have some questions please let me know so I can update the answer.t

Fedyashev Nikita
A: 

Perhaps sometimes a simpler approach works best. If you keep stable releases simply tagged within the svn repo then you can just write a batch / bash script to download the newest revision whilst backing up to old with no user intervention - you can also run any scripts required in this way. Another alternative is writing a simple interface to this in PHP but it depends on how simple it needs to be.

ternaryOperator
+2  A: 

I'd start by making the application root of the various servers an SVN working copy. You can add in mod_rewrite (or IIRF ASAPI filters for IIS) rules to ensure people can't address your .svn directories directly.

Then, updating to the latest source can be as simple as an SVN update. For your database update needs, I'd maintain the database modification scripts also in SVN. You'll likely need to wrap the SVN update in a batch/shell script in order to perform the database updates after the scripts are downloaded.

For change management on the live servers, I'd also have their working copies not of trunk, but a release branch. You can merge trunk into the release branch when you are ready for a release. This will allow you to test the deploy and make sure it's solid before performing it on the live servers. It also has the nice side-effect of giving you a nice replica of the site-release versions in case you need to track down issues post-launch.

Lastly, depending on the intensity and timing of these updates, you may also want to have your update script flip an "under maintenance" switch so that users are temporarily met with a proper message rather than a broken site.

James Maroney
+2  A: 

Benjamin Eberlei posted a blog a few weeks ago titled Trying a Two Step PEAR/PHAR approach to develop and deploy. He describes is a very interesting and elegant procedure for deploying a PHP application.

Bill Karwin
The procedure, or at least the article, seemed overly complex to me. I didn't see a clear explanation of what he was trying to accomplish.
rick
A: 

I've used subversion as a deployment tool to great effect.

Use svn update on all your production servers, or use phing. (Or use phing to svn update, even.)

Makes rollbacks and backups a snap. Just remember to remove access to any .svn directories.

gabrielk
+1  A: 

Either way, I would manage your builds with phing or something similar. Let it run your tests, generate docs, build and publish your package/tarball.

As for distribution, you could run your own PEAR server. Rationale here is you said you want users to pull updates, you have both Windows and Linux users, and you want to handle dependencies for them. PEAR should be able to handle all that with one command.

That said, I would go with the simplest thing that works and suits your users. That could just be a tarball available via HTTP and a small PHP upgrade script (or a phing target.)

Definitely provide a simple way to rollback to a previous version. With code/configuration you can just keep a copy. With DB, use migrations (which it sounds like you're doing already.)

oops