[IMP] runbot: execute flamegraph in case of failure and log dl link

This commit is contained in:
Xavier-Do 2019-10-22 13:36:07 +02:00 committed by Christophe Monniez
parent 8284c7270d
commit c874f4a046
2 changed files with 32 additions and 15 deletions

View File

@ -634,29 +634,21 @@ class runbot_build(models.Model):
results = {'local_result': 'ko'} results = {'local_result': 'ko'}
build_values.update(results) build_values.update(results)
# Non running build in build.active_step.log_end(build)
notify_end_job = build.active_step.job_type != 'create_build'
build_values.update(build._next_job_values()) # find next active_step or set to done build_values.update(build._next_job_values()) # find next active_step or set to done
ending_build = build.local_state not in ('done', 'running') and build_values.get('local_state') in ('done', 'running') ending_build = build.local_state not in ('done', 'running') and build_values.get('local_state') in ('done', 'running')
if ending_build: if ending_build:
build.update_build_end() build.update_build_end()
step_end_message = 'Step %s finished in %s $$fa-download$$' % (build.job, s2human(build.job_time))
step_end_link = 'http://%s/runbot/static/build/%s/logs/%s-%s.sql.gz' % (build.host, build.dest, build.dest, build.active_step.db_name)
build.write(build_values) build.write(build_values)
if ending_build: if ending_build:
build._github_status() build._github_status()
if not build.local_result: # Set 'ok' result if no result set (no tests job on build) if not build.local_result: # Set 'ok' result if no result set (no tests job on build)
build.local_result = 'ok' build.local_result = 'ok'
build._logger("No result set, setting ok by default") build._logger("No result set, setting ok by default")
if notify_end_job:
build._log('end_job', step_end_message, log_type='link', path=step_end_link)
else:
build._logger(step_end_message)
# run job # run job
pid = None pid = None
if build.local_state != 'done': if build.local_state != 'done':
@ -683,6 +675,9 @@ class runbot_build(models.Model):
root = self.env['runbot.repo']._root() root = self.env['runbot.repo']._root()
return os.path.join(root, 'build', build.dest, *l) return os.path.join(root, 'build', build.dest, *l)
def http_log_url(self):
return 'http://%s/runbot/static/build/%s/logs/' % (self.host, self.dest)
def _server(self, *path): def _server(self, *path):
"""Return the absolute path to the direcory containing the server file, adding optional *path""" """Return the absolute path to the direcory containing the server file, adding optional *path"""
self.ensure_one() self.ensure_one()

View File

@ -5,7 +5,7 @@ import os
import re import re
import shlex import shlex
import time import time
from ..common import now, grep, time2str, rfind, Commit from ..common import now, grep, time2str, rfind, Commit, s2human
from ..container import docker_run, docker_get_gateway_ip, Command from ..container import docker_run, docker_get_gateway_ip, Command
from odoo import models, fields, api from odoo import models, fields, api
from odoo.exceptions import UserError, ValidationError from odoo.exceptions import UserError, ValidationError
@ -339,10 +339,31 @@ class ConfigStep(models.Model):
cmd.finals.append(['pg_dump', db_name, '|', 'gzip', '>', '/data/build/logs/%s.sql.gz' % db_name]) cmd.finals.append(['pg_dump', db_name, '|', 'gzip', '>', '/data/build/logs/%s.sql.gz' % db_name])
if self.flamegraph:
cmd.finals.append(['flamegraph.pl', '--title', 'Flamegraph %s for build %s' % (self.name, build.id), self._perfs_data_path(), '>', self._perfs_data_path(ext='svg')])
cmd.finals.append(['gzip', '-f', self._perfs_data_path()]) # keep data but gz them to save disc space
max_timeout = int(self.env['ir.config_parameter'].get_param('runbot.runbot_timeout', default=10000)) max_timeout = int(self.env['ir.config_parameter'].get_param('runbot.runbot_timeout', default=10000))
timeout = min(self.cpu_limit, max_timeout) timeout = min(self.cpu_limit, max_timeout)
return docker_run(cmd.build(), log_path, build._path(), build._get_docker_name(), cpu_limit=timeout, ro_volumes=exports) return docker_run(cmd.build(), log_path, build._path(), build._get_docker_name(), cpu_limit=timeout, ro_volumes=exports)
def log_end(self, build):
if self.job_type == 'create_build':
build._logger('Step %s finished in %s' % (self.name, s2human(build.job_time)))
return
message = 'Step %s finished in %s $$fa-download$$' % (self.name, s2human(build.job_time))
link = '%s%s-%s.sql.gz' % (build.http_log_url(), build.dest, self.db_name)
build._log('end_job', message, log_type='link', path=link)
if self.flamegraph:
link = self._perf_data_url(build, 'log.gz')
message = 'Flamegraph data: $$fa-download$$'
build._log('end_job', message, log_type='link', path=link)
link = self._perf_data_url(build, 'svg')
message = 'Flamegraph svg: $$fa-download$$'
build._log('end_job', message, log_type='link', path=link)
def _modules_to_install(self, build): def _modules_to_install(self, build):
return set(build._get_modules_to_test(modules_patterns=self.install_modules)) return set(build._get_modules_to_test(modules_patterns=self.install_modules))
@ -353,12 +374,13 @@ class ConfigStep(models.Model):
cov_path = build._path('coverage') cov_path = build._path('coverage')
os.makedirs(cov_path, exist_ok=True) os.makedirs(cov_path, exist_ok=True)
return ['python%s' % py_version, "-m", "coverage", "html", "-d", "/data/build/coverage", "--ignore-errors"] return ['python%s' % py_version, "-m", "coverage", "html", "-d", "/data/build/coverage", "--ignore-errors"]
elif self.flamegraph:
return ['flamegraph.pl', '--title', 'Flamegraph %s for build %s' % (self.name, build.id), self._perfs_data_path(), '>', self._perfs_data_path(prefix='flame', ext='svg')]
return [] return []
def _perfs_data_path(self, prefix='perf', ext='log'): def _perfs_data_path(self, ext='log'):
return '/data/build/logs/%s_%s.%s' % (prefix, self.name, ext) return '/data/build/logs/flame_%s.%s' % (self.name, ext)
def _perf_data_url(self, build, ext='log'):
return '%sflame_%s.%s' % (build.http_log_url(), self.name, ext)
def _coverage_params(self, build, modules_to_install): def _coverage_params(self, build, modules_to_install):
pattern_to_omit = set() pattern_to_omit = set()