Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Xavier-Do committed Mar 1, 2023
1 parent ca06677 commit 11110ec
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 78 deletions.
9 changes: 5 additions & 4 deletions runbot/models/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ def create(self, vals_list):
build_logs = logs_by_build_id[build.id]
for ir_log in build_logs:
ir_log['active_step_id'] = build.active_step.id
if ir_log['level'].upper() == 'WARNING':
build.local_result = 'warn'
elif ir_log['level'].upper() == 'ERROR':
build.local_result = 'ko'
if build.local_state != 'running':
if ir_log['level'].upper() == 'WARNING':
build.local_result = 'warn'
elif ir_log['level'].upper() == 'ERROR':
build.local_result = 'ko'
return super().create(vals_list)

def _markdown(self):
Expand Down
2 changes: 1 addition & 1 deletion runbot/tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ def test_repo_gc_testing(self):
build_a.write({'local_state': 'testing', 'host': host.name})
build_b.write({'local_state': 'testing', 'host': 'runbot_yyy'})

build_a._update_globals()
# no room needed, verify that nobody got killed
self.Runbot._gc_testing(host)
self.assertFalse(build_a.requested_action)
Expand All @@ -468,7 +469,6 @@ def test_repo_gc_testing(self):
bundle_a.last_batch._prepare()
build_a_last = bundle_a.last_batch.slot_ids[0].build_id
self.assertEqual(build_a_last.local_state, 'pending')
build_a_last._update_globals()
self.assertTrue(build_a.killable, 'The previous build in the batch should be killable')

# the build_b create a child build
Expand Down
35 changes: 26 additions & 9 deletions runbot/tests/test_build_config_step.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ def test_config_step_create_results(self):
child_build._update_globals()
self.assertEqual(child_build.global_result, 'ko')

self.parent_build._update_globals()
self.assertEqual(self.parent_build.global_result, 'ko')

def test_config_step_create(self):
Expand All @@ -236,7 +237,8 @@ def test_config_step_create(self):
for child_build in self.parent_build.children_ids:
self.assertTrue(child_build.orphan_result, 'An orphan result config step should mark the build as orphan_result')
child_build.local_result = 'ko'

child_build._update_globals()
self.parent_build._update_globals()
self.assertEqual(self.parent_build.global_result, 'ok')

def test_config_step_create_child_data(self):
Expand Down Expand Up @@ -565,10 +567,13 @@ def _log(func, message, level='INFO', log_type='runbot', path='runbot'):
logs = []
with patch('builtins.open', mock_open(read_data=file_content)):
config_step._make_results(build)
self.assertEqual(build.job_end, '1970-01-01 02:00:00')
self.assertEqual(str(build.job_end), '1970-01-01 02:00:00')
self.assertEqual(logs, [('INFO', 'Getting results for build %s' % build.dest)])
self.assertEqual(build.local_result, 'ok')
# no shutdown
build = self.Build.create({
'params_id': self.base_params.id,
})
logs = []
file_content = """
Loading stuff
Expand All @@ -577,27 +582,33 @@ def _log(func, message, level='INFO', log_type='runbot', path='runbot'):
"""
with patch('builtins.open', mock_open(read_data=file_content)):
config_step._make_results(build)
self.assertEqual(build.job_end, '1970-01-01 02:00:00')
self.assertEqual(str(build.job_end), '1970-01-01 02:00:00')
self.assertEqual(build.local_result, 'ko')
self.assertEqual(logs, [
('INFO', 'Getting results for build %s' % build.dest),
('ERROR', 'No "Initiating shutdown" found in logs, maybe because of cpu limit.')
])
# no loaded
build = self.Build.create({
'params_id': self.base_params.id,
})
logs = []
file_content = """
Loading stuff
"""
with patch('builtins.open', mock_open(read_data=file_content)):
config_step._make_results(build)
self.assertEqual(build.job_end, '1970-01-01 02:00:00')
self.assertEqual(str(build.job_end), '1970-01-01 02:00:00')
self.assertEqual(build.local_result, 'ko')
self.assertEqual(logs, [
('INFO', 'Getting results for build %s' % build.dest),
('ERROR', 'Modules loaded not found in logs')
])

