diff --git a/runbot/models/branch.py b/runbot/models/branch.py
index 6aea3c3f..64ef7748 100644
--- a/runbot/models/branch.py
+++ b/runbot/models/branch.py
@@ -87,6 +87,28 @@ class Branch(models.Model):
reference_name = f'{forced_version.name}---{reference_name}'
branch.reference_name = reference_name
+ def _match_errors_from_body(self):
+ """
+ Checks the pr_body for any reference to runbot errors and links the branch
+ to those errors if they exist.
+ """
+ self.ensure_one()
+ if not self.pr_body:
+ return
+ pr_body_regex = r'^.*runbot.*error[^\d]*(\d+)[ \S]*\r?$'
+ error_ids = re.findall(
+ pr_body_regex,
+ self.pr_body,
+ re.IGNORECASE | re.MULTILINE
+ )
+ # We need to check if they exist and search does nothing if error_ids is empty
+ errors = self.env['runbot.build.error'].sudo().search([
+ ('id', 'in', error_ids), ('fixing_pr_id', '=', False),
+ ])
+ errors.fixing_pr_id = self
+ for error in errors:
+ error.message_post(body='Fixing pr automatically set through PR message')
+
def _update_branch_infos(self, pull_info=None):
"""compute branch_url, pull_head_name and target_branch_name based on name"""
name_to_remote = {}
@@ -131,6 +153,7 @@ class Branch(models.Model):
owner, repo_name = pull_head_repo_name.split('/')
name_to_remote[pull_head_repo_name] = self.env['runbot.remote'].search([('owner', '=', owner), ('repo_name', '=', repo_name)], limit=1)
branch.pull_head_remote_id = name_to_remote[pull_head_repo_name]
+ branch._match_errors_from_body()
except (TypeError, AttributeError):
_logger.exception('Error for pr %s using pull_info %s', branch.name, pi)
raise
diff --git a/runbot/tests/test_branch.py b/runbot/tests/test_branch.py
index b4d478c6..66f0ef35 100644
--- a/runbot/tests/test_branch.py
+++ b/runbot/tests/test_branch.py
@@ -65,6 +65,44 @@ class TestBranch(RunbotCase):
self.Branch.search([('dname', '=', branch.dname)]),
)
+ def test_automatic_match_with_error(self):
+ self.env['runbot.build.error'].search([]).active = False
+ errors = self.env['runbot.build.error'].create([{} for _ in range(5)])
+ branch = self.Branch.create({
+ 'name': '18.0-test',
+ 'remote_id': self.remote_server.id,
+ 'is_pr': True,
+ })
+ # Does not crash without pr_body or nothing on pr_body
+ branch._match_errors_from_body()
+ branch.pr_body = ''
+ branch._match_errors_from_body()
+ # Does not link unknown errors
+ branch.pr_body = f'This is an error {errors[0].id}'
+ branch._match_errors_from_body()
+ self.assertFalse(errors.fixing_pr_id)
+ # Test multiple formats
+ branch.pr_body = f"""
+ Runbot error {errors[0].id}
+ runbot error {errors[1].id}
+ runbot-error-{errors[2].id}
+ https://domain.com/odoo/runbot.build.error/{errors[3].id}
+ https://domain.com/odoo/runbot-error/{errors[4].id}/
+ """
+ branch._match_errors_from_body()
+ self.assertTrue(all(e.fixing_pr_id == branch for e in errors))
+ # Test that it does not reassign
+ errors.fixing_pr_id = False
+ branch.pr_body = f'Runbot ERror {errors[0].id}'
+ other_branch = self.Branch.create({
+ 'name': 'other-branch',
+ 'remote_id': self.remote_server.id,
+ 'is_pr': True,
+ })
+ errors[0].fixing_pr_id = other_branch
+ branch._match_errors_from_body()
+ self.assertEqual(errors[0].fixing_pr_id, other_branch)
+
class TestBranchRelations(RunbotCase):
def setUp(self):
diff --git a/runbot/views/branch_views.xml b/runbot/views/branch_views.xml
index 42654aff..d19445aa 100644
--- a/runbot/views/branch_views.xml
+++ b/runbot/views/branch_views.xml
@@ -21,7 +21,7 @@
-
+
diff --git a/runbot/views/build_error_views.xml b/runbot/views/build_error_views.xml
index a0e66684..eb199732 100644
--- a/runbot/views/build_error_views.xml
+++ b/runbot/views/build_error_views.xml
@@ -468,6 +468,7 @@
runbot.build.error
list,form
{'search_default_not_fixed_errors': True, 'active_test': False}
+ runbot-error