<odoo> <function model="website.page" name="write"> <value eval="ref('website.homepage_page')"/> <value eval="{'active': False}"/> </function> <template id="link-pr" name="create a link to `pr`"> <t t-set="title"> <t t-if="pr.repository.group_id <= env.user.groups_id"> <t t-esc="pr.message.split('\n')[0]"/> </t> </t> <a t-attf-href="https://github.com/{{ pr.repository.name }}/pull/{{ pr.number }}" t-att-title="pr.blocked or title.strip()" t-att-target="target or None" t-att-class="classes or None" ><t t-esc="pr.display_name"/></a> </template> <template id="staging-statuses" name="dropdown statuses list of stagings"> <div class="dropdown" t-if="staging.heads"> <button class="btn btn-link dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" t-attf-title="Staged at {{staging.staged_at}}Z" > <t t-out="0"/> <span class="caret"></span> </button> <div class="dropdown-menu staging-statuses"> <a groups="runbot_merge.group_admin" class="dropdown-item" role="menuitem" t-attf-href="/web#id={{staging.id}}&view_type=form&model=runbot_merge.stagings" target="new"> Open Staging </a> <t t-set="statuses" t-value="{(r, c): (s, t) for r, c, s, t in staging.statuses}"/> <t t-foreach="repo_statuses._for_staging(staging)" t-as="req"> <t t-set="st" t-value="statuses.get((req.repo_id.name, req.context)) or (None, None)"/> <a t-att-href="st[1]" target="new" role="menuitem" t-attf-class=" dropdown-item {{'bg-success' if st[0] == 'success' else 'bg-danger' if st[0] in ('error', 'failure') else 'bg-info' if st[0] else 'bg-light'}}"> <t t-esc="req.repo_id.name"/>: <t t-esc="req.context"/> </a> </t> </div> </div> </template> <template id="alerts"> <div id="alerts" class="row text-center"> <div class="alert alert-light col-md-12 h6 mb-0"> <a href="/runbot_merge/changelog">Changelog</a> </div> <t t-set="stagingcron" t-value="env(user=1).ref('runbot_merge.staging_cron')"/> <div t-if="not stagingcron.active" class="alert alert-warning col-12 mb-0" role="alert"> Staging is disabled, "ready" pull requests will not be staged. </div> <t t-set="mergecron" t-value="env(user=1).ref('runbot_merge.merge_cron')"/> <div t-if="not mergecron.active" class="alert alert-warning col-12 mb-0" role="alert"> Merging is disabled, stagings will not be integrated. </div> </div> </template> <template id="dashboard" name="mergebot dashboard"> <t t-call="website.layout"> <div id="wrap"><div class="container-fluid"> <t t-call="runbot_merge.alerts"/> <section t-foreach="projects.with_context(active_test=False)" t-as="project" class="row"> <h1 class="col-md-12"><t t-esc="project.name"/></h1> <div class="col-md-12"> key: <ul class="list-inline"> <li class="bg-success">success (hopefully merged)</li> <li class="bg-info">ongoing</li> <li class="bg-danger">failure</li> <li class="bg-gray-lighter">cancelled</li> </ul> </div> <section t-foreach="project.branch_ids" t-as="branch" t-if="branch.active" class="col-md-12"> <h2> <a t-attf-href="/runbot_merge/{{branch.id}}"> <t t-esc="branch.name"/> </a> </h2> <t t-call="runbot_merge.stagings"/> <t t-set="splits" t-value="branch.split_ids"/> <t t-set="ready_unstaged" t-value=" project.env['runbot_merge.pull_requests'].search([ ('target', '=', branch.id), ('state', '=', 'ready'), ('staging_id', '=', False), ]) - splits.mapped('batch_ids.prs') "/> <t t-set="ready" t-value="ready_unstaged.filtered(lambda p: not p.blocked)"/> <t t-set="blocked" t-value="ready_unstaged.filtered(lambda p: p.blocked)"/> <div t-if="splits" class="splits bg-warning pr-awaiting"> <h5> Splits <small class="text-muted">will be staged next</small> </h5> <ul> <li t-foreach="splits" t-as="split"> <ul class="pr-listing list-inline list-unstyled mb0"> <li t-foreach="split.mapped('batch_ids.prs')" t-as="pr"> <t t-call="runbot_merge.link-pr"/> </li> </ul> </li> </ul> </div> <div t-if="ready" class="pr-listing pr-awaiting bg-warning"> <h5>Awaiting</h5> <ul class="list-inline"> <li t-foreach="ready" t-as="pr"> <t t-call="runbot_merge.link-pr"/> </li> </ul> </div> <div t-if="blocked" class="pr-listing pr-blocked bg-info"> <h5>Blocked</h5> <ul class="list-inline"> <li t-foreach="blocked" t-as="pr"> <t t-call="runbot_merge.link-pr"/> </li> </ul> </div> <t t-set="failed" t-value=" project.env['runbot_merge.pull_requests'].search([ ('target', '=', branch.id), ('state', '=', 'error'), ('staging_id', '=', False), ]) "/> <div t-if="failed" class="pr-listing pr-failed bg-danger"> <h5>Failed</h5> <ul class="list-inline"> <li t-foreach="failed" t-as="pr"> <t t-call="runbot_merge.link-pr"/> </li> </ul> </div> </section> </section> </div></div> </t> </template> <template id="stagings" name="mergebot branch stagings"> <t t-set="repo_statuses" t-value="branch.project_id.repo_ids.having_branch(branch).status_ids"/> <ul class="list-unstyled stagings"> <t t-foreach="branch.env['runbot_merge.stagings'].search([('target', '=', branch.id)], order='staged_at desc', limit=6)" t-as="staging"> <t t-set="success" t-value="staging.state == 'success'"/> <t t-set="failure" t-value="staging.state == 'failure'"/> <t t-set="pending" t-value="staging.active and (not staging.state or staging.state == 'pending')"/> <t t-set="stateclass"> <t t-if="success">bg-success <t t-if="staging.active">bg-unmerged</t></t> <t t-if="failure">bg-danger</t> <t t-if="pending">bg-info</t> <t t-if="not (success or failure or pending)">bg-gray-lighter</t> </t> <t t-set="decorationclass" > <t t-if="4 > staging_index >= 2">d-none d-md-block</t> <t t-if="staging_index >= 4">d-none d-lg-block</t> </t> <t t-set="title"> <t t-if="staging.state == 'ff_failed'">fast forward failed (<t t-esc="staging.reason"/>)</t> <t t-if="staging.state == 'pending'">last status</t> </t> <!-- separate concatenation to avoid having line-break in title as some browsers trigger it --> <!-- write-date may have microsecond precision, strip that information --> <!-- use write-date under assumption that a staging is last modified when it ends --> <t t-set="title"><t t-esc="title.strip() or staging.reason"/> at <t t-esc="staging.write_date.replace(microsecond=0)"/>Z</t> <li t-attf-class="staging {{stateclass.strip()}} {{decorationclass.strip()}}" t-att-title="title"> <ul class="list-unstyled"> <li t-foreach="staging.batch_ids" t-as="batch" class="batch"> <t t-esc="batch.prs[:1].label"/> <t t-foreach="batch.prs" t-as="pr"> <t t-call="runbot_merge.link-pr"/> </t> </li> </ul> <t t-call="runbot_merge.staging-statuses"> Staged <span t-field="staging.staged_at" t-options="{'widget': 'relative'}"/> </t> </li> </t> </ul> </template> <template id="branch_stagings" name="mergebot stagings page"> <t t-set="repo_statuses" t-value="branch.project_id.repo_ids.having_branch(branch).status_ids"/> <t t-call="website.layout"> <div id="wrap"><div class="container-fluid"> <section class="row"> <h1 class="col-md-12"><t t-esc="branch.project_id.name"/>: <t t-esc="branch.name"/></h1> </section> <table> <t t-foreach="stagings" t-as="staging"> <t t-set="success" t-value="staging.state == 'success'"/> <t t-set="failure" t-value="staging.state == 'failure'"/> <t t-set="pending" t-value="staging.active and (not staging.state or staging.state == 'pending')"/> <t t-set="stateclass"> <t t-if="success">bg-success</t> <t t-if="failure">bg-danger</t> <t t-if="pending">bg-info</t> <t t-if="not (success or failure or pending)"> bg-gray-lighter </t> </t> <t t-set="title"> <t t-if="staging.state == 'canceled'">Cancelled: <t t-esc="staging.reason"/> </t> <t t-if="staging.state == 'ff_failed'">Fast Forward Failed </t> <t t-if="staging.state not in ('canceled', 'ff_failed')"> <t t-esc="staging.reason"/> </t> </t> <tr t-att-class="stateclass" style="border-bottom: 1px solid gainsboro; vertical-align: top"> <th t-att-title="title.strip() or None"> <t t-if="not staging.heads"> <span t-field="staging.staged_at" t-options="{'format': 'yyyy-MM-dd\'T\'HH:mm:ssZ'}"/> </t> <t t-call="runbot_merge.staging-statuses"> <span t-field="staging.staged_at" t-options="{'format': 'yyyy-MM-dd\'T\'HH:mm:ssZ'}"/> </t> </th> <td> <ul class="list-inline list-unstyled mb0"> <t t-foreach="staging.batch_ids" t-as="batch"> <t t-set="first_pr" t-value="batch.prs[-1:]"/> <li class="dropdown" t-if="first_pr"> <button class="btn btn-link dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" > <t t-esc="first_pr.label"/> <span class="caret"></span> </button> <div class="dropdown-menu"> <t t-foreach="batch.prs" t-as="pr"> <t t-call="runbot_merge.link-pr"> <t t-set="target">new</t> <t t-set="classes">dropdown-item</t> </t> </t> </div> </li> </t> </ul> </td> </tr> </t> </table> <t t-if="next"> <a t-attf-href="/runbot_merge/{{branch.id}}?until={{next}}"> Next > </a> </t> </div></div> </t> </template> <template id="changelog" name="mergebot changelog"> <t t-call="website.layout"> <div id="wrap"><div class="container-fluid"> <h1>Changelog</h1> <section t-foreach="entries" t-as="entry"> <h3 t-if="not entry_first" t-esc="entry"/> <ul> <li t-foreach="sorted(entry_value)" t-as="item"> <t t-out="item"/> </li> </ul> </section> </div></div> </t> </template> <template id="view_pull_request_info_merged"> <div class="alert alert-success"> Merged <t t-if="merged_head"> at <a t-attf-href="https://github.com/{{pr.repository.name}}/commit/{{merged_head}}"><t t-esc="merged_head"/></a> </t> <t t-set="linked_prs" t-value="pr._linked_prs"/> <div t-if="linked_prs"> Linked pull requests <ul> <li t-foreach="linked_prs" t-as="linked"> <a t-att-href="linked.url" t-field="linked.display_name"/> </li> </ul> </div> </div> </template> <template id="view_pull_request_info_closed"> <div class="alert alert-light"> Closed </div> </template> <template id="view_pull_request_info_error"> <div class="alert alert-danger"> Error: <span t-esc="pr.with_context(active_test=False).batch_ids[-1:].staging_id.reason"> Unable to stage PR </span> </div> </template> <template id="view_pull_request_info_staging"> <div class="alert alert-primary"> Staged <span t-field="pr.staging_id.staged_at" t-options="{'widget': 'relative'}"/>. <t t-set="linked_prs" t-value="pr._linked_prs"/> <div t-if="linked_prs"> Linked pull requests <ul> <li t-foreach="linked_prs" t-as="linked"> <a t-att-href="linked.url" t-field="linked.display_name"/> </li> </ul> </div> </div> </template> <template id="view_pull_request_info_open"> <!-- nb: replicates `blocked`, maybe that should be split into various criteria? --> <div class="alert alert-info"> <p t-if="pr.blocked" class="alert-danger">Blocked</p> <p t-else="" class="alert-success">Ready (waiting for staging)</p> <ul class="todo"> <li t-att-class="'ok' if pr.squash or pr.merge_method else 'fail'"> Merge method </li> <li t-att-class="'ok' if pr._approved else 'fail'"> Review </li> <li t-att-class="'ok' if pr.state not in ('opened', 'approved') else ''"> CI <ul class="todo"> <t t-foreach="pr.repository.status_ids._for_pr(pr)" t-as="ci"> <t t-set="st" t-value="statuses.get(ci.context.strip())"/> <t t-set="result"> <t t-if="not st or st['state'] == 'pending'"></t> <t t-elif="st['state'] in ('error', 'failure')">fail</t> <t t-else="">ok</t> </t> <li t-att-class="result"> <a t-att-href="st.get('target_url') if st else None"><t t-esc="ci.context.strip()"/></a><t t-if="st and st.get('description')">: <t t-esc="st['description']"/></t> </li> </t> </ul> </li> <t t-set="linked_prs" t-value="pr._linked_prs"/> <li t-if="linked_prs" t-att-class="'ok' if all(l._ready for l in linked_prs) else 'fail'"> Linked pull requests <ul class="todo"> <t t-foreach="linked_prs" t-as="linked"> <li t-att-class="'ok' if linked._ready else 'fail'"> <a t-att-href="linked.url" t-field="linked.display_name"/> </li> </t> </ul> </li> </ul> </div> </template> <template id="view_pull_request"> <t t-call="website.layout"> <div id="wrap"><div class="container-fluid"> <t t-call="runbot_merge.alerts"/> <h1> <a t-att-href="pr.github_url" t-field="pr.display_name"> </a> <a t-attf-href="/web#view_type=form&model=runbot_merge.pull_requests&id={{pr.id}}" class="btn btn-sm btn-secondary align-top float-right" groups="base.group_user">View in backend</a> </h1> <h6>Created by <span t-field="pr.author.display_name"/></h6> <t t-set="tmpl"> <t t-if="pr.state in ('merged', 'closed', 'error')"><t t-esc="pr.state"/></t> <t t-elif="pr.staging_id">staging</t> <t t-else="">open</t> </t> <t t-call="runbot_merge.view_pull_request_info_{{tmpl.strip()}}"/> <t t-set="target_cls" t-value="None if pr.target.active else 'text-muted bg-warning'"/> <dl class="runbot-merge-fields"> <dt>label</dt> <dd><span t-field="pr.label"/></dd> <dt>head</dt> <dd><a t-attf-href="{{pr.github_url}}/commits/{{pr.head}}"><span t-field="pr.head"/></a></dd> <dt t-att-class="target_cls">target</dt> <dd t-att-class="target_cls"><span t-field="pr.target"/></dd> </dl> <p t-field="pr.message"/> </div></div> </t> </template> </odoo>