# traceback
build = self.Build.create({
'params_id': self.base_params.id,
})
logs = []
file_content = """
Loading stuff
Expand All @@ -611,14 +622,17 @@ def _log(func, message, level='INFO', log_type='runbot', path='runbot'):
"""
with patch('builtins.open', mock_open(read_data=file_content)):
config_step._make_results(build)
self.assertEqual(build.job_end, '1970-01-01 02:00:00')
self.assertEqual(str(build.job_end), '1970-01-01 02:00:00')
self.assertEqual(build.local_result, 'ko')
self.assertEqual(logs, [
('INFO', 'Getting results for build %s' % build.dest),
('ERROR', 'Error or traceback found in logs')
])

# warning in logs
build = self.Build.create({
'params_id': self.base_params.id,
})
logs = []
file_content = """
Loading stuff
Expand All @@ -629,7 +643,7 @@ def _log(func, message, level='INFO', log_type='runbot', path='runbot'):
"""
with patch('builtins.open', mock_open(read_data=file_content)):
config_step._make_results(build)
self.assertEqual(build.job_end, '1970-01-01 02:00:00')
self.assertEqual(str(build.job_end), '1970-01-01 02:00:00')
self.assertEqual(build.local_result, 'warn')
self.assertEqual(logs, [
('INFO', 'Getting results for build %s' % build.dest),
Expand All @@ -648,6 +662,9 @@ def _log(func, message, level='INFO', log_type='runbot', path='runbot'):
])

