# -*- python -*-
# ex: set syntax=python:

# This is a sample buildmaster config file. It must be installed as
# 'master.cfg' in your buildmaster's base directory (although the filename
# can be changed with the --basedir option to 'mktap buildbot master').

# It has one job: define a dictionary named BuildmasterConfig. This
# dictionary has a variety of keys to control different aspects of the
# buildmaster. They are documented in docs/config.xhtml .


# This is the dictionary that the buildmaster pays attention to. We also use
# a shorter alias to save typing.
c = BuildmasterConfig = {}

####### BUILDSLAVES

# the 'slaves' list defines the set of allowable buildslaves. Each element is
# a BuildSlave object, which is created with bot-name, bot-password.  These
# correspond to values given to the buildslave's mktap invocation.
from buildbot.buildslave import BuildSlave
c['slaves'] = [BuildSlave("r0calcul5", "1MotDePasse!"),
               BuildSlave("r0calcul6", "1MotDePasse!"),
               BuildSlave("r0calcul7", "1MotDePasse!"),
               BuildSlave("r0calcul8", "1MotDePasse!"),
               BuildSlave("r0calcul9", "1MotDePasse!"),
               BuildSlave("r0calcul10", "1MotDePasse!")]

c['slavePortnum'] = 9989

####### CHANGESOURCES
#bm = {'lp:yade' : 'defaultBranch' }
from buildbot.changes.mail import BzrLaunchpadEmailMaildirSource
c['change_source'] = BzrLaunchpadEmailMaildirSource("/var/lib/buildbot/Maildir",
                                                    defaultBranch = None)


####### SCHEDULERS

## configure the Schedulers

from buildbot.scheduler import Scheduler, Nightly
c['schedulers'] = []
c['schedulers'].append(Scheduler(name="full", branch=None,
                                 treeStableTimer=5*60,
                                 builderNames=["yade-full"]))

c['schedulers'].append(Nightly(name="nightly", branch=None,
                                 hour=01,minute=23,
                                 builderNames=["yade-full"]))


#c['schedulers'].append(Nightly(name="nightly", branch=None,
#                                 hour=16,minute=55,
#                                 builderNames=["yade-full-test"]))
#
#c['schedulers'].append(Nightly(name="lucid64", branch=None,
#                                 hour=01,minute=23,
#                                 builderNames=["yade-full-lucid64"]))
#
####### BUILDERS

# the 'builders' list defines the Builders. Each one is configured with a
# dictionary, using the following keys:
#  name (required): the name used to describe this builder
#  slavename (required): which slave to use (must appear in c['bots'])
#  builddir (required): which subdirectory to run the builder in
#  factory (required): a BuildFactory to define how the build is run
#  periodicBuildTime (optional): if set, force a build every N seconds

from buildbot.process import factory
from buildbot.process.properties import WithProperties
from buildbot.steps.source import Bzr
from buildbot.steps.python_twisted import Trial
from buildbot.steps.shell import Compile
from buildbot.steps.shell import ShellCommand, RemoteCommand
from buildbot.steps.shell import Test
from buildbot.steps.transfer import DirectoryUpload, FileUpload
from buildbot.steps.master import MasterShellCommand

## nextSlave : choose the best buildslave
## we use nagios probe do determine which hosts is the bets.
import os
import subprocess


def nextSlave(builder, slaves):
    best = 0
    for slave in slaves:
        print slave
        mem = float(subprocess.Popen(["/usr/local/bin/check_nrpe", "-H", slave.slave.slavename, "-c", "check_freemem"],
                    stdout=subprocess.PIPE).communicate()[0].split("(")[1].split(")")[0].strip("M"))
        load = float(subprocess.Popen(["/usr/local/bin/check_nrpe", "-H", slave.slave.slavename, "-c", "check_load_buildbot"],
                    stdout=subprocess.PIPE).communicate()[0].split()[1].rstrip(',')) + 0.01
        score = mem/load
        if score > best :
            best = score
            selected = slave
    return selected


bzrurl = "lp:yade"

f1 = factory.BuildFactory()

# EIGEN3
prefix = "/home/buildbot/yade/yade-full"
f1.addStep(Bzr(repourl=bzrurl, mode="update"))
f1.addStep(Compile(description="Compiling with eigen3", command=["scons", "features=opengl,gts,openmp,vtk,qt4,cgal",
            "chunkSize=20", "jobs=4", "PREFIX=" + prefix]))
