[IMP] runbot_merge: inspectability of patch parsing

Show patch metadata on the patch screen, so it's easier to understand
what the parser sees in case of issues.

Behaviour is not *entirely* consisten, `file_ids` is correctly set but
it looks like during the initial `web_read` it gets stripped out in at
least some cases and the files list is empty even though files have
been found in the patch. nm.

Fixes #987
This commit is contained in:
Xavier Morel 2024-11-28 15:41:42 +01:00
parent 7f7589c50e
commit 38c2bc97f3
3 changed files with 73 additions and 15 deletions

View File

@ -17,7 +17,7 @@ from email import message_from_string, policy
from email.utils import parseaddr from email.utils import parseaddr
from typing import Union from typing import Union
from odoo import models, fields, api from odoo import models, fields, api, Command
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
from odoo.tools.mail import plaintext2html from odoo.tools.mail import plaintext2html
@ -122,6 +122,13 @@ class PatchFailure(Exception):
pass pass
class PatchFile(models.TransientModel):
_name = "runbot_merge.patch.file"
_description = "metadata for single file to patch"
name = fields.Char()
class Patch(models.Model): class Patch(models.Model):
_name = "runbot_merge.patch" _name = "runbot_merge.patch"
_inherit = ['mail.thread'] _inherit = ['mail.thread']
@ -137,6 +144,16 @@ class Patch(models.Model):
("format-patch", "format-patch"), ("format-patch", "format-patch"),
("show", "show"), ("show", "show"),
], compute="_compute_patch_meta") ], compute="_compute_patch_meta")
author = fields.Char(compute="_compute_patch_meta")
# TODO: should be a datetime, parse date
authordate = fields.Char(compute="_compute_patch_meta")
committer = fields.Char(compute="_compute_patch_meta")
# TODO: should be a datetime, parse date
commitdate = fields.Char(compute="_compute_patch_meta")
file_ids = fields.One2many(
"runbot_merge.patch.file",
compute="_compute_patch_meta",
)
message = fields.Text(compute="_compute_patch_meta") message = fields.Text(compute="_compute_patch_meta")
_sql_constraints = [ _sql_constraints = [
@ -145,13 +162,37 @@ class Patch(models.Model):
@api.depends("patch") @api.depends("patch")
def _compute_patch_meta(self) -> None: def _compute_patch_meta(self) -> None:
File = self.env['runbot_merge.patch.file']
for p in self: for p in self:
if r := p._parse_patch(): if r := p._parse_patch():
p.format = r.kind p.format = r.kind
match r.author:
case [name, email]:
p.author = f"{name} <{email}>"
case [name, email, date]:
p.author = f"{name} <{email}>"
p.authordate = date
match r.committer:
case [name, email]:
p.committer = f"{name} <{email}>"
case [name, email, date]:
p.committer = f"{name} <{email}>"
p.commitdate = date
p.file_ids = File.concat(*(
File.new({'name': m['file_from']})
for m in FILE_PATTERN.finditer(p.patch)
))
p.message = r.message p.message = r.message
else: else:
p.format = False p.update({
p.message = False 'format': False,
'author': False,
'authordate': False,
'committer': False,
'commitdate': False,
'file_ids': False,
'message': False,
})
def _parse_patch(self) -> ParseResult | None: def _parse_patch(self) -> ParseResult | None:
if not self.patch: if not self.patch:

View File

@ -32,4 +32,5 @@ access_runbot_merge_review_rights_2,Users can see partners,model_res_partner_rev
access_runbot_merge_review_override_2,Users can see partners,model_res_partner_override,base.group_user,1,0,0,0 access_runbot_merge_review_override_2,Users can see partners,model_res_partner_override,base.group_user,1,0,0,0
access_runbot_merge_pull_requests_feedback_template,access_runbot_merge_pull_requests_feedback_template,runbot_merge.model_runbot_merge_pull_requests_feedback_template,base.group_system,1,1,0,0 access_runbot_merge_pull_requests_feedback_template,access_runbot_merge_pull_requests_feedback_template,runbot_merge.model_runbot_merge_pull_requests_feedback_template,base.group_system,1,1,0,0
access_runbot_merge_patch,Patcher access,runbot_merge.model_runbot_merge_patch,runbot_merge.group_patcher,1,1,1,0 access_runbot_merge_patch,Patcher access,runbot_merge.model_runbot_merge_patch,runbot_merge.group_patcher,1,1,1,0
access_runbot_merge_patch_file,Patcher access to patch file,model_runbot_merge_patch_file,runbot_merge.group_patcher,1,0,0,0
access_runbot_merge_backport_admin,Admin access to backport wizard,model_runbot_merge_pull_requests_backport,runbot_merge.group_admin,1,1,1,0 access_runbot_merge_backport_admin,Admin access to backport wizard,model_runbot_merge_pull_requests_backport,runbot_merge.group_admin,1,1,1,0

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
32 access_runbot_merge_review_override_2 Users can see partners model_res_partner_override base.group_user 1 0 0 0
33 access_runbot_merge_pull_requests_feedback_template access_runbot_merge_pull_requests_feedback_template runbot_merge.model_runbot_merge_pull_requests_feedback_template base.group_system 1 1 0 0
34 access_runbot_merge_patch Patcher access runbot_merge.model_runbot_merge_patch runbot_merge.group_patcher 1 1 1 0
35 access_runbot_merge_patch_file Patcher access to patch file model_runbot_merge_patch_file runbot_merge.group_patcher 1 0 0 0
36 access_runbot_merge_backport_admin Admin access to backport wizard model_runbot_merge_pull_requests_backport runbot_merge.group_admin 1 1 1 0

View File

@ -122,20 +122,36 @@
<field name="active"/> <field name="active"/>
</group> </group>
</group> </group>
<group invisible="patch and not commit"> <notebook>
<group colspan="4"> <page string="commit" invisible="patch and not commit">
<field name="commit"/> <group colspan="4">
</group> <field name="commit"/>
</group> </group>
<group invisible="commit and not patch"> </page>
<group colspan="4"> <page string="patch" invisible="commit and not patch">
<field name="format" colspan="4"/> <field name="patch" widget="ace" nolabel="1" colspan="2"/>
<field name="patch" widget="ace"/>
<!-- no diff/patch mode support --> <!-- no diff/patch mode support -->
<!-- options="{'mode': 'patch'}"/> --> <!-- options="{'mode': 'patch'}"/> -->
<field name="message" colspan="4"/> <group colspan="4" string="metadata">
</group> <group>
</group> <field name="format"/>
</group>
<group>
<field name="author"/>
<field name="authordate" invisible="not authordate"/>
<field name="committer" invisible="not committer"/>
<field name="commitdate" invisible="not commitdate"/>
</group>
<separator string="message" cols="4"/>
<field name="message" nolabel="1"/>
<field name="file_ids" nolabel="1">
<tree>
<field name="display_name" string="File Name"/>
</tree>
</field>
</group>
</page>
</notebook>
</sheet> </sheet>
<div class="oe_chatter"> <div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/> <field name="message_follower_ids" widget="mail_followers"/>