[IMP] runbot: add a config_data field on build

When two steps in the same build needs to exchange informations, some
hacks have to be used. E.g. using the extra_params fields to store comma
separated values.

With this commit, a config_data field is added alongside with a
JsonDictField that automatically transform the data into json.
This commit is contained in:
Christophe Monniez 2019-12-21 11:00:28 +01:00
parent a7f1b94c41
commit 0c8678e671
3 changed files with 72 additions and 0 deletions

50
runbot/fields.py Normal file
View File

@ -0,0 +1,50 @@
from odoo.fields import Field, pycompat
import json
from collections import MutableMapping
from psycopg2.extras import Json
class JsonDictField(Field):
type = 'jsonb'
column_type = ('jsonb', 'jsonb')
column_cast_from = ('varchar',)
def convert_to_write(self, value, record):
return value
def convert_to_column(self, value, record, values=None, validate=True):
val = self.convert_to_cache(value, record, validate=validate)
return Json(value) if val else val
def convert_to_cache(self, value, record, validate=True):
return value.dict if isinstance(value, FieldDict) else value if isinstance(value, dict) else None
def convert_to_record(self, value, record):
return FieldDict(value or {}, self, record)
class FieldDict(MutableMapping):
def __init__(self, init_dict, field, record):
self.field = field
self.record = record
self.dict = init_dict
def __setitem__(self, key, value):
new = self.dict.copy()
new[key] = value
self.record[self.field.name] = new
def __getitem__(self, key):
return self.dict[key]
def __delitem__(self, key):
new = self.dict.copy()
del new[key]
self.record[self.field.name] = new
def __iter__(self):
return iter(self.dict)
def __len__(self):
return len(self.dict)

View File

@ -10,6 +10,7 @@ import time
import datetime
from ..common import dt2time, fqdn, now, grep, uniq_list, local_pgadmin_cursor, s2human, Commit, dest_reg, os
from ..container import docker_build, docker_stop, docker_state, Command
from ..fields import JsonDictField
from odoo.addons.runbot.models.repo import RunbotException
from odoo import models, fields, api
from odoo.exceptions import UserError, ValidationError
@ -54,6 +55,7 @@ class runbot_build(models.Model):
sequence = fields.Integer('Sequence')
log_ids = fields.One2many('ir.logging', 'build_id', string='Logs')
error_log_ids = fields.One2many('ir.logging', 'build_id', domain=[('level', 'in', ['WARNING', 'ERROR', 'CRITICAL'])], string='Error Logs')
config_data = JsonDictField('Json Data')
# state machine

View File

@ -53,6 +53,14 @@ class Test_Build(RunbotCase):
build._compute_domain()
self.assertEqual(build.domain, 'runbot99.example.org:1234')
# test json stored _data field and data property
self.assertEqual(build.config_data, {})
build.config_data = {'restore_url': 'foobar'}
self.assertEqual(build.config_data, {'restore_url': 'foobar'})
build.config_data['test_info'] = 'dummy'
self.assertEqual(build.config_data, {"restore_url": "foobar", "test_info": "dummy"})
del build.config_data['restore_url']
self.assertEqual(build.config_data, {"test_info": "dummy"})
other = self.create_build({
'branch_id': self.branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
@ -69,6 +77,18 @@ class Test_Build(RunbotCase):
with self.assertRaises(AssertionError):
builds.write({'local_state': 'duplicate'})
# test non initialized json stored _data field and data property
other.config_data['test_info'] = 'foo'
self.assertEqual(other.config_data, {'test_info': 'foo'})
(build|other).write({'config_data': {'test_write': 'written'}})
build.config_data['test_build'] = 'foo'
other.config_data['test_other'] = 'bar'
self.assertEqual(build.config_data, {'test_write': 'written', 'test_build': 'foo'})
self.assertEqual(other.config_data, {'test_write': 'written', 'test_other': 'bar'})
build.flush()
build.env.cr.execute("SELECT config_data, config_data->'test_write' AS written, config_data->'test_build' AS test_build FROM runbot_build WHERE id = %s", [build.id])
self.assertEqual([({'test_write': 'written', 'test_build': 'foo'}, 'written', 'foo')], self.env.cr.fetchall())
@patch('odoo.addons.runbot.models.build.runbot_build._get_repo_available_modules')
def test_filter_modules(self, mock_get_repo_mods):
""" test module filtering """