12

How can we push code to multiple servers? We have many servers which needs to have the same copy of the code. It is difficult to push to individual server. I know mercurial has hooks but none of them gives a proper solution.

Akshay
  • 1,735
  • 6
  • 21
  • 29

3 Answers3

19

In your central server you create a changegroup hook.

So your central server would have the following hgrc:

[paths]
server2=http://server2
server3=http://server3
[hooks]
changegroup.server2 = hg push -f server2
changegroup.server3 = hg push -f server3

You can have multiple hooks for the same event, so that shouldn't be an issue.
The advantage of the changegroup hook over the changeset hook is that it is run far less often.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Ton Plomp
  • 3,020
  • 1
  • 18
  • 35
  • 2
    This one's the best solution because it will only be triggered if the push to server 1 succeeded. You'll probably need 'push -f' in those changegroup hook lines if you're working with branchy histories. – Ry4an Brase Jul 21 '10 at 14:45
  • The code needs editing for it to work. Mercurial lets you [performing multiple actions per event](http://hgbook.red-bean.com/read/handling-repository-events-with-hooks.html) **by adding an extension to the end** of a hook's name. You extend a hook's name by giving the name of the hook, followed by a full stop (the “.” character), followed by some more text of your choosing. For example, Mercurial will run both commit.foo and commit.bar when the commit event occurs. – Serge Stroobandt Nov 09 '13 at 23:54
  • [This linked answer](http://stackoverflow.com/a/6236600/2192488) was already corrected in this sense by somebody else. – Serge Stroobandt Nov 09 '13 at 23:56
1

In your .hg/hgrc file you should have a [paths] directive, which contains your default location. What about adding something like:

[paths]
default = http://server1
server2 = http://server2

And then do a:

hg push default
hg push server2
Roberto Aloi
  • 30,570
  • 21
  • 75
  • 112
  • 2
    yes that's the problem. I know this solution, what I want is a hook or a trigger that on a successful push to server1, push to server2 is automatically initiated. The above solution always has a chance of forgetting to push to one server. By the way, thanks for a quick reply. – Akshay Jul 21 '10 at 10:32
  • I have faced automatic push chain problem. Does it solve or not? – Chen Yu Dec 06 '12 at 08:07
0

i assume that one of the servers is a master repo, the rest are deployments. in such a situation, i would interact with just the master and leave the deployments up to cron:

cat >$HOME/bin/dist <<'EOM'
#!/bin/sh
cd ${1:?}
tip=$(hg tip --template '{node}')
for r in $remotes; do
  hg push -r $tip $r
done
EOM

chmod +x $HOME/bin/dist
(crontab -l; echo '*/5 * * * * $HOME/bin/dist /var/repos/master') | crontab -
just somebody
  • 18,602
  • 6
  • 51
  • 60
  • huh.. what will happen if more than one commit has been pushed in less than 5 mn? :-). In this case it's better to setup a "changegroup" hook. Also when a changeset is creating a branch, it would be necessary to push with the -f option (force). My advice, if you want to use cron instead of a hook, would be to set it up on the remote machines which would regularly pull changes: this way, there can be more than one changeset pulled (so you can even pull every hours for example), and also pull does not require the -f option. Just my 0.02€. Cheers, Christophe. – Christophe Muller Jul 21 '10 at 14:23
  • 1
    's solution works fine. 'push' pushes 'tip' and all of its ancestors, so they'll get everything. There's a lot of unecessary code though, you can use the name 'tip' instead of using the template to learn it (-r takes names just fine), and you can skip the -r param all together and just do 'push' which defaults to tip. You probably want push -f though since you may need to push new branches and new heads at some point and you don't want the script failing. – Ry4an Brase Jul 21 '10 at 14:44
  • @ry4an: you cannot use the name `tip`, since it could point to a different changeset before the script gets from server1 to server3. that's just the reason why you cannot just leave out the `-r`: if you want all the mirrors to have the same tip after each push, you need to stick to the same revision for the whole script. the `-f` comment is valid, though. – just somebody Jul 21 '10 at 17:34