Setting Up a Deployment/Build/Ci Cycle For PHP Projects

Setting up a deployment / build / CI cycle for PHP projects

I've been through buildbot, CruiseControl.net, CruiseControl and Hudson. All though I really liked CruiseControl*, it was just too much of a hassle with really complex dependency cases. buildbot is not easy to set up, but it's got a nice aura (I just like python, that's all). But hudson won over the former three because:

  1. It's just easy to set up
  2. It's easy to customize
  3. It looks good and got nice overview functionality
  4. It got point-and-click updates, for itself and all installed plugins. This is a really nice feature, that I appreciate more and more

Caveat: I only ever used linux as base for the above mentioned build servers (CC.net ran on mono), but they should all - according to the docs - run cross-platform.

Setting up a hudson server

Prerequisites:

  • Java (1.5 will serve you just fine)
  • Read access to the subversion server (I have a separate account for the hudson user)

From here, it's just:

java -jar hudson.war

This will run a small server instance right off your console, and you should be able to browse the installation at your http://localhost:8080, if you don't have anything else running on that port in advance (you can specify another port by passing the --httpPort=ANOTHER_HTTP_PORT option to the above command) and everything went well in the 'installation' process.

If you go to the available plugins directory (http://localhost:8080/pluginManager/available), you'll find plugins for supporting your above mentioned tasks (subversion support is installed per default).

If that has whet you appetite, you should install a java application server, such as tomcat or jetty. Installation instructions are available for all major application servers

Update: Kohsuke Kawaguchi has constructed a windows service installer for hudson

Setting up a project in hudson

The links in the following walk-through assumes a running instance of hudson located at http://localhost:8080

  1. Select new Job (http://localhost:8080/view/All/newJob) from the menu on the left
  2. Give the job a name and tick Build a free-style software project on the list
  3. Pressing 'ok' will take you to the configuration page of the job. All the options have a little question mark besides them. Pressing this will bring up a help text regarding the option.
  4. Under the option group 'Source Code Management' you would be using Subversion. Hudson accepts both url access as well as local module access
  5. Under the option group 'Build Triggers', you would use 'Poll SCM'. The syntax used here is that of cron, so polling the subversion repository every 5 minutes would be */5 * * * *
  6. The process of building the project is specified under the option group 'Build'. If you already have an ant build file with all the targets you need, you're in luck. Just choose 'Invoke ant' and write the name of the target. The option group supports maven and shell commands as well out of the box, but there is also a plugin available for phing.
  7. Tick off additional build actions in 'Post Build Actions', such as e-mail notifications or archiving of build artefacts.

For setting up processes for which hudson have no plugins, you can either call them directly through a shell script from within the build setup, or you could write you own plugin

Pitfalls:

  • If you have it produce build artefacts, remember to have hudson clean up after itself in regular intervals.
  • If you have more than 20 projects set up, consider not displaying their build status as the default main page on hudson

Good luck!

What continuous integration tool suits for php?

Jenkins (formerly Hudson) is by far the best solution. It has a nice PHP integration (see http://jenkins-php.org/)

Recommended server for continuous integration for a PHP project

I have had good luck with phpUnderControl, which is based on CruiseControl.

Is there any stable tool for complete web deployment & CI?

There is a lot of chaos in your question:

  1. Configuration management:

    setup web services, databases, etc with tools like Ansible, Saltstack, Puppet, Chef
  2. Deploy code from repository to production:

    build package like Docker image or deb\rpm package or deploy directly from sources with Ansible\Fabric\Capistrano scripting
  3. Continuous integration:

    Automatic get sources after each commit or by scheduling, deploy it to the test environment, execute a tests and then merge changes into master or even deploy it to the production with tools like Jenkins, Hudson, Teamcity, Buildbot, etc
  4. Service orchestration for big complex environment:

    When you have a lot of components and cloud instances, environment required complex design and management. For this cases DevOps uses "cloud operating systems" like Mesosphere or orchestration tools like Nomad or Juju

In simplest case I recommend use Ansible for setup your components, Vagrant for local testing and AWS or any VPS for production. When your team will grow for automation you can use Jenkins for private repositories or Travis-ci for open source projects.

And hire a good DevOps when you'll grow ;)

Why to have build/ folder with PHP project and phing

There are several good reasons to have a build directory (i.e., deployment to multiple environments, performing some text replacement, minimizing and combining CSS and JS, optimizing images, handling of config files etc.)

However, these may not apply in your use cases. There is no rule saying you need this directory. Depending on your thinking on testing in production, a build directory may be a good reason to keep this directory.

PHP Code Deployment Tips

I would suggest making your testing deployment strategy a production-ready install-script -- since you're going to need one of those anyway eventually.

A few tips that may seem obvious to some, but are worth pointing out:

  • Your config file saved in your VCS should be a template, and should be named differently from the file that will eventually contain the actual settings. E.g. config-dist.php or config-sample.conf or sample/config-mysql.php or something along those lines. Otherwise you will end up accidentally checking in a server-specific configuration file over your template.
  • For PHP deployment, anticipate that some users will not be able to run server-side scripts through any mechanism other than the web server itself. A PHP-based installer is almost non-negotiable.
  • You should include a consumer-friendly update mechanism, and for that, wordpress is a great example of a project to emulate. A PHP script can (a) download the latest build, (b) use the ftp functions to update your application's files, and (c) execute an update script which makes the appropriate changes to the database, etc.
  • For heaven's sake don't do like [redacted] and make your users download and install separate patches for each point release. Have them download the latest (final) release which contains all the updates to date, and applies the correct ALTER TABLE functions in sequence.

Whether the files are deployed via SVN or through FTP, the install/update mechanism should be the same: get the latest files, run the update script. The updater uses the version listed in the PHP script and the version listed in the DB, and uses that knowledge to apply the appropriate DB patches in order. As for how to generate those patches, there are other questions here that you can refer to for more info.

As for the "Maintenance" page, just use the version trick mentioned above to trigger it (compare the version in the DB against the version in the PHP code). It's also useful to be able to mark a site as "down" to the public but make it visible to admins (like Joomla does), which you can trigger through database or filesystem flags.

As for automatically pulling code from SVN, I'd say you're better off with either a cron script or with commit triggers than working that into your application, since it wouldn't be relevant to end users.

Separate Building from Deployment with Hudson

I ended up doing something similar to Peter Schuetze suggestion. I used only the only job however. I use 3 build parameters, deploy (bool), environment (choice) and revision (text). I then altered my Phing scripts to only do deployments if the deploy parameter is true, in which case it will deploy the specified revision to the specified environment. By default deploy is false, revision is head and environment is staging. Now when Hudson polls svn, it sees the deploy parameter is false and bypasses the deployment tasks.



Related Topics



Leave a reply



Submit