Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions runbot/models/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ class BuildResult(models.Model):
trigger_id = fields.Many2one('runbot.trigger', related='params_id.trigger_id', store=True, index=True)
create_batch_id = fields.Many2one('runbot.batch', related='params_id.create_batch_id', store=True, index=True)
create_bundle_id = fields.Many2one('runbot.bundle', related='params_id.create_batch_id.bundle_id', index=True)
base_attached = fields.Boolean('Base attached', compute='_compute_base_attached')
can_rebuild = fields.Boolean('Can rebuild', compute='_compute_can_rebuild')

# state machine
global_state = fields.Selection(make_selection(state_order), string='Status', compute='_compute_global_state', store=True, recursive=True)
Expand Down Expand Up @@ -494,6 +496,18 @@ def _compute_build_age(self):
else:
build.build_age = 0

def _compute_can_rebuild(self):
# note, not recursive, only checks one level of depth to avoid checking to much builds, mainly for nightlies
# this is a relaxed condition to help and easier rebuild before waiting for all child to be killed
for build in self:
build.can_rebuild = False
if build.global_state in ['done', 'running']:
build.can_rebuild = True
elif build.requested_action == 'deathrow':
build.can_rebuild = True
elif build.local_state in ['done', 'running'] and all(child.can_rebuild for child in build.children_ids):
build.can_rebuild = True

def _rebuild(self, message=None):
"""Force a rebuild and return a recordset of builds"""
self.ensure_one()
Expand Down Expand Up @@ -1015,6 +1029,24 @@ def truncate(message, maxlenght=300000):
'line': '0',
})

def _compute_base_attached(self):
slots = self.env['runbot.batch.slot'].search([('build_id', 'in', self.ids)], order='build_id')
slots.batch_id.bundle_id.mapped('is_base') # prefetch
bundle_per_build = defaultdict(list)
for slot in slots:
bundle_per_build[slot.build_id].append(slot.batch_id.bundle_id)
for build in self:
build.base_attached = any(bundle.is_base for bundle in bundle_per_build[build])

def _cannnot_kill_reason(self, from_batch=None):
if self.requested_action == 'deathrow':
return "Killing"
if not self.base_attached:
return None
if from_batch and from_batch.bundle_id.is_base and self.env.user.has_groups('runbot.group_runbot_admin'):
return None
return "Cannot be killed, attached to a base bundle"

def _kill(self, result=None):
host_name = self.env['runbot.host']._get_current_name()
self.ensure_one()
Expand Down
1 change: 0 additions & 1 deletion runbot/models/runbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ def _gc_running(self, host):
for build in Build.browse(build_ids)[running_max:]:
build._kill()


def _gc_testing(self, host):
"""garbage collect builds that could be killed"""
# decide if we need room
Expand Down
4 changes: 2 additions & 2 deletions runbot/models/upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def action_post_message(self):
raise UserError('You are not allowed to send messages')
for pr in self.pr_ids:
pr.remote_id._github('/repos/:owner/:repo/issues/%s/comments' % pr.name, {'body': self.message})

def action_auto_rebuild(self):
builds = self.create_build_id.parent_id.children_ids if self.create_build_id.parent_id else self.create_build_id
for build in builds:
Expand All @@ -40,7 +40,7 @@ def _generate(self):
if exceptions:
return 'suppress_upgrade_warnings=%s' % (','.join(exceptions.mapped('elements'))).replace(' ', '').replace('\n', ',')
return False

def default_pr_ids(self):
bundle_id = self.env.context.get('default_bundle_id')
if bundle_id:
Expand Down
2 changes: 1 addition & 1 deletion runbot/templates/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
</t>

<!-- Commits -->
<t t-foreach="build.params_id.sudo().commit_link_ids" t-as="build_commit">
<t t-foreach="build.params_id.sudo().commit_link_ids.sorted(key=lambda lc: (lc.commit_id.repo_id.sequence, lc.commit_id.repo_id.id))" t-as="build_commit">
<b>Commit:</b>
<a t-attf-href="/runbot/commit/{{build_commit.commit_id.id}}">
<t t-out="build_commit.commit_id.dname"/>
Expand Down
27 changes: 20 additions & 7 deletions runbot/templates/utils.xml
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,9 @@
<a t-if="slot.trigger_id.report_view_id" title="View last trigger report" t-attf-href="/runbot/trigger/report/{{slot.trigger_id.id}}" class="fa fa-eye btn btn-info"/>
<a t-if="bu.local_state == 'running' and bu.database_ids" t-attf-href="/runbot/run/{{bu.id}}" class="fa fa-sign-in btn btn-info"/>
<a t-if="bu.static_run" t-att-href="bu.static_run" class="fa fa-sign-in btn btn-info"/>
<t t-if="bu" t-call="runbot.build_menu"/>
<t t-if="bu" t-call="runbot.build_menu">
<t t-set="from_batch" t-value="slot.batch_id"/>
</t>
<a t-if="not bu" groups="base.group_user" class="btn btn-default" title="Create build" t-attf-href="/runbot/batch/slot/{{slot.id}}/build">
<i class="fa fa-play fa-fw"/>
</a>
Expand All @@ -266,7 +268,10 @@
<i class="fa fa-file-text-o"/>
</a>
<!--<a t-if="show_commit_button" t-attf-href="https://#{repo.base_url}/commit/#{bu['name']}" class="btn btn-default" title="Open commit on GitHub" aria-label="Open commit on GitHub"><i class="fa fa-github"/></a>-->
<t t-call="runbot.build_menu"/>
<t t-call="runbot.build_menu">
<t t-set="from_batch" t-value="from_batch"/>
<t t-set="from_build_page" t-value="True"/>
</t>
</div>
</div>
</template>
Expand Down Expand Up @@ -315,16 +320,24 @@
Database selector
</a>
</t>
<a class="dropdown-item" t-if="bu.global_state in ['done','running'] or bu.requested_action == 'deathrow'" groups="base.group_user" href="#" data-runbot="rebuild" t-att-data-runbot-build="bu['id']" title="Retry this build, usefull for false positive">
<i class="fa fa-refresh"/>
Rebuild
</a>
<t t-if="from_build_page" groups="base.group_user">
<a class="dropdown-item" t-if="bu.local_result != 'ok' and bu.can_rebuild" href="#" data-runbot="rebuild" t-att-data-runbot-build="bu['id']" title="Retry this build, usefull for false positive">
<i class="fa fa-refresh"/>
Rebuild
</a>
<a class="dropdown-item" t-else="" t-if="more and bu.can_rebuild" href="#" data-runbot="rebuild" t-att-data-runbot-build="bu['id']" title="Build result is ok, you may prefer to rebuild a child.">
<i class="fa fa-refresh text-danger"/>
Advanced Rebuild
</a>
</t>
<t t-if="bu.global_state != 'done'">
<t t-if="bu.requested_action != 'deathrow'">
<a groups="base.group_user" href="#" data-runbot="kill" class="dropdown-item" t-att-data-runbot-build="bu['id']">
<t t-set="cannnot_kill_reason" t-value="bu._cannnot_kill_reason(from_batch)"/>
<a t-if="not cannnot_kill_reason" groups="base.group_user" href="#" data-runbot="kill" class="dropdown-item" t-att-data-runbot-build="bu['id']">
<i class="fa fa-crosshairs"/>
Kill
</a>
<t t-else="" t-out="cannnot_kill_reason"/>
</t>
<t t-else="">
<a groups="base.group_user" class="dropdown-item disabled">
Expand Down