f1.addStep(Test(command=[WithProperties(prefix + "/bin/yade-bzr%(got_revision)s"), "--test"]))
f1.addStep(Test(command=[WithProperties(prefix + "/bin/yade-bzr%(got_revision)s"), "--checkall"], 
			description="checking eigen3 build", descriptionDone="checking eigen3 build done"))

# EIGEN3 - DEBUG
#f1.addStep(Compile(description="Compiling debug with eigen3", command=["scons", "features=opengl,gts,openmp,vtk,qt4,cgal",
#            "chunkSize=20", "jobs=4","debug=true", "PREFIX=" + prefix]))
#f1.addStep(Test(command=[WithProperties(prefix + "/bin/yade-bzr%(got_revision)s"), "--test"]))
#f1.addStep(Test(command=[WithProperties(prefix + "/bin/yade-bzr%(got_revision)s"), "--checkall"], 
#			description="checking eigen3 debug build", descriptionDone="checking eigen3 debug build done"))
#
# EIGEN2
f1.addStep(Compile(description="Compiling with eigen2", command=["scons", "features=opengl,gts,openmp,vtk,qt4,cgal",
            "chunkSize=20", "jobs=4", "PREFIX=" + prefix, "eigen2=true"]))
f1.addStep(Test(command=[WithProperties(prefix + "/bin/yade-bzr%(got_revision)s"), "--test"]))
f1.addStep(Test(command=[WithProperties(prefix + "/bin/yade-bzr%(got_revision)s"), "--checkall"], 
			description="checking eigen2 build", descriptionDone="checks eigen2 build done"))

# doc
wdir = prefix + "/build/doc/sphinx/"
texdir = wdir+"_build/latex/"
f1.addStep(ShellCommand(workdir=wdir, env={'PYTHONPATH':wdir},
                        command=["xvfb-run", WithProperties(prefix + "/bin/yade-bzr%(got_revision)s"), "yadeSphinx.py"],
                       description="compiling html doc", descriptionDone="html doc", haltOnFailure=True))
f1.addStep(ShellCommand(workdir= texdir, command=["xelatex", "Yade.tex"],
                        description="compiling pdf doc 1st pass", descriptionDone="pdf doc", haltOnFailure=True))
f1.addStep(ShellCommand(workdir= texdir, command=["xelatex", "Yade.tex"],
                        description="compiling pdf doc 2nd pass", descriptionDone="pdf doc (2)", haltOnFailure=True))
f1.addStep(DirectoryUpload(slavesrc="doc/sphinx/_build/html",
                           masterdest=WithProperties("/var/www/doc")))
f1.addStep(DirectoryUpload(slavesrc="doc/sphinx/_build/html",
                           masterdest=WithProperties("/var/www/doc/%(got_revision)s")))
f1.addStep(FileUpload(slavesrc=texdir+"Yade.pdf",
                      masterdest="/var/www/doc/Yade.pdf"))
f1.addStep(MasterShellCommand(command="chmod -R a-x+rX /var/www/doc"))

# tarball
f1.addStep(ShellCommand(workdir= prefix + "/build", command="/usr/bin/bzr export /tmp/yade"))
f1.addStep(ShellCommand(workdir="/tmp",command=["tar", "cvzf", "yade-src.tgz", "yade"]))
f1.addStep(FileUpload(slavesrc="/tmp/yade-src.tgz",
                      masterdest=WithProperties("/var/www/source/yade_r%(got_revision)s.tgz")))
f1.addStep(MasterShellCommand(command=["ln", "-sf", WithProperties("/var/www/source/yade_r%(got_revision)s.tgz") ,"/var/www/source/yade_latest_trunk.tgz"]))

# clean
f1.addStep(ShellCommand(command=["rm","-rf", WithProperties(prefix + "/build-bzr%(got_revision)s"),
                                WithProperties(prefix + "/bin/yade-bzr%(got_revision)s"),
                                "/tmp/yade",
                                WithProperties(prefix + "/bin/yade-bzr%(got_revision)s-batch"),
                                WithProperties(prefix + "/lib/yade-bzr%(got_revision)s")],
                        alwaysRun=True,
                        description="cleaning", descriptionDone="clean"))



