I am now officially impressed with the extensibility of monotone.
So I wanted some way to version control a website (well, ultimately more than just one). The way this used to be done with cvs was to have a checkout in the web area and a checkout in a test area. You would then cvs update in the test area, make sure everything worked, and then cvs update in the web area.
It’s not a bad workflow. It does the job, and it’s relatively simple.
But monotone can do better.
The first thing I set up was a new monotone server, on the web server itself. I used one of the scripts from monotone’s contrib directory to trigger a sync with my central monotone server whenever anything new is received (on the branches that relate to the web sites). This works both ways, so that syncing with one server will ensure that both servers receive new data within seconds. This was remarkably easy to set up, and because the script reads a config file, will be remarkably easy to maintain.
Then I created another monotone database as the user which will be updating the live website. This instance isn’t running as a server, so I can’t use quite the same mechanism to cause this one to update. Running it as a server would make it difficult to use ‘mtn update’, since the database would always be locked.
So the replication script grew some more code which could also execute scripts at the same time as kicking off replication. And a few small scripts later, a script which was run as the monotone user by monotone was able to kick off a sequence of actions that resulted in ‘mtn sync’ being executed for the web update database. This would connect to the server and receive the new data. Effectively, replication but triggered only in one direction. The important thing is that this database isn’t running as a server, and therefore can be used to run ‘mtn update’.
So the last part of the chain is a trigger on the web update database to execute another script when new revisions or certs are received. This is a bit simpler, as it’s already running as the correct user. This script simply checks that there is a unique head on the branch, and if there is, performs ‘mtn update’ in the web area.
The end result then is that you don’t need UNIX write access to any of the files in the web area to update the website (unlike cvs where you would have to log in to kick it), and updates happen instantly (with cvs, if you wanted to lock down UNIX access, you’d have to kick cvs with a cron job). The only action required in order to update the website is to check something into a monotone database, and then sync it with any one of the monotone servers on the network.
So why is this better? Surely you want to actually test changes first? Well, yes. This update script could now happily update files in a staging area too. And then, monotone can be configured to require a certificate asserting that the site has been tested before considering it for update in the live web area. That way, all changes would appear in the staging area immediately, and once an eye has been cast over the staging area, it can be signed by the tester, which will cause monotone to push it out live.
In the future, I can add testing requirements, such that an automated test suite can run (such as, perhaps, an HTML validator), and only once both a human and the test suite have given the thumbs up will it be pushed live.
Find out more about monotone here.