From c874f4a0469723a9bfae8ab64e3c04698997d272 Mon Sep 17 00:00:00 2001 From: Xavier-Do Date: Tue, 22 Oct 2019 13:36:07 +0200 Subject: [PATCH] [IMP] runbot: execute flamegraph in case of failure and log dl link --- runbot/models/build.py | 15 +++++---------- runbot/models/build_config.py | 32 +++++++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/runbot/models/build.py b/runbot/models/build.py index a8ec7094..d543b3b6 100644 --- a/runbot/models/build.py +++ b/runbot/models/build.py @@ -634,29 +634,21 @@ class runbot_build(models.Model): results = {'local_result': 'ko'} build_values.update(results) - # Non running build in - notify_end_job = build.active_step.job_type != 'create_build' + build.active_step.log_end(build) 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') if ending_build: 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) - if ending_build: build._github_status() if not build.local_result: # Set 'ok' result if no result set (no tests job on build) build.local_result = 'ok' 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 pid = None if build.local_state != 'done': @@ -683,6 +675,9 @@ class runbot_build(models.Model): root = self.env['runbot.repo']._root() 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): """Return the absolute path to the direcory containing the server file, adding optional *path""" self.ensure_one() diff --git a/runbot/models/build_config.py b/runbot/models/build_config.py index d9cf542b..2abbbda4 100644 --- a/runbot/models/build_config.py +++ b/runbot/models/build_config.py @@ -5,7 +5,7 @@ import os import re import shlex 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 odoo import models, fields, api 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]) + 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)) 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) + 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): 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') os.makedirs(cov_path, exist_ok=True) 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 [] - def _perfs_data_path(self, prefix='perf', ext='log'): - return '/data/build/logs/%s_%s.%s' % (prefix, self.name, ext) + def _perfs_data_path(self, ext='log'): + 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): pattern_to_omit = set()