# no error but build was already in warn
build = self.Build.create({
'params_id': self.base_params.id,
})
logs = []
file_content = """
Loading stuff
Expand All @@ -662,7 +679,7 @@ def _log(func, message, level='INFO', log_type='runbot', path='runbot'):
self.assertEqual(logs, [
('INFO', 'Getting results for build %s' % build.dest)
])
self.assertEqual(build.job_end, '1970-01-01 02:00:00')
self.assertEqual(str(build.job_end), '1970-01-01 02:00:00')
self.assertEqual(build.local_result, 'warn')

@patch('odoo.addons.runbot.models.build_config.ConfigStep._make_tests_results')
Expand All @@ -688,8 +705,8 @@ def test_make_python_result(self, mock_make_tests_results):

# no result defined
config_step.python_result_code = ""
mock_make_tests_results.return_value = {'local_result': 'warning'}
mock_make_tests_results.return_value = {'local_result': 'warn'}
config_step._make_results(build)
self.assertEqual(build.local_result, 'warning')
self.assertEqual(build.local_result, 'warn')

# TODO add generic test to copy_paste _run_* in a python step
10 changes: 8 additions & 2 deletions runbot/tests/test_build_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ def setUp(self):

def test_build_scan(self):
IrLog = self.env['ir.logging']
ko_build = self.create_test_build({'local_result': 'ko'})
ok_build = self.create_test_build({'local_result': 'ok'})
ko_build = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'})
ok_build = self.create_test_build({'local_result': 'ok', 'local_state': 'running'})
ko_build._update_globals()
ok_build._update_globals()

error_team = self.BuildErrorTeam.create({
'name': 'test-error-team',
Expand All @@ -56,6 +58,10 @@ def test_build_scan(self):
IrLog.create(log)
log.update({'build_id': ok_build.id})
IrLog.create(log)

self.assertEqual(ko_build.local_result, 'ko', 'Testing build should have gone ko after error log')
self.assertEqual(ok_build.local_result, 'ok', 'Running build should not have gone ko after error log')

ko_build._parse_logs()
ok_build._parse_logs()
build_error = self.BuildError.search([('build_ids', 'in', [ko_build.id])])
Expand Down
4 changes: 3 additions & 1 deletion runbot/tests/test_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def test_schedule_mark_done(self, mock_docker_state, mock_getmtime):

build = self.Build.create({
'local_state': 'testing',
'global_state': 'testing',
'port': '1234',
'host': host.name,
'job_start': datetime.datetime.now(),
Expand All @@ -33,9 +34,10 @@ def test_schedule_mark_done(self, mock_docker_state, mock_getmtime):
self.assertEqual(build.local_state, 'testing')
build._schedule() # too fast, docker not started
self.assertEqual(build.local_state, 'testing')
self.assertEqual(build.local_result, 'ok')

self.start_patcher('fetch_local_logs', 'odoo.addons.runbot.models.host.Host._fetch_local_logs', []) # the local logs have to be empty
build.write({'job_start': datetime.datetime.now() - datetime.timedelta(seconds=70)}) # docker never started
build._schedule()
self.assertEqual(build.local_state, 'done')
self.assertEqual(build.local_result, 'ok')
self.assertEqual(build.local_result, 'ko')
147 changes: 86 additions & 61 deletions runbot/tests/test_upgrade.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import getpass
import logging
import getpass
from unittest.mock import patch, mock_open
from odoo.exceptions import UserError
from odoo.tools import mute_logger
from .common import RunbotCase
Expand Down Expand Up @@ -353,9 +354,14 @@ def assertOk(build, t, f, b_type, db_suffix, trigger):
[]
)
to_version_builds.host = host.name
to_version_builds._schedule()
to_version_builds._schedule()
self.assertEqual(to_version_builds.mapped('local_state'), ['done']*4)
for build in to_version_builds:
build._schedule() # starts builds
self.assertEqual(build.local_state, 'testing')
build._schedule() # makes result and end build
self.assertEqual(build.local_state, 'done')
to_version_builds._update_globals()
self.assertEqual(to_version_builds.mapped('global_state'), ['done', 'waiting', 'waiting', 'waiting'], 'One build have no child, other should wait for children')

from_version_builds = to_version_builds.children_ids
self.assertEqual(
[
Expand All @@ -368,9 +374,15 @@ def assertOk(build, t, f, b_type, db_suffix, trigger):
['11.0->12.0', 'saas-11.3->12.0', '12.0->13.0', 'saas-12.3->13.0', '13.0->master', 'saas-13.1->master', 'saas-13.2->master', 'saas-13.3->master']
)
from_version_builds.host = host.name
from_version_builds._schedule()
from_version_builds._schedule()
self.assertEqual(from_version_builds.mapped('local_state'), ['done']*8)
for build in from_version_builds:
build._schedule()
self.assertEqual(build.local_state, 'testing')
build._schedule()
self.assertEqual(build.local_state, 'done')

from_version_builds._update_globals()
self.assertEqual(from_version_builds.mapped('global_state'), ['waiting'] * 8)

db_builds = from_version_builds.children_ids
self.assertEqual(len(db_builds), 40)

Expand Down Expand Up @@ -405,61 +417,74 @@ def assertOk(build, t, f, b_type, db_suffix, trigger):
[b.params_id.dump_db.db_suffix for b in b133_master],
['account', 'l10n_be', 'l10n_ch', 'mail', 'stock'] # is this order ok?
)

first_build = db_builds[0]

self.start_patcher('docker_state', 'odoo.addons.runbot.models.build.docker_state', 'END')

def docker_run_restore(cmd, *args, **kwargs):
source_dest = first_build.params_id.dump_db.build_id.dest
dump_url='http://host.runbot.com/runbot/static/build/%s/logs/%s-account.zip' % (source_dest, source_dest)
zip_name='%s-account.zip' % source_dest
db_name='%s-master-account' % str(first_build.id).zfill(5)
self.assertEqual(
str(cmd).split(' && '),
[
'mkdir /data/build/restore',
'cd /data/build/restore',
f'wget {dump_url}',
f'unzip -q {zip_name}',
'echo "### restoring filestore"',
f'mkdir -p /data/build/datadir/filestore/{db_name}',
f'mv filestore/* /data/build/datadir/filestore/{db_name}',
'echo "### restoring db"',
f'psql -q {db_name} < dump.sql',
'cd /data/build',
'echo "### cleaning"',
'rm -r restore',
'echo "### listing modules"',
f'psql {db_name} -c "select name from ir_module_module where state = \'installed\'" -t -A > /data/build/logs/restore_modules_installed.txt',
'echo "### restore" "successful"'
]
)
self.patchers['docker_run'].side_effect = docker_run_restore
first_build.host = host.name
first_build._schedule()
self.patchers['docker_run'].assert_called()

def docker_run_upgrade(cmd, *args, ro_volumes=False, **kwargs):
user = getpass.getuser()
self.assertTrue(ro_volumes.pop(f'/home/{user}/.odoorc').startswith('/tmp/runbot_test/static/build/'))
self.assertEqual(
ro_volumes, {
'/data/build/addons': '/tmp/runbot_test/static/sources/addons/addons120',
'/data/build/server': '/tmp/runbot_test/static/sources/server/server120',
'/data/build/upgrade': '/tmp/runbot_test/static/sources/upgrade/123abc789',
},
"other commit should have been added automaticaly"
)
self.assertEqual(
str(cmd),
'python3 server/server.py {addons_path} --no-xmlrpcs --no-netrpc -u all -d {db_name} --stop-after-init --max-cron-threads=0'.format(
addons_path='--addons-path addons,server/addons,server/core/addons',
db_name='%s-master-account' % str(first_build.id).zfill(5))
)
self.patchers['docker_run'].side_effect = docker_run_upgrade
first_build._schedule()
self.assertEqual(self.patchers['docker_run'].call_count, 2)
current_build = db_builds[0]
for current_build in db_builds:
self.start_patcher('docker_state', 'odoo.addons.runbot.models.build.docker_state', 'END')

suffix = current_build.params_id.dump_db.db_suffix
source_dest = current_build.params_id.dump_db.build_id.dest
def docker_run_restore(cmd, *args, **kwargs):
dump_url = f'http://host.runbot.com/runbot/static/build/{source_dest}/logs/{source_dest}-{suffix}.zip'
zip_name = f'{source_dest}-{suffix}.zip'
db_name = f'{current_build.dest}-{suffix}'
self.assertEqual(
str(cmd).split(' && '),
[
'mkdir /data/build/restore',
'cd /data/build/restore',
f'wget {dump_url}',
f'unzip -q {zip_name}',
'echo "### restoring filestore"',
f'mkdir -p /data/build/datadir/filestore/{db_name}',
f'mv filestore/* /data/build/datadir/filestore/{db_name}',
'echo "### restoring db"',
f'psql -q {db_name} < dump.sql',
'cd /data/build',
'echo "### cleaning"',
'rm -r restore',
'echo "### listing modules"',
f'psql {db_name} -c "select name from ir_module_module where state = \'installed\'" -t -A > /data/build/logs/restore_modules_installed.txt',
'echo "### restore" "successful"'
]
)
self.patchers['docker_run'].side_effect = docker_run_restore
current_build.host = host.name
current_build._schedule()()
self.patchers['docker_run'].assert_called()

def docker_run_upgrade(cmd, *args, ro_volumes=False, **kwargs):
user = getpass.getuser()
self.assertTrue(ro_volumes.pop(f'/home/{user}/.odoorc').startswith('/tmp/runbot_test/static/build/'))
self.assertEqual(
list(ro_volumes.keys()), [
'/data/build/addons',
'/data/build/server',
'/data/build/upgrade',
],
"other commit should have been added automaticaly"
)
self.assertEqual(
str(cmd),
'python3 server/server.py {addons_path} --no-xmlrpcs --no-netrpc -u all -d {db_name} --stop-after-init --max-cron-threads=0'.format(
addons_path='--addons-path addons,server/addons,server/core/addons',
db_name=f'{current_build.dest}-{suffix}')
)
self.patchers['docker_run'].side_effect = docker_run_upgrade
current_build._schedule()()

with patch('builtins.open', mock_open(read_data='')):
current_build._schedule()
self.assertEqual(current_build.local_state, 'done')
current_build._update_globals()
self.assertEqual(current_build.global_state, 'done')
#self.assertEqual(current_build.global_result, 'ok')

self.assertEqual(self.patchers['docker_run'].call_count, 80)

from_version_builds._update_globals()
self.assertEqual(from_version_builds.mapped('global_state'), ['done'] * 8)
to_version_builds._update_globals()
self.assertEqual(to_version_builds.mapped('global_state'), ['done'] * 4)

# test_build_references
batch = self.master_bundle._force()
Expand Down

0 comments on commit 11110ec

Please sign in to comment.