Tim Jackson
If you're building and supporting a number of individual web applications then rapidly reproducing predictable deployments can become a challenge, especially when distributed across multiple developers and multiple environments. This talk outlines some of the real-world challenges, and introduces an open source tool which can help make your life easier.
Things we typically have to do to get a system up and running...
which can easily lead to...
and
$ wadf-deploy mywebapp Do you want to deploy database(s) if relevant? (y/n):y Checking out svn+ssh://svn@svn.example.com/apps/mywebapp/trunk... PEAR dependencies found; creating a PEAR installation in pear_local/ install ok: channel://pear.php.net/Archive_Tar-1.3.3 install ok: channel://pear.php.net/Structures_Graph-1.0.2 install ok: channel://pear.php.net/Console_Getopt-1.2.3 install ok: channel://pear.php.net/XML_Util-1.2.1 install ok: channel://pear.php.net/PEAR-1.9.0 Installing PEAR dependencies... upgrade ok: channel://pear.php.net/Net_URL-1.0.15 upgrade ok: channel://pear.php.net/HTTP_Request-1.4.4 upgrade ok: channel://__uri/mywebapp-1.1.0 Setting up database mywebapp on host localhost... Deleting existing tables in database mywebapp... Deploying new schema for database mywebapp as user myuser... Deploying webserver configuration... Deploying scheduled jobs from /home/myuser/mywebapp/crontab... Running kickstart script /home/myuser/mywebapp/setup.php... ----------- OUTPUT BELOW IS FROM KICKSTART SCRIPT, NOT WADF ----------- Set up initial database content.....................OK ------------------- END OF KICKSTART SCRIPT OUTPUT -------------------- Restarting webserver... Starting WADF HTTPD instance: [ OK ] Listening on port 10080 and configured for the following applications: mywebapp: (/home/myuser/mywebapp) ver=DEVTR:1792 http://mywebapp.localhost.localdomain:10080 $ firefox http://mywebapp.localhost.localdomain:10080
No, If you use the standard conventions, what we just saw can be done from a default install with only 1 option:
[local] vc_base = svn+ssh://svn@svn.example.com/apps
@some_macro@@appref@ - app reference@deploy_path@ - filesystem path to deployed app@vhostX_name@ - application hostname (X=1,2,...)@dbX_[name|host|user|pass|type]@ - database details@php_dir@ - path to PEAR installation (if used)@profile@ - environment profile in usefoo.template vs foo - the original files with environment-specific data are not checked into SCMDefaults can be specified in a file called wadf.conf in the root of the site (this can be checked in if you don't include passwords or things that vary from deployment-to-deployment...). Example:
[local] admin_email = developer@example.com [staging] admin_email = qa@example.com [live] admin_email = sales@customer.example.net
If you need to prompt at install time...
[globals] ; Here's a macro with a made-up name admin_email = developer@example.com [staging] ; '%%' means "prompt on deploy" (with optional message) admin_email = %%E-mail address to receive admin notifications vhost1_name = staging.example.com [live] ; '**' means "something should have been filled in here; halt the deployment" admin_email = **Awaiting customer admin contact vhost1_name = www.example.com
These values get saved in a file called .wadf-instance within the deployment.
By default, these are all in the root of the application, but that's configurable (as is the naming).
vhost-httpd.conf.template - template Apache HTTPD virtual host. Don't include PHP config options! (think about CGI)php.ini - PHP configuration options for the app, including include_path etc.setup.php - anything that needs setting up, typically basic population of SQL databaseschema.sql - SQL schema (without data)crontab - scheduled jobs for this applicationpackage.xml - Dependency metadataExample vhost.conf.template
<VirtualHost @vhost1_interface@> ServerName @vhost1_name@ DocumentRoot @deploy_path@/webroot RewriteEngine on RewriteRule /.* @deploy_path@/application/bootstrap_http.php </VirtualHost>
Example php.ini:
engine = on ; when processed, 'php_dir' will be the path to the PEAR installation include_path = .:@deploy_path@/include:@php_dir@ register_globals = off magic_quotes_gpc = off ...
Create a package.xml file in the root of the site (location configurable)
package.xml format which is unfortunately a bit long-winded for what we want<dependencies> sectionExample package.xml for the web application itself:
<package version="2.0" xmlns="http://pear.php.net/dtd/package-2.0"...>
<name>testapp</name>
<channel>__uri</channel>
<summary>Test application</summary>
<description>Test application</description>
...some boring stuff here: version, notes, developer etc. ...
<dependencies>
<required>
<php><min>5.2.0</min></php>
<pearinstaller><min>1.7.0</min></pearinstaller>
<package>
<name>HTTP_Request</name>
<channel>pear.php.net</channel>
<min>1.4.4</min>
</package>
</required>
</dependencies>
<phprelease/>
</package>
pear list') a "dependency tags" file which overrides the normal dependency mechanism and force-installs the specified versions:PEAR:pear.php.net/Archive_Tar-1.3.3 PEAR:pear.php.net/Console_Getopt-1.2.3 PEAR:pear.php.net/Date-1.4.7 ... SVN:svn+ssh://svn@svn.example.com/Somelib/trunk@12345 /checkouts/Somelib ...
(SVN dependencies are there as an optional alternative to externals; useful if you have groups of developers accessing SVN via different protocols e.g. HTTP, SVN, SVN+SSH etc.)
channel-discover pear.timj.co.ukpear install timj/Tools_WADF[local] vc_base = svn+ssh://svn@example.com/clients
wadf-deploy [-d foo=bar] [-v] [-r revision] <appref> [version]wadf-reprocess [--db] [--templates-only] ... [version]wadf-undeploywadf-cleanwadf-list-macroswadf-httpd [-i myapp] [start|stop|restart|reload|status|...]wadf-deploy. This will:
*.template)wadf-reprocess if you've changed any template files or dependencieswww.timj.co.uk/computing/software/wadf