mirror of
https://github.com/odoo/runbot.git
synced 2025-03-15 23:45:44 +07:00
[IMP] runbot: documentation and views imps
Add a small documentation for users, mainly about teams and codeowners. Improves some views and hide some menu_items to keep interface easier to navigate.
This commit is contained in:
parent
ada69222c9
commit
c83f89fc23
@ -32,6 +32,7 @@ def route(routes, **kw):
|
||||
refresh = kwargs.get('refresh', False)
|
||||
nb_build_errors = request.env['runbot.build.error'].search_count([('random', '=', True), ('parent_id', '=', False)])
|
||||
nb_assigned_errors = request.env['runbot.build.error'].search_count([('responsible', '=', request.env.user.id)])
|
||||
nb_team_errors = request.env['runbot.build.error'].search_count([('responsible', '=', False), ('team_id', 'in', request.env.user.runbot_team_ids.ids)])
|
||||
kwargs['more'] = more
|
||||
kwargs['projects'] = projects
|
||||
|
||||
@ -60,6 +61,7 @@ def route(routes, **kw):
|
||||
response.qcontext['title'] = 'Runbot %s' % project.name or ''
|
||||
response.qcontext['nb_build_errors'] = nb_build_errors
|
||||
response.qcontext['nb_assigned_errors'] = nb_assigned_errors
|
||||
response.qcontext['nb_team_errors'] = nb_team_errors
|
||||
return response
|
||||
return response_wrap
|
||||
return decorator
|
||||
@ -390,6 +392,17 @@ class Runbot(Controller):
|
||||
}
|
||||
return request.render(view_id if view_id else "runbot.monitoring", qctx)
|
||||
|
||||
@route(['/runbot/errors/assign/<int:build_error_id>'
|
||||
], type='http', auth='user', methods=['POST'], csrf=False, sitemap=False)
|
||||
def build_errors_assign(self, build_error_id=None, **kwargs):
|
||||
build_error = request.env['runbot.build.error'].browse(build_error_id)
|
||||
if build_error.responsible:
|
||||
return build_error.responsible.name
|
||||
if request.env.user._is_internal():
|
||||
build_error.sudo().responsible = request.env.user
|
||||
return request.env.user.name
|
||||
return 'Error'
|
||||
|
||||
@route(['/runbot/errors',
|
||||
'/runbot/errors/page/<int:page>'
|
||||
], type='http', auth='user', website=True, sitemap=False)
|
||||
@ -409,9 +422,11 @@ class Runbot(Controller):
|
||||
|
||||
current_user_errors = request.env['runbot.build.error'].search([
|
||||
('responsible', '=', request.env.user.id),
|
||||
('parent_id', '=', False),
|
||||
], order='last_seen_date desc, build_count desc')
|
||||
|
||||
current_team_errors = request.env['runbot.build.error'].search([
|
||||
('responsible', '=', False),
|
||||
('team_id', 'in', request.env.user.runbot_team_ids.ids)
|
||||
], order='last_seen_date desc, build_count desc')
|
||||
domain = [('parent_id', '=', False), ('responsible', '!=', request.env.user.id), ('build_count', '>', 1)]
|
||||
build_errors_count = request.env['runbot.build.error'].search_count(domain)
|
||||
url_args = {}
|
||||
@ -422,10 +437,12 @@ class Runbot(Controller):
|
||||
|
||||
qctx = {
|
||||
'current_user_errors': current_user_errors,
|
||||
'current_team_errors': current_team_errors,
|
||||
'build_errors': build_errors,
|
||||
'title': 'Build Errors',
|
||||
'sort_order_choices': sort_order_choices,
|
||||
'pager': pager
|
||||
'page': page,
|
||||
'pager': pager,
|
||||
}
|
||||
return request.render('runbot.build_error', qctx)
|
||||
|
||||
|
51
runbot/documentation/codeowner.md
Normal file
51
runbot/documentation/codeowner.md
Normal file
@ -0,0 +1,51 @@
|
||||
# Teams and Codeowner
|
||||
|
||||
## How
|
||||
|
||||
Codeowner is using two way to define which team should be notified when a file is modified:
|
||||
|
||||
- Module ownership to link a module to a team. (Editable by team manager)
|
||||
- Regexes, to target specific files or more specific rules. (Editable by runbot admin)
|
||||
|
||||
For each file, the codeowner will check all regexes and all module ownership.
|
||||
If a module ownersip is a `fallback`, the team won't be added as a reviewer if any previous rule matched for a file.
|
||||
If no reviewer is found for a file, a fallback github team is added as reviewer.
|
||||
|
||||
The codeowner is not applied on draft pull request (and will give a red ci as a reminder)
|
||||
A pr is considered draft if:
|
||||
|
||||
- marked as draft on github
|
||||
- contains `[DRAFT]` or `[WIP]` in the title
|
||||
- is linked to any other draft pr (in the same bundle)
|
||||
|
||||
The codeowner is not applied on forwardport initial push. Any following push (conflict resolution) will trigger the codeowner again.
|
||||
|
||||
## Module ownership
|
||||
|
||||
Module ownership links a module to a team with an additionnal `is_fallback` flag to define if the codeowner should only be triggered if no one else was added for a file.
|
||||
|
||||
Module ownership is also a way to define which team should be contacted for some question on a module.
|
||||
|
||||
Module coverage should idealy reach 100% with module ownership. Having all files covered allows to ensure that at least one reviewer will be added when a pr is open (mainly for external contributors). This can sometimes generate to much github notifications, this is why it is important to configure members, create subteams, and skip pr policy.
|
||||
|
||||
## Team management
|
||||
|
||||
Team managers can be anyone from the team with a basic knowledge of the guidelines to follow and a good understanding of the system.
|
||||
|
||||
Team manager can modify.
|
||||
|
||||
- Teams
|
||||
- Module ownership
|
||||
- Github account of users
|
||||
|
||||
Some basic config can be done on Teams
|
||||
|
||||
- `Github team`: the corresponding github team to add as reviewer
|
||||
- `Github logins`: additional github logins in the github team, mainly for github users no listed in the members of the runbot team. Mainly usefull if `Skip team pr` is checked. This list can be updated automatically using the `Fetch members` action. This field can also be manually modified to avoid being notified by some github login, even if it is adviced to add them as a `Team members` if they have an internal user.
|
||||
- `Skip team pr`: If checked, don't add the team as reviewer if the pr was oppened by one of the members of the team.
|
||||
- `Module Ownership`: The list of modules owned by the team. `Fallback` options can be edited from there but it is adviced to use the `Modules` or `Module ownership` menu to add or remove a module, mainly to avoid removing all ownership from a module.
|
||||
- `Team members`: the members of the team. Those members will see a link to the team dashboard and team errors count will be displayed on main page
|
||||
|
||||
## Disable codeowner on demand
|
||||
|
||||
In some rare cases, if a pr modifies a lot of files in an almost automated way, it can be useful to disable the codeowner. This can be done on a bundle. Note that forwardport won't be impacted, and this should be done per forwardport in case of conflict.
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB |
3
runbot/documentation/readme.md
Normal file
3
runbot/documentation/readme.md
Normal file
@ -0,0 +1,3 @@
|
||||
# User documentation
|
||||
|
||||
- [Teams and codeowner](codeowner.md)
|
@ -120,7 +120,7 @@ class BuildError(models.Model):
|
||||
@api.depends('content')
|
||||
def _compute_summary(self):
|
||||
for build_error in self:
|
||||
build_error.summary = build_error.content[:50]
|
||||
build_error.summary = build_error.content[:80]
|
||||
|
||||
@api.depends('build_ids', 'child_ids.build_ids')
|
||||
def _compute_children_build_ids(self):
|
||||
|
@ -7,7 +7,7 @@ from odoo.exceptions import ValidationError
|
||||
|
||||
class Codeowner(models.Model):
|
||||
_name = 'runbot.codeowner'
|
||||
_description = "Notify github teams based on filenames regex"
|
||||
_description = "Codeowner regex"
|
||||
_inherit = "mail.thread"
|
||||
|
||||
project_id = fields.Many2one('runbot.project', required=True, default=lambda self: self.env.ref('runbot.main_project', raise_if_not_found=False))
|
||||
|
@ -14,12 +14,12 @@ class Dockerfile(models.Model):
|
||||
name = fields.Char('Dockerfile name', required=True, help="Name of Dockerfile")
|
||||
image_tag = fields.Char(compute='_compute_image_tag', store=True)
|
||||
template_id = fields.Many2one('ir.ui.view', string='Docker Template', domain=[('type', '=', 'qweb')], context={'default_type': 'qweb', 'default_arch_base': '<t></t>'})
|
||||
arch_base = fields.Text(related='template_id.arch_base', readonly=False)
|
||||
arch_base = fields.Text(related='template_id.arch_base', readonly=False, related_sudo=True)
|
||||
dockerfile = fields.Text(compute='_compute_dockerfile', tracking=True)
|
||||
to_build = fields.Boolean('To Build', help='Build Dockerfile. Check this when the Dockerfile is ready.', default=False)
|
||||
version_ids = fields.One2many('runbot.version', 'dockerfile_id', string='Versions')
|
||||
description = fields.Text('Description')
|
||||
view_ids = fields.Many2many('ir.ui.view', compute='_compute_view_ids')
|
||||
view_ids = fields.Many2many('ir.ui.view', compute='_compute_view_ids', groups="runbot.group_runbot_admin")
|
||||
project_ids = fields.One2many('runbot.project', 'dockerfile_id', string='Default for Projects')
|
||||
bundle_ids = fields.One2many('runbot.bundle', 'dockerfile_id', string='Used in Bundles')
|
||||
|
||||
@ -37,7 +37,7 @@ class Dockerfile(models.Model):
|
||||
def _compute_dockerfile(self):
|
||||
for rec in self:
|
||||
try:
|
||||
res = rec.template_id._render() if rec.template_id else ''
|
||||
res = rec.template_id.sudo()._render() if rec.template_id else ''
|
||||
rec.dockerfile = re.sub(r'^\s*$', '', res, flags=re.M).strip()
|
||||
except QWebException:
|
||||
rec.dockerfile = ''
|
||||
|
@ -26,3 +26,8 @@ class ResUsers(models.Model):
|
||||
if list(values.keys()) == ['github_login'] and self.env.user.has_group('runbot.group_runbot_team_manager'):
|
||||
return super(ResUsers, self.sudo()).write(values)
|
||||
return super().write(values)
|
||||
|
||||
# backport of 16.0 feature TODO remove after migration
|
||||
def _is_internal(self):
|
||||
self.ensure_one()
|
||||
return not self.sudo().share
|
||||
|
@ -19,6 +19,7 @@ class RunbotTeam(models.Model):
|
||||
_name = 'runbot.team'
|
||||
_description = "Runbot Team"
|
||||
_order = 'name, id'
|
||||
_inherit = 'mail.thread'
|
||||
|
||||
name = fields.Char('Team', required=True)
|
||||
project_id = fields.Many2one('runbot.project', 'Project', help='Project to monitor', required=True,
|
||||
@ -34,10 +35,11 @@ class RunbotTeam(models.Model):
|
||||
'e.g.: `*website*,-*website_sale*`'
|
||||
)
|
||||
module_ownership_ids = fields.One2many('runbot.module.ownership', 'team_id')
|
||||
codeowner_ids = fields.One2many('runbot.codeowner', 'team_id')
|
||||
upgrade_exception_ids = fields.One2many('runbot.upgrade.exception', 'team_id', string='Team Upgrade Exceptions')
|
||||
github_team = fields.Char('Github team')
|
||||
github_logins = fields.Char('Github logins', help='Additional github logins, prefer adding the login on the member of the team')
|
||||
skip_team_pr = fields.Boolean('Skip team pr', help="Don't add codeowner if pr was created by a member of the team")
|
||||
github_team = fields.Char('Github team', tracking=True)
|
||||
github_logins = fields.Char('Github logins', help='Additional github logins, prefer adding the login on the member of the team', tracking=True)
|
||||
skip_team_pr = fields.Boolean('Skip team pr', help="Don't add codeowner if pr was created by a member of the team", tracking=True)
|
||||
|
||||
@api.model_create_single
|
||||
def create(self, values):
|
||||
|
@ -9,14 +9,21 @@
|
||||
return;
|
||||
}
|
||||
var xhr = new XMLHttpRequest();
|
||||
var url = e.target.href
|
||||
if (data.runbotBuild) {
|
||||
url = '/runbot/build/' + data.runbotBuild + '/' + operation
|
||||
}
|
||||
var elem = e.target
|
||||
xhr.addEventListener('load', function () {
|
||||
if (operation == 'rebuild' && window.location.href.split('?')[0].endsWith('/build/' + data.runbotBuild)){
|
||||
window.location.href = window.location.href.replace('/build/' + data.runbotBuild, '/build/' + xhr.responseText);
|
||||
} else if (operation == 'action') {
|
||||
elem.parentElement.innerText = this.responseText
|
||||
} else {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
xhr.open('POST', '/runbot/build/' + data.runbotBuild + '/' + operation);
|
||||
xhr.open('POST', url);
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
@ -8,9 +8,7 @@
|
||||
<div class="row">
|
||||
<div class="col">Last seen date</div>
|
||||
<div class="col col-md-3">Module</div>
|
||||
<div class="col col-md-3">Summary</div>
|
||||
<div class="col">Nb Seen</div>
|
||||
<div class="col">Random</div>
|
||||
<div class="col col-md-5">Summary</div>
|
||||
<div class="col">Assigned to</div>
|
||||
<div class="col">&nbsp;</div>
|
||||
</div>
|
||||
@ -22,24 +20,23 @@
|
||||
<div class="row">
|
||||
<div class="col"><t t-esc="build_error.last_seen_date" t-options='{"widget": "datetime"}'/></div>
|
||||
<div class="col col-md-3"><t t-esc="build_error.module_name"/></div>
|
||||
<div class="col col-md-3">
|
||||
<div class="col col-md-5">
|
||||
<button class="btn btn-link" type="button" data-toggle="collapse" t-attf-data-target="#collapse{{build_error.id}}" aria-expanded="true" aria-controls="collapseOne">
|
||||
<i class="fa fa-minus"/>
|
||||
</button>
|
||||
<code><t t-esc="build_error.summary"/></code>
|
||||
</div>
|
||||
<div class="col">
|
||||
<t t-esc="build_error.build_count"/>
|
||||
<t t-if="build_error.responsible" t-esc="build_error.responsible.name"/>
|
||||
<a t-else="" t-attf-href="/runbot/errors/assign/{{build_error.id}}" data-runbot="action" role="button" class="btn btn-primary btn-sm">Assign to me</a>
|
||||
</div>
|
||||
<div class="col">
|
||||
<i t-if="build_error.random" class="fa fa-random"/>
|
||||
</div>
|
||||
<div class="col"><t t-esc="build_error.responsible.name"/></div>
|
||||
<div class="col">
|
||||
<a groups="base.group_user" t-attf-href="/web/#id={{build_error.id}}&view_type=form&model=runbot.build.error&menu_id={{env.ref('runbot.runbot_menu_root').id}}" target="new" title="View in Backend">
|
||||
<i class="fa fa-list"/>
|
||||
</a>
|
||||
<a t-att-href="build_error.last_seen_build_id.build_url" t-attf-title="View last affected build ({{build_error.last_seen_build_id.id}})"><i class="fa fa-external-link"/></a>
|
||||
<a groups="base.group_user" t-attf-href="/web/#id={{build_error.id}}&view_type=form&model=runbot.build.error&menu_id={{env.ref('runbot.runbot_menu_root').id}}" target="new" title="View in Backend">
|
||||
<span class="badge badge-info" t-esc="build_error.build_count" t-attf-title="This error was seen {{build_error.build_count}} View in backend"/>
|
||||
</a>
|
||||
<span groups="!base.group_user" class="badge badge-info" t-esc="build_error.build_count" t-attf-title="This error was seen {{build_error.build_count}}"/>
|
||||
<span class="fa fa-random" t-if="build_error.random"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -59,16 +56,25 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class='col-md-12'>
|
||||
<h3>Your assigned bug on Runbot Builds</h3>
|
||||
<t t-call="runbot.build_error_cards">
|
||||
<t t-set="build_errors" t-value="current_user_errors"/>
|
||||
<t t-set="accordion_id">user_errors</t>
|
||||
<t t-if="page==1 and current_user_errors">
|
||||
<h4>Your assigned build errors</h4>
|
||||
<t t-call="runbot.build_error_cards">
|
||||
<t t-set="build_errors" t-value="current_user_errors"/>
|
||||
<t t-set="accordion_id">user_errors</t>
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="page==1 and current_team_errors">
|
||||
<h4>Team unassigned build errors</h4>
|
||||
<t t-call="runbot.build_error_cards">
|
||||
<t t-set="build_errors" t-value="current_team_errors"/>
|
||||
<t t-set="accordion_id">user_errors</t>
|
||||
</t>
|
||||
</t>
|
||||
<h3>Current Bugs on Runbot Builds</h3>
|
||||
<t t-if="build_errors">
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<div class="dropdown mr-auto">
|
||||
<nav class="navbar navbar-expand-lg navbar-light">
|
||||
<h4 class="d-inline"> All builds errors</h4>
|
||||
<span class="ml-auto">
|
||||
<span class="dropdown mr-auto">
|
||||
<a role="button" href="#" class="dropdown-toggle btn btn-secondary" data-toggle="dropdown">
|
||||
Sort By: <t t-esc="request.params.get('sort', '')"/>
|
||||
</a>
|
||||
@ -77,12 +83,12 @@
|
||||
<a role="menuitem" class="dropdown-item" t-attf-href="/runbot/errors?sort={{sort_choice}}"><t t-esc="sort_order_choices[sort_choice]"/></a>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<span class="ml-auto">
|
||||
<t t-call="website.pager" />
|
||||
</span>
|
||||
</nav>
|
||||
</div>
|
||||
</span>
|
||||
<span class="ml-auto">
|
||||
<t t-call="website.pager" />
|
||||
</span>
|
||||
</nav>
|
||||
|
||||
<t t-call="runbot.build_error_cards">
|
||||
<t t-set="build_errors" t-value="build_errors"/>
|
||||
|
@ -137,13 +137,26 @@
|
||||
</template>
|
||||
|
||||
<template id="runbot.build_errors_link">
|
||||
<t t-if="nb_assigned_errors and nb_assigned_errors > 0">
|
||||
<t t-if="nb_assigned_errors">
|
||||
<li class="nav-item divider"/>
|
||||
<li class="nav-item">
|
||||
<a href="/runbot/errors" class="nav-link text-danger" t-attf-title="You have {{nb_assigned_errors}} random bug assigned"><i class="fa fa-bug"/><t t-esc="nb_assigned_errors"/></a>
|
||||
<a href="/runbot/errors" class="nav-link text-danger" t-attf-title="You have {{nb_assigned_errors}} random bug assigned">
|
||||
<i class="fa fa-bug"/>
|
||||
<t t-esc="nb_assigned_errors"/>
|
||||
<span class="text-warning" t-if="nb_team_errors">+<t t-esc="nb_team_errors"/></span>
|
||||
</a>
|
||||
</li>
|
||||
</t>
|
||||
<t t-elif="nb_build_errors and nb_build_errors > 0">
|
||||
<t t-elif="nb_team_errors">
|
||||
<li class="nav-item divider"/>
|
||||
<li class="nav-item">
|
||||
<a href="/runbot/errors" class="nav-link text-warning" t-attf-title="Your team has {{nb_team_errors}} random bug assigned">
|
||||
<i class="fa fa-bug"/>
|
||||
<t t-esc="nb_team_errors"/>
|
||||
</a>
|
||||
</li>
|
||||
</t>
|
||||
<t t-elif="nb_build_errors">
|
||||
<li class="nav-item divider"/>
|
||||
<li class="nav-item">
|
||||
<a href="/runbot/errors" class="nav-link" title="Random Bugs"><i class="fa fa-bug"/></a>
|
||||
|
@ -14,12 +14,6 @@
|
||||
<field name="skip_team_pr"/>
|
||||
<field name="dashboard_id"/>
|
||||
<field name="path_glob"/>
|
||||
<field name="module_ownership_ids">
|
||||
<tree>
|
||||
<field name="module_id" readonly="1"/>
|
||||
<field name="is_fallback" widget="boolean_toggle"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Team Members">
|
||||
@ -33,8 +27,27 @@
|
||||
<page string="Team Errors">
|
||||
<field name="build_error_ids" nolabel="1" widget="many2many" options="{'not_delete': True, 'no_create': True}"/>
|
||||
</page>
|
||||
<page string="Modules">
|
||||
<field name="module_ownership_ids">
|
||||
<tree create="0" delete="0">
|
||||
<field name="module_id" readonly="1"/>
|
||||
<field name="is_fallback" widget="boolean_toggle"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Codeowners">
|
||||
<field name="codeowner_ids">
|
||||
</field>
|
||||
</page>
|
||||
|
||||
|
||||
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -25,7 +25,7 @@
|
||||
<page string="Dockerfile">
|
||||
<field name="dockerfile"/>
|
||||
</page>
|
||||
<page string="Views">
|
||||
<page string="Views" groups="runbot.group_runbot_admin">
|
||||
<field name="view_ids" widget="one2many">
|
||||
<tree>
|
||||
<field name="id"/>
|
||||
@ -58,7 +58,8 @@
|
||||
<tree string="Dockerfile" decoration-danger="dockerfile == ''" decoration-warning="to_build == False">
|
||||
<field name="name"/>
|
||||
<field name="image_tag"/>
|
||||
<field name="to_build" widget="boolean_toggle"/>
|
||||
<field name="to_build" groups="!runbot.group_runbot_admin"/>
|
||||
<field name="to_build" widget="boolean_toggle" groups="runbot.group_runbot_admin"/>
|
||||
<field name="version_ids" widget="many2many_tags"/>
|
||||
<field name="project_ids" widget="many2many_tags"/>
|
||||
<field name="bundle_ids"/>
|
||||
|
@ -11,16 +11,13 @@
|
||||
<menuitem name="Commits" id="runbot_menu_commit_tree" parent="menu_objects" sequence="50" action="open_view_commit_tree"/>
|
||||
<menuitem id="runbot_menu_bundle_custom_trigger" parent="menu_objects" sequence="70" action="action_bundle_custom_trigger"/>
|
||||
|
||||
<menuitem name="Hosts" id="runbot_menu_host_tree" parent="runbot_menu_root" sequence="300" action="open_view_host_tree"/>
|
||||
<menuitem name="Hosts" id="runbot_menu_host_tree" parent="runbot_menu_root" sequence="300" action="open_view_host_tree" groups="runbot.group_runbot_admin"/>
|
||||
|
||||
<menuitem id="runbot_menu_trigger" parent="runbot_menu_root" sequence="500" action="runbot_triggers_action"/>
|
||||
<menuitem id="runbot_menu_trigger" parent="runbot_menu_root" sequence="500" action="runbot_triggers_action" groups="runbot.group_runbot_admin"/>
|
||||
|
||||
<menuitem name="Configs" id="runbot_menu_configs" parent="runbot_menu_root" sequence="600"/>
|
||||
<menuitem name="Configs" id="runbot_menu_configs" parent="runbot_menu_root" sequence="600" groups="runbot.group_build_config_user"/>
|
||||
<menuitem id="runbot_menu_job_config_tree" parent="runbot_menu_configs" sequence="10" action="open_view_job_config_tree"/>
|
||||
<menuitem id="runbot_menu_job_tree" parent="runbot_menu_configs" sequence="20" action="open_view_job_tree"/>
|
||||
<menuitem name="CodeOwners" id="runbot_menu_codeowner_tree" parent="runbot_menu_configs" sequence="30" action="open_view_codeowner_tree"/>
|
||||
<menuitem name="Modules" id="runbot_menu_module_tree" parent="runbot_menu_configs" sequence="40" action="open_view_runbot_module"/>
|
||||
<menuitem name="Modules ownership" id="runbot_menu_module_ownership_tree" parent="runbot_menu_configs" sequence="50" action="open_view_runbot_module_ownership"/>
|
||||
|
||||
<menuitem id="runbot_menu_upgrade_exceptions_tree" parent="runbot_menu_root" sequence="700" action="open_view_upgrade_exception_tree"/>
|
||||
|
||||
@ -32,12 +29,15 @@
|
||||
|
||||
<menuitem name="Teams" id="runbot_menu_teams" parent="runbot_menu_root" sequence="1000"/>
|
||||
<menuitem name="Teams" id="runbot_menu_team_tree" parent="runbot_menu_teams" sequence="30" action="open_view_runbot_team"/>
|
||||
<menuitem name="Dashboards" id="runbot_menu_runbot_dashboard_tree" parent="runbot_menu_teams" sequence="40" action="open_view_runbot_dashboard"/>
|
||||
<menuitem name="Dashboard Tiles" id="runbot_menu_runbot_dashboard_tile_tree" parent="runbot_menu_teams" sequence="50" action="open_view_runbot_dashboard_tile"/>
|
||||
<menuitem name="Dashboards" id="runbot_menu_runbot_dashboard_tree" parent="runbot_menu_teams" sequence="40" action="open_view_runbot_dashboard" groups="runbot.group_runbot_admin"/>
|
||||
<menuitem name="Dashboard Tiles" id="runbot_menu_runbot_dashboard_tile_tree" parent="runbot_menu_teams" sequence="50" action="open_view_runbot_dashboard_tile" groups="runbot.group_runbot_admin"/>
|
||||
<menuitem name="Modules" id="runbot_menu_module_tree" parent="runbot_menu_teams" sequence="70" action="open_view_runbot_module"/>
|
||||
<menuitem name="Modules ownership" id="runbot_menu_module_ownership_tree" parent="runbot_menu_teams" sequence="80" action="open_view_runbot_module_ownership"/>
|
||||
<menuitem name="CodeOwners" id="runbot_menu_codeowner_tree" parent="runbot_menu_teams" sequence="90" action="open_view_codeowner_tree"/>
|
||||
|
||||
<menuitem name="Warnings" id="runbot_menu_warning_root" parent="runbot_menu_root" sequence="1200" action="open_view_warning_tree"/>
|
||||
<menuitem name="Warnings" id="runbot_menu_warning_root" parent="runbot_menu_root" sequence="1200" action="open_view_warning_tree" groups="runbot.group_runbot_admin"/>
|
||||
|
||||
<menuitem name="Settings" id="menu_runbot_settings" parent="runbot_menu_root" sequence="9000" />
|
||||
<menuitem name="Settings" id="menu_runbot_settings" parent="runbot_menu_root" sequence="9000" groups="runbot.group_runbot_admin"/>
|
||||
<menuitem id="menu_runbot_global_settings" parent="menu_runbot_settings" action="action_runbot_configuration" groups="base.group_system"/>
|
||||
<menuitem id="menu_bundle_project" action="action_bundle_project" sequence="10" parent="menu_runbot_settings"/>
|
||||
<menuitem id="menu_bundle_version" action="action_bundle_version" sequence="20" parent="menu_runbot_settings"/>
|
||||
@ -49,7 +49,7 @@
|
||||
<menuitem name="Stat Regex Wizard" id="runbot_menu_stat_wizard" parent="menu_runbot_settings" sequence="80" action="runbot_stat_regex_wizard_action"/>
|
||||
<menuitem name="Error regex" id="runbot_menu_error_regex_tree" parent="menu_runbot_settings" sequence="20" action="open_view_error_regex"/>
|
||||
|
||||
<menuitem name="Technical" id="runbot_menu_technical" parent="menu_runbot_settings" sequence="10000"/>
|
||||
<menuitem name="Technical" id="runbot_menu_technical" parent="menu_runbot_settings" sequence="10000" groups="base.group_system"/>
|
||||
<menuitem id="runbot_menu_ir_cron_act" action="base.ir_cron_act" parent="runbot_menu_technical"/>
|
||||
<menuitem id="runbot_menu_base_automation_act" action="base_automation.base_automation_act" parent="runbot_menu_technical"/>
|
||||
<menuitem id="runbot_menu_action_ui_view" action="base.action_ui_view" parent="runbot_menu_technical"/>
|
||||
|
Loading…
Reference in New Issue
Block a user