mirror of
https://github.com/odoo/runbot.git
synced 2025-03-27 13:25:47 +07:00
[FIX] runbot: send status only once.
Runbot can send status multiple time for the same hash: - if transaction fails in scheduler and is retried - if multiple subbuild are failing Leading to multiple issues: - when github receive more than one failure status, mergebot will be notified multiple times and send multiple mail (for forward ports mainly) - github will answer `422 Unprocessable Entity for url...` after 1000 status. This fix proposes to limit number of status: - By avoiding to send status for orphan build (parent status will never change) - By storing last send status to avoid to notify multiple time - By sending status post commit to avoid to contact github in case of failure. This will also slightly reduce transaction time by removing an http request.
This commit is contained in:
parent
b517df4ff0
commit
3bf9b263f0
@ -12,7 +12,7 @@ from ..common import dt2time, fqdn, now, grep, local_pgadmin_cursor, s2human, Co
|
|||||||
from ..container import docker_build, docker_stop, docker_state, Command
|
from ..container import docker_build, docker_stop, docker_state, Command
|
||||||
from ..fields import JsonDictField
|
from ..fields import JsonDictField
|
||||||
from odoo.addons.runbot.models.repo import RunbotException
|
from odoo.addons.runbot.models.repo import RunbotException
|
||||||
from odoo import models, fields, api
|
from odoo import models, fields, api, registry
|
||||||
from odoo.exceptions import UserError, ValidationError
|
from odoo.exceptions import UserError, ValidationError
|
||||||
from odoo.http import request
|
from odoo.http import request
|
||||||
from odoo.tools import appdirs
|
from odoo.tools import appdirs
|
||||||
@ -89,6 +89,7 @@ class runbot_build(models.Model):
|
|||||||
global_result = fields.Selection(make_selection(result_order), string='Result', compute='_compute_global_result', store=True)
|
global_result = fields.Selection(make_selection(result_order), string='Result', compute='_compute_global_result', store=True)
|
||||||
local_result = fields.Selection(make_selection(result_order), string='Build Result')
|
local_result = fields.Selection(make_selection(result_order), string='Build Result')
|
||||||
triggered_result = fields.Selection(make_selection(result_order), string='Triggered Result') # triggered by db only
|
triggered_result = fields.Selection(make_selection(result_order), string='Triggered Result') # triggered by db only
|
||||||
|
last_github_state = fields.Char('Last github status', readonly=True)
|
||||||
|
|
||||||
requested_action = fields.Selection([('wake_up', 'To wake up'), ('deathrow', 'To kill')], string='Action requested', index=True)
|
requested_action = fields.Selection([('wake_up', 'To wake up'), ('deathrow', 'To kill')], string='Action requested', index=True)
|
||||||
|
|
||||||
@ -1040,19 +1041,36 @@ class runbot_build(models.Model):
|
|||||||
"""Notify each repo with a status"""
|
"""Notify each repo with a status"""
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
if self.config_id.update_github_state:
|
if self.config_id.update_github_state:
|
||||||
repos = {b.repo_id for b in self.search([('name', '=', self.name)])}
|
repos_ids = {b.repo_id.id for b in self.search([('name', '=', self.name)])}
|
||||||
for repo in repos:
|
build_name = self.name
|
||||||
_logger.debug("github updating %s status %s to %s in repo %s", status['context'], self.name, status['state'], repo.name)
|
user_id = self.env.user.id
|
||||||
|
_dbname = self.env.cr.dbname
|
||||||
|
_context = self.env.context
|
||||||
|
build_id = self.id
|
||||||
|
def send_github_status():
|
||||||
try:
|
try:
|
||||||
repo._github('/repos/:owner/:repo/statuses/%s' % self.name, status, ignore_errors=True)
|
db_registry = registry(_dbname)
|
||||||
except Exception:
|
with api.Environment.manage(), db_registry.cursor() as cr:
|
||||||
self._log('_github_status_notify_all', 'Status notification failed for "%s" in repo "%s"' % (self.name, repo.name))
|
env = api.Environment(cr, user_id, _context)
|
||||||
|
repos = env['runbot.repo'].browse(repos_ids)
|
||||||
|
for repo in repos:
|
||||||
|
_logger.debug(
|
||||||
|
"github updating %s status %s to %s in repo %s",
|
||||||
|
status['context'], build_name, status['state'], repo.name)
|
||||||
|
repo._github('/repos/:owner/:repo/statuses/%s' % build_name, status, ignore_errors=True)
|
||||||
|
except:
|
||||||
|
_logger.exception('Something went wrong sending notification for %s', build_id)
|
||||||
|
self._cr.after('commit', send_github_status)
|
||||||
|
|
||||||
|
|
||||||
def _github_status(self):
|
def _github_status(self):
|
||||||
"""Notify github of failed/successful builds"""
|
"""Notify github of failed/successful builds"""
|
||||||
for build in self:
|
for build in self:
|
||||||
if build.parent_id:
|
if build.parent_id:
|
||||||
build.parent_id._github_status()
|
if build.orphan_result:
|
||||||
|
_logger.debug('Skipping result for orphan build %s', self.id)
|
||||||
|
else:
|
||||||
|
build.parent_id._github_status()
|
||||||
elif build.config_id.update_github_state:
|
elif build.config_id.update_github_state:
|
||||||
runbot_domain = self.env['runbot.repo']._domain()
|
runbot_domain = self.env['runbot.repo']._domain()
|
||||||
desc = "runbot build %s" % (build.dest,)
|
desc = "runbot build %s" % (build.dest,)
|
||||||
@ -1076,7 +1094,11 @@ class runbot_build(models.Model):
|
|||||||
"description": desc,
|
"description": desc,
|
||||||
"context": "ci/runbot"
|
"context": "ci/runbot"
|
||||||
}
|
}
|
||||||
build._github_status_notify_all(status)
|
if self.last_github_state != state:
|
||||||
|
build._github_status_notify_all(status)
|
||||||
|
self.last_github_state = state
|
||||||
|
else:
|
||||||
|
_logger.debug('Skipping unchanged status for %s', self.id)
|
||||||
|
|
||||||
def _next_job_values(self):
|
def _next_job_values(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
|
Loading…
Reference in New Issue
Block a user