runbot/runbot_populate/models/runbot.py

144 lines
6.7 KiB
Python
Raw Permalink Normal View History

2021-12-08 19:50:23 +07:00
from odoo import models, fields, api
from unittest.mock import patch
from odoo.tools import mute_logger
import logging
_logger = logging.getLogger(__name__)
2023-06-20 14:47:20 +07:00
2021-12-08 19:50:23 +07:00
class Runbot(models.AbstractModel):
_inherit = 'runbot.runbot'
@api.model
@patch('odoo.addons.runbot.models.repo.Remote._github')
@patch('odoo.addons.runbot.models.repo.Repo._git')
def _create_demo_data(self, mock_git, mock_github):
mock_github.return_value = False
project = self.env.ref('runbot.main_project')
2021-12-08 19:50:23 +07:00
bundles = self.env['runbot.bundle'].browse(
self.env['ir.model.data'].search([
('module', '=', 'runbot_populate'), ('model', '=', 'runbot.bundle')
]).mapped('res_id')
).filtered(lambda bundle: bundle.project_id == project)
bundles |= project.master_bundle_id
2021-12-08 19:50:23 +07:00
bundles = bundles.sorted('is_base', reverse=True)
existing_bundle = bundles.search([('project_id', '=', project.id)])
expected_bundle = bundles | project.dummy_bundle_id
assert expected_bundle == existing_bundle
2021-12-08 19:50:23 +07:00
if bundles.branch_ids:
2021-12-08 19:50:23 +07:00
# only populate data if no branch are found
return
if not bundles.branch_ids:
pr = True
count = 1000
for bundle in bundles:
_logger.info(bundle.name)
for repo in bundle.project_id.repo_ids:
main_remote = repo.main_remote_id
dev_remote = next((remote for remote in repo.remote_ids if remote != main_remote), main_remote)
if bundle.is_base:
dev_remote = main_remote
self.env['runbot.branch'].create({'remote_id': dev_remote.id, 'name': bundle.name, 'is_pr': False})
2022-02-01 14:48:16 +07:00
if not bundle.is_base:
2021-12-08 19:50:23 +07:00
mock_github.return_value = {
'base': {
'ref': bundle.base_id.name
},
'head': {
'label': '%s:%s' % (dev_remote.owner, bundle.name),
'repo': {'full_name': '%s/%s' % (dev_remote.owner, dev_remote.repo_name)}
2022-11-21 15:11:12 +07:00
},
'title': '[IMP] Title',
'body': 'Body',
2022-11-21 22:45:31 +07:00
'user': {
2022-11-21 15:11:12 +07:00
'login': 'Pr author'
},
2021-12-08 19:50:23 +07:00
}
branch = self.env['runbot.branch'].create({
'remote_id': main_remote.id,
'name': str(count),
'is_pr': True,
})
count += 1
2023-06-20 14:47:20 +07:00
branch.flush_recordset()
2021-12-08 19:50:23 +07:00
2022-02-01 14:48:16 +07:00
if 'partial' in bundle.name:
break
2021-12-08 19:50:23 +07:00
if not bundle.is_base:
pr = not pr
security_config = self.env.ref('runbot_populate.runbot_build_config_security')
linting_config = self.env.ref('runbot_populate.runbot_build_config_linting')
for bundle in bundles:
nb_batch = 4 if bundle.sticky else 2
for i in range(nb_batch):
values = {
'last_update': fields.Datetime.now(),
'bundle_id': bundle.id,
'state': 'preparing',
}
batch = self.env['runbot.batch'].create(values)
bundle.last_batch = batch
for repo in bundle.project_id.repo_ids:
commit = self.env['runbot.commit']._get('%s00b%s0000ba%s000' % (repo.id, bundle.id, batch.id), repo.id, {
'author': 'Author',
'author_email': 'author@example.com',
'committer': 'Committer',
'committer_email': 'committer@example.com',
'subject': '[IMP] core: come imp',
'date': fields.Datetime.now(),
})
branches = bundle.branch_ids.filtered(lambda b: b.remote_id.repo_id == repo)
for branch in branches:
branch.head = commit
batch._new_commit(branch)
def git(command):
if command[0] == 'merge-base':
_, sha1, sha2 = command
2022-02-01 14:48:16 +07:00
return sha1 if sha1 == sha2 else sha2 #if bundle.is_base else '%s_%s' % (sha1, sha2)
2021-12-08 19:50:23 +07:00
elif command[0] == 'rev-list':
_, _, _, shas = command
sha1, sha2 = shas.split('...')
return '0\t0' if command[1] == command[2] else '3\t5'
elif command[0] == 'diff':
_, _, sha1, sha2 = command
return '' if sha1 == sha2 else '0 5 _\n1 8 _'
else:
_logger.info(command)
mock_git.side_effect = git
with mute_logger('odoo.addons.runbot.models.batch'):
batch._process()
2021-12-08 19:50:23 +07:00
if i != nb_batch - 1:
for slot in batch.slot_ids:
if slot.build_id:
build = slot.build_id
with mute_logger('odoo.addons.runbot.models.build'):
build._log('******','Starting step X', level='SEPARATOR')
build._log('******','Some log')
for config in (linting_config, security_config):
child = build._add_child({'config_id': config.id})
build._log('create_build', 'created with config %s' % config.name, log_type='subbuild', path=str(child.id))
child.local_state = 'done'
child.local_result = 'ok'
child.description = "Description for security"
build._log('******','Step x finished')
build._log('******','Starting step Y', level='SEPARATOR')
build._log('******','Some log', level='ERROR')
build._log('******','Some log\n with multiple lines', level='ERROR')
[FIX] runbot: fix markdown adding escape A common error on runbot is to generate link containing a __init__.py file [/some/path/to/__init__.py](/some/path/to/__init__.py) This would be rendered as <a href="/some/path/to/<ins>init<ins>.py">/some/path/to/<ins>init<ins>.py</a> Breaking the link, and the display of the name By default markdown will not render links avoiding this issue, but it will remain for the content of the a, needing to manage some kind of escaping. The way to escape markdown is to add a \ before any special character This must be done upront before formating, adding the method markdown_escape Our implementation of markdown is not meant to meet the exact specification of markdown but better suit our needs. One of the requirements is to be able to use it to format message easily but adding dynamic countent comming from the outside. One of the error than can occur is also 'Some code `%s`' % code can also cause problem if code contains ` This issue could be solved using indented code block, but this would need to complexify the generated string, have a dedicated method to escape the code blocs, ... Since we have the controll on the input, we can easily sanitize all ynamic content to avoid such issues. For code block we introduce a way to escape backtick (\`). It is non standard but will be easier to use. Combine with that, the build._log method now allows to add args with the values to format the string (similar to logging) but will escape params by default. (cr.execute spirit) name = '__init__.py' url = 'path/to/__init__.py' code = '# comment `for` something' build._log('f', 'Some message [%s](%s) \n `%s`', name, url, code) name, url and code will be escaped
2024-09-03 20:25:17 +07:00
build._log('******','**Some** *markdown* [log](%s)', 'http://example.com', log_type='markdown')
2021-12-08 19:50:23 +07:00
build._log('******','Step x finished', level='SEPARATOR')
build.local_state = 'done'
build.local_result = 'ok' if bundle.sticky else 'ko'
batch._process()