Support atomic promotion and rollback
Implemented a new directory structure that supports a more atomic
promotion process and automated rollbacks. Each project revision is
deployed into its own directory under revs/ and a current symlink,
created just before service restart, controls which revision is
The 'fetch' stage now utilizes a local cache directory for the remote
repo which is then used to clone locally into the revision specific
directory. This process should be disk-space efficient as long as both
locations are on the same local filesystem, as git hard links objects by
default for local clones. If it proves problematic, we can investigate
using something like git-new-workdir.
Rollback support depends on two additional symlinks (.in-progress and
.done), both located in the root deploy directory, to maintain state
for the current deployment across target nodes. The .in-progress
symlink is created following a successful 'fetch', and replaces the
.done symlink upon a successful 'check'.
If any failure occurs during the promote and check stages, the user
is prompted to rollback. The actual rollback process simply resolves the
last successful revision by looking at the .done symlink and performs
a 'promote' to that revision.