Call us Toll-Free:
1-800-218-1525
Live ChatEmail us

 Sponsors

Mercurial Hook: Push to remote servers automatically

Brett Batie, 09-08-2010
The Mercurial version control system offers a powerful mechanism to let you perform automated actions in response to events that occur in a repository. In some cases, you can even control Mercurial's response to those events. No comments

With this post, I'll walk you through how I developed a Mercurial hook that automatically pushes files from one central location, to a remote server.

Why do we need this auto-push-remotely hook?

Here at SoftwareProjects, as part of our multi-homed hosting solution, we host servers in multiple data-centers, where multiple servers run the same websites. Think geo-load balancing.

Replicating a website across several locations has several benefits:
  • Throughput - It will be able to handle more traffic, since the load is distributed across several machines.
  • Better reliability - if one machine is down, the others can still serve user requests.
  • Easier maintenance - Upgrades can be implemented one machine at a time, with zero impact to the end users.

    More moving parts

    Of course, running multiple servers does add some complexity as the website data needs to be synchronized on all the servers.

    Often Rsync is used for this purpose and setup to run every X minutes via cron.

    Rysnc has some disadvantages. It has to recursively scan all the directories and search for files that have changed before sending them to another server. This can be a bit time consuming and also requires more CPU. It means that the content may be out of sync by roughly 5-10 minutes. Having the content live on some servers and not on others can be an issue as different users will have a different experience.

    Another solution instead of using Rsync is to automatically synchronize the file or files to the other servers as soon as it has changed. This can easily be done when using version control to send the content to a central server. Then the central server can send the content to all of the other servers.

    The Mercurial Hook

    Automatically synchronizing files to other servers can be setup with Mercurial. This just requires setting up a new hook on the changegroup event.

    This hook can be setup in mercurial's config file with the following two lines of code:

    [hooks]
    changegroup.hg_sync = /usr/home/code/hg_sync.sh

    We also need to create the hg_sync.sh script that is executed during the changroup event. Below is an example script that will automatically push the changes to all other servers.
    #!/usr/local/bin/bash

    # Determine the repository that recieved the push
    p=`/bin/pwd`

    # See if it is a repository that we want to synchronize across servers
    if [ "$p" == "/usr/home/admin/htdocs" ]; then
    # Get each server to syncrhonize with
    while read current_line
    do
    # Push the content to the other server
    /usr/local/bin/hg push -f $current_line
    done < /usr/home/code/hg_sync_servers.txt
    fi

    exit 0;

    This script will first determine if the changegroup event is occurring on the correct repository, based on the path. Then it will push to each server that is listed in the file /usr/home/code/hg_sync_servers.txt. This text file can look something like the following:
    ssh://user@code1.domain.com//usr/home/admin/htdocs
    ssh://user@code2.domain.com//usr/home/admin/htdocs
    ssh://user@code3.domain.com//usr/home/admin/htdocs

    With the above script setup on the changegroup event the output from an "hg push" will contain the following line:
    running hook changegroup.hg_sync: /usr/home/code/hg_sync.sh

    How to install

    The last step is to add a hook to all of the servers listed in the hg_sync_servers.txt file. These servers need to be setup to automatically run "hg update" after they are pushed to. This is simply a matter of adding the following line to the mercurial config file on these servers:

    changegroup = /usr/local/bin/hg update >&2

    This setup will allow all files to be automatically synchronized to all servers just after the central repository receives the files. This allows for files to be seen on all servers faster than what can be accomplished with a tool such as rsync.
  • Vlax, 05-04-2011
    Hi
    Thanks for the article very useful indeed!
    I got just a question:
    Where did you take the ".hg_sync" part in "changegroup.hg_sync" from? I can't find any documentation about that...
    Regards
    Vlax

    Meik, 07-05-2011
    Nice1 - Thx for sharing

    Miz, 07-03-2014
    Hi Brett,

    Thanks for the article, it was nice. Can you please help me how to achieve same in windows platform. i want that whenever i push changes on local server it automatically syn with remote server.
    Enjoyed this post?

    Subscribe Now to receive new posts via Email as soon as they come out.

     Comments
    Post your comments












    Note: No link spamming! If your message contains link/s, it will NOT be published on the site before manually approved by one of our moderators.



    About Us  |  Contact us  |  Privacy Policy  |  Terms & Conditions