b1 = {'name': "yade-full",
      'slavenames': ["r0calcul5", "r0calcul8", "r0calcul9", "r0calcul10"],
      'builddir': "yade-full",
      'factory': f1,
      'nextSlave': nextSlave,
      }

#b1-test =   {'name': "yade-full-test",
#            'slavenames': ["r0calcul5", "r0calcul8", "r0calcul9", "r0calcul10"],
#            'builddir': "yade-full-test",
#            'factory': f2,
#            'nextSlave': nextSlave,
#            }
#

c['builders'] = [b1]



####### STATUS TARGETS

# 'status' is a list of Status Targets. The results of each build will be
# pushed to these targets. buildbot/status/*.py has a variety to choose from,
# including web pages, email senders, and IRC bots.

c['status'] = []

# Use allowForce=True (boolean, not a string. ie: not 'True') to allow
# Forcing Builds in the Web User Interface. The default is False.
# from buildbot.status import html
# c['status'].append(html.WebStatus(http_port=8010,allowForce=True))

from buildbot.status import html
c['status'].append(html.WebStatus(http_port=8010,allowForce=True))

from zope.interface import implements
from buildbot.interfaces import IEmailLookup
import re
class MailLookup():
    implements(IEmailLookup)

    def getAddress(self,user):
        found = set()
        mailsrch =  re.compile("[a-zA-Z0-9\.\_\%\-\+]+@[a-zA-Z0-9\.\_\%\-]+.[a-zA-Z]{2,6}")
        found.update(mailsrch.findall(user))
        if len(found) : return found.pop()
        else : return None

email_lookup = MailLookup()

from buildbot.status import mail
c['status'].append(mail.MailNotifier(fromaddr="buildbot@yade-dem.org",
                                     extraRecipients=["remi.cailletaud@hmg.inpg.fr"],
                                     sendToInterestedUsers=True, lookup=email_lookup))

c['status'].append(mail.MailNotifier(fromaddr="buildbot@yade-dem.org",
                                     mode="failing",
                                     extraRecipients=["yade-dev@lists.launchpad.net"],
                                     sendToInterestedUsers=False))

#from buildbot.status import words
#irc = words.IRC("chat.eu.freenode.net", "ybb",
#                channels=["#yade-dev"],
#                port=8000,
#                password="1MotDePasse!",
#                notify_events={
#                'started': 1,
#                'finished': 1,
#                'exception': 1,
#                'successToFailure': 1,
#                'failureToSuccess': 1,
#                })
#c['status'].append(irc)
#
#
#c['status'].append(mail.MailNotifier(fromaddr="buildbot@yade-dem.org",builders=["yade-full-test"],
#                                     extraRecipients=["remi.cailletaud@hmg.inpg.fr"],
#                                     sendToInterestedUsers=True))


# from buildbot.status import client
# c['status'].append(client.PBListener(9988))


####### DEBUGGING OPTIONS

# if you set 'debugPassword', then you can connect to the buildmaster with
# the diagnostic tool in contrib/debugclient.py . From this tool, you can
# manually force builds and inject changes, which may be useful for testing
# your buildmaster without actually committing changes to your repository (or
# before you have a functioning 'sources' set up). The debug tool uses the
# same port number as the slaves do: 'slavePortnum'.

#c['debugPassword'] = "debugpassword"

# if you set 'manhole', you can ssh into the buildmaster and get an
# interactive python shell, which may be useful for debugging buildbot
# internals. It is probably only useful for buildbot developers. You can also
# use an authorized_keys file, or plain telnet.
#from buildbot import manhole
#c['manhole'] = manhole.PasswordManhole("tcp:9999:interface=127.0.0.1",
#                                       "admin", "password")


####### PROJECT IDENTITY

# the 'projectName' string will be used to describe the project that this
# buildbot is working on. For example, it is used as the title of the
# waterfall HTML page. The 'projectURL' string will be used to provide a link
# from buildbot HTML pages to your project's home page.

c['projectName'] = "Yade"
c['projectURL'] = "http://yade-dem.org"

# the 'buildbotURL' string should point to the location where the buildbot's
# internal web server (usually the html.Waterfall page) is visible. This
# typically uses the port number set in the Waterfall 'status' entry, but
# with an externally-visible host name which the buildbot cannot figure out
# without some help.

c['buildbotURL'] = "http://yade-dem.org/buildbot/"
