diff --git a/runbot/runbot.py b/runbot/runbot.py
index 94918177..eea31e6e 100644
--- a/runbot/runbot.py
+++ b/runbot/runbot.py
@@ -182,7 +182,7 @@ class runbot_repo(osv.osv):
'jobs': fields.char('Jobs'),
'nginx': fields.boolean('Nginx'),
'auto': fields.boolean('Auto'),
- 'duplicate_id': fields.many2one('runbot.repo', 'Repository for finding duplicate builds'),
+ 'duplicate_id': fields.many2one('runbot.repo', 'Duplicate repo', help='Repository for finding duplicate builds'),
'modules': fields.char("Modules to Install", help="Comma-separated list of modules to install and test."),
'dependency_ids': fields.many2many(
'runbot.repo', 'runbot_repo_dep_rel',
@@ -221,26 +221,28 @@ class runbot_repo(osv.osv):
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
p2.communicate()[0]
- def github(self, cr, uid, ids, url, payload=None, delete=False, context=None):
+ def github(self, cr, uid, ids, url, payload=None, ignore_errors=False, context=None):
"""Return a http request to be sent to github"""
for repo in self.browse(cr, uid, ids, context=context):
- if not repo.token:
- raise Exception('Repository does not have a token to authenticate')
- match_object = re.search('([^/]+)/([^/]+)/([^/.]+(.git)?)', repo.base)
- if match_object:
- url = url.replace(':owner', match_object.group(2))
- url = url.replace(':repo', match_object.group(3))
- url = 'https://api.%s%s' % (match_object.group(1),url)
- session = requests.Session()
- session.auth = (repo.token,'x-oauth-basic')
- session.headers.update({'Accept': 'application/vnd.github.she-hulk-preview+json'})
- if payload:
- response = session.post(url, data=simplejson.dumps(payload))
- elif delete:
- response = session.delete(url)
+ try:
+ match_object = re.search('([^/]+)/([^/]+)/([^/.]+(.git)?)', repo.base)
+ if match_object:
+ url = url.replace(':owner', match_object.group(2))
+ url = url.replace(':repo', match_object.group(3))
+ url = 'https://api.%s%s' % (match_object.group(1),url)
+ session = requests.Session()
+ session.auth = (repo.token,'x-oauth-basic')
+ session.headers.update({'Accept': 'application/vnd.github.she-hulk-preview+json'})
+ if payload:
+ response = session.post(url, data=simplejson.dumps(payload))
+ else:
+ response = session.get(url)
+ return response.json()
+ except Exception:
+ if ignore_errors:
+ _logger.exception('Ignored github error %s %r', url, payload)
else:
- response = session.get(url)
- return response.json()
+ raise
def update(self, cr, uid, ids, context=None):
for repo in self.browse(cr, uid, ids, context=context):
@@ -261,14 +263,14 @@ class runbot_repo(osv.osv):
repo.git(['fetch', '-p', 'origin', '+refs/heads/*:refs/heads/*'])
repo.git(['fetch', '-p', 'origin', '+refs/pull/*/head:refs/pull/*'])
- fields = ['refname','objectname','committerdate:iso8601','authorname','subject','committername']
+ fields = ['refname','objectname','committerdate:iso8601','authorname','authoremail','subject','committername','committeremail']
fmt = "%00".join(["%("+field+")" for field in fields])
git_refs = repo.git(['for-each-ref', '--format', fmt, '--sort=-committerdate', 'refs/heads', 'refs/pull'])
git_refs = git_refs.strip()
refs = [[decode_utf(field) for field in line.split('\x00')] for line in git_refs.split('\n')]
- for name, sha, date, author, subject, committer in refs:
+ for name, sha, date, author, author_email, subject, committer, committer_email in refs:
# create or get branch
branch_ids = Branch.search(cr, uid, [('repo_id', '=', repo.id), ('name', '=', name)])
if branch_ids:
@@ -292,7 +294,9 @@ class runbot_repo(osv.osv):
'branch_id': branch.id,
'name': sha,
'author': author,
+ 'author_email': author_email,
'committer': committer,
+ 'committer_email': committer_email,
'subject': subject,
'date': dateutil.parser.parse(date[:19]),
'modules': ','.join(filter(None, [branch.repo_id.modules, branch.modules])),
@@ -468,7 +472,9 @@ class runbot_build(osv.osv):
'domain': fields.function(_get_domain, type='char', string='URL'),
'date': fields.datetime('Commit date'),
'author': fields.char('Author'),
+ 'author_email': fields.char('Author Email'),
'committer': fields.char('Committer'),
+ 'committer_email': fields.char('Committer Email'),
'subject': fields.text('Subject'),
'sequence': fields.integer('Sequence', select=1),
'modules': fields.char("Modules to Install"),
@@ -505,8 +511,6 @@ class runbot_build(osv.osv):
if len(duplicate_ids):
extra_info.update({'state': 'duplicate', 'duplicate_id': duplicate_ids[0]})
self.write(cr, uid, [duplicate_ids[0]], {'duplicate_id': build_id})
- if self.browse(cr, uid, duplicate_ids[0]).state != 'pending':
- self.github_status(cr, uid, [build_id])
self.write(cr, uid, [build_id], extra_info, context=context)
def reset(self, cr, uid, ids, context=None):
@@ -734,36 +738,27 @@ class runbot_build(osv.osv):
"""Notify github of failed/successful builds"""
runbot_domain = self.pool['runbot.repo'].domain(cr, uid)
for build in self.browse(cr, uid, ids, context=context):
- if build.state != 'duplicate' and build.duplicate_id:
- self.github_status(cr, uid, [build.duplicate_id.id], context=context)
desc = "runbot build %s" % (build.dest,)
- real_build = build.duplicate_id if build.state == 'duplicate' else build
- if real_build.state == 'testing':
- state = 'pending'
- elif real_build.state in ('running', 'done'):
- state = {
- 'ok': 'success',
- 'killed': 'error',
- }.get(real_build.result, 'failure')
+ if build.state in ('running', 'done'):
+ state = 'error'
+ if build.result == 'ok':
+ state = 'sucess'
+ if build.result == 'ko':
+ state = 'failure'
desc += " (runtime %ss)" % (real_build.job_time,)
else:
continue
-
status = {
"state": state,
"target_url": "http://%s/runbot/build/%s" % (runbot_domain, build.id),
"description": desc,
"context": "continuous-integration/runbot"
}
- try:
- build.repo_id.github('/repos/:owner/:repo/statuses/%s' % build.name, status)
- _logger.debug("github status %s update to %s", build.name, state)
- except Exception:
- _logger.exception("github status error")
+ _logger.debug("github updating status %s to %s", build.name, state)
+ build.repo_id.github('/repos/:owner/:repo/statuses/%s' % build.name, status, ignore_errors=True)
def job_10_test_base(self, cr, uid, build, lock_path, log_path):
build._log('test_base', 'Start test base module')
- build.github_status()
# checkout source
build.checkout()
# run base test
@@ -966,6 +961,7 @@ class runbot_build(osv.osv):
def _log(self, cr, uid, ids, func, message, context=None):
assert len(ids) == 1
+ _logger.debug("Build %s %s %s", ids[0], func, message)
self.pool['ir.logging'].create(cr, uid, {
'build_id': ids[0],
'level': 'INFO',
@@ -1269,8 +1265,6 @@ class RunbotController(http.Controller):
return request.not_found()
return werkzeug.utils.redirect(url)
-
-
# kill ` ps faux | grep ./static | awk '{print $2}' `
# ps faux| grep Cron | grep -- '-all' | awk '{print $2}' | xargs kill
# psql -l | grep " 000" | awk '{print $1}' | xargs -n1 dropdb
diff --git a/runbot/runbot.xml b/runbot/runbot.xml
index bed5594d..96500285 100644
--- a/runbot/runbot.xml
+++ b/runbot/runbot.xml
@@ -24,9 +24,7 @@
-
-
-
+
@@ -122,7 +120,9 @@
+
+
diff --git a/runbot_cla/__init__.py b/runbot_cla/__init__.py
new file mode 100644
index 00000000..ef0a414f
--- /dev/null
+++ b/runbot_cla/__init__.py
@@ -0,0 +1 @@
+import runbot
diff --git a/runbot_cla/__openerp__.py b/runbot_cla/__openerp__.py
new file mode 100644
index 00000000..3e43c1a9
--- /dev/null
+++ b/runbot_cla/__openerp__.py
@@ -0,0 +1,10 @@
+{
+ 'name': 'Runbot CLA',
+ 'category': 'Website',
+ 'summary': 'Runbot CLA',
+ 'version': '1.1',
+ 'description': "Runbot CLA",
+ 'author': 'Odoo SA',
+ 'depends': ['runbot'],
+ 'data': [ ],
+}
diff --git a/runbot_cla/runbot.py b/runbot_cla/runbot.py
new file mode 100644
index 00000000..7f822122
--- /dev/null
+++ b/runbot_cla/runbot.py
@@ -0,0 +1,38 @@
+# -*- encoding: utf-8 -*-
+
+import glob
+import logging
+import os
+import re
+
+import openerp
+
+_logger = logging.getLogger(__name__)
+
+class runbot_build(openerp.models.Model):
+ _inherit = "runbot.build"
+
+ def job_15_check_cla(self, cr, uid, build, lock_path, log_path):
+ cla_glob = build.path("doc/cla/*/*.md")
+ if cla_glob:
+ cla = ''.join(open(f).read() for f in glob.glob(cla_glob))
+ cla = cla.lower()
+ mo = re.search('[^ <@]+@[^ @>]+', build.author_email or '')
+ state = "failure"
+ if mo:
+ email = mo.group(0).lower()
+ if re.match('.*(odoo|openerp|tinyerp).com$',email):
+ state = "success"
+ if cla.find(mo.group(0).lower()) != -1:
+ state = "success"
+ status = {
+ "state": state,
+ "target_url": "http://www.odoo.com/sign-cla",
+ "description": "Odoo CLA",
+ "context": "legal/cla"
+ }
+ build._log('check_cla', 'Check CLA %s' % state)
+ build.repo_id.github('/repos/:owner/:repo/statuses/%s' % build.name, status, ignore_errors=True)
+ # 0 is myself, -1 is everybody else, -2 nothing
+ return -2
+