In the last couple of months we started using Ant tool heavily to do server deployments, along with Jenkins server (although not in the role it was intended, but hey, it serves the purpose).
Most of the things in setup work well and it became a pretty smooth operation, but one big hurdle that remained was the db changes management.
Lack of time prevented me from exploring the options, but as luck would have it, we were attending the awesome phpDay 2012 conference, and an exellent talk by Jeremy Coates titled An introduction to Phing the PHP build system where on one of the slides two tools were mentioned, dbdeploy and Liquidbase.
I did not hear about them up till then, and they were mentioned briefly as db change automation tools, and those words rang in my ears, I could not believe my luck, so few days after, I started looking into them.
What I wanted to have is a way to incrementaly update the database, or just dump all the alters in, a nice side effect would be to be able to generate one flat deploy file that could be either user for some remote deployment, or submitted to the DBA if needed.
Both tools look excellent, and they seem to do their job well, but in the end I selected the dbdeploy because it was closer to the way we structure our projects and files, and would be less intrusive to our process.
dbdeploy relies on deltas to update the db, each delta is one file that should ideally have one CREATE/ALTER/DROP command and it’s undo counterpart, the files should be named in form XXX_something_or_other.sql, where XXX is numeric that identifies the order of execution of the script, with that in mind, it goes along nicely with the way we work (granted naming of directories is different, but it works, for now…). We would have to adapt a bit to break down the initial db draft into individual alter files, and add their undos, but that is really a non-issue.
The setup consists of
- Ant
- dbdeploy, which you can get from here
- MySql Connector JDBC driver, which you can get from here, or some other JDBC driver (I am targeting MySql so YMMV)
The tasks/targets are defined in the build.xml file, more on that later, for the moment I’d like to focus on the build.properties file. This file is not supposed to go into the VCS apart in it’s build.properties.dist form (which you should rename and mod for your local setup). This file will contain some paths and db credentials that vary from project to project and/or server to server. This file is a standard ant properties file which consits of key/value pairs
build.properties:
|
|
This is pretty straight forward stuff, but point of interest is line 12 - path to mysql, you may want to drop this, I used it to execute the flat sql file with mysql, more like a proof that it works than actual use
With that the variable properties are covered and the build.xml file can be built. My personal preference is that it goes in the VCS, but some prefer to keep only the build.xml.dist in the VCS.
build.xml:
|
|
Points of interest:
-
Line 18 - the path to the dbdeploy and MySql JDBC connector jars, because this will be standardized structure it makes more sense to set it here, than in build.properties
-
Lines 20 - 27 - the paths for the deltas, deploy and undo scripts, they are defined relatively to the build.xml file or basedir definition
-
Line 30 - build.dbdeploy.lastChangeToApply key - this is basically a limiter, if you have new deltas you are working on, and do not want them in the db, you can prevent their execution by setting the number to lower than the order number they have.
-
Line 33 - the package for your db driver, to decrease the typos possible when generating a new target
-
Line 36 - the url of the database
-
Line 42 - the path to the changelog table script, it comes with dbdeploy package, and is IMPORTANT, dbdeploy uses it to track changes
-
Lines 45 - 46 - definiton for the deploy and undo files, I chose to use timestamp value after the name
-
Lines 51 - 55 - define classpath for the MySql Connector and the location of the jars for it
-
Lines 58 - 66 - define classpath for the dbdeploy and the location of the jars for it
-
Line 69 - declared the dbdeploy task to Ant
-
Lines 73 - 78 - This is the target that actually creates the changelog table in your db, should be used once or when recreating the db. Without this table the dbdeploy will fail
-
Lines 155 - 161 - This is more a proof of concept than it actually works kinda thing, it can be used do import the generated deploy file into the db via shell command
You might notice that the actual targets to execute are doubled, their syntax is almost the same, they differ in one important aspect. The *-all targets will execute ALL the deltas present indiscriminantly.
The targets without the -all will rely on the build.dbdeploy.lastChangeToApply from build.properties file to execute the deltas only upto, and including the number given.
This is important to us, because this way we can make sure that only the deltas that are verified as good be executed in the db, or to shoot ourselves in the foot and lose a couple of hours trying to figure out why delta with order number x is not executed while not realising that the build.dbdeploy.lastChangeToApply value y is less than x, SO BEWARE OF THE LIMITER
The targets dbdeploy-generate-sql/dbdeploy-generate-sql-all will generate two files (flat sql files), one for deploy on location set by build.dbdeploy.deploy_dir, and one for undo on location set by build.dbdeploy.undo_dir. These files can either be executed on remote server or submitted to your DBA for review, or some other purpose you may need.
The targets dbdeploy-migrate/dbdeploy-migrate-all will update your db schema with the deltas that were not yet executed.
You will notice that I do not mention the undo/rollback process, from what I understand the dbdeploy currently does not support rolling back to a specific script, and it’s undo will happen only if the update is broken. Dbdeploy will assume you will fix the problem by making another delta and executing it on the db.
For our scenarios that is currently a non-issue because we test things locally and on dev server before we deploy to live. Chances of immediate rollback are small, yet still present.
The files are available on Github