Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build a git polling build bot?

How can a little cron, bash + make based script (e.g. much smaller and less robust than, for example, Hudson) build-bot poll a git repo and detect if it should build now - e.g. if in its periodic pull from the remote git repo, it has retrieved new code?

Currently, it looks like this:

git fetch  > build_log.txt 2>&1
if [ $? -eq 0 ]
then
  echo "Fetch from git done";
  git merge FETCH_HEAD >> build_log.txt 2>&1 ;
  if [ $? -eq 0 ]
  then
    echo "Merge via git done"; ...
    # builds unconditionally at the moment
  fi
fi
like image 945
grrussel Avatar asked Aug 23 '11 19:08

grrussel


4 Answers

You can record the tip of your branch to build between polls, and build whenever the the tip changes–that is, when the branch has been changed.

git rev-parse <branch_name>

Will retrieve the sha1 of the latest commit in the branch. Compare the output of the command with the stored output, and when it changes:

  1. update the stored sha1
  2. perform the build

This lets you target specific branches and only build when that branch changes. Otherwise, if you want to build whenever any branch changes you can just check that the output of git fetch is empty (when there are no updates, git fetch returns nothing).

Here's a version of your script that only builds when master changes (so that changes to experimental branches don't trigger new builds of master if it hasn't changed):

if [ ! -f prev_head ]; # initialize if this is the 1st poll
then
  git rev-parse master > prev_head
fi
# fetch & merge, then inspect head
git fetch  > build_log.txt 2>&1
if [ $? -eq 0 ]
then
  echo "Fetch from git done";
  git merge FETCH_HEAD >> build_log.txt 2>&1 ;
  git rev-parse master > latest_head
  if ! diff latest_head prev_head > /dev/null ;
  then
    echo "Merge via git done"; ...
    cat latest_head > prev_head # update stored HEAD
    # there has been a change, build
  fi
fi
like image 198
shelhamer Avatar answered Oct 31 '22 21:10

shelhamer


If you have control over the remote repo, you might consider doing it via hooks instead of polling. That way your script only gets called when there is something new to build.

like image 42
Karl Bielefeldt Avatar answered Oct 31 '22 20:10

Karl Bielefeldt


If nothing was fetched, then "get fetch" will output no lines, so just check for zero filesize on build_log.txt:

git fetch > build_log.txt 2>&1
if [ -s build_log.txt ]
then
   # build
fi
like image 35
Alex Howansky Avatar answered Oct 31 '22 20:10

Alex Howansky


You can also target a specific branch without maintaining the most recent head or using a temporary file:

if [[ $(git fetch 2>&1 | grep master) ]]; then 
  # build 
fi
like image 1
Neil Sarkar Avatar answered Oct 31 '22 19:10

Neil Sarkar