From c6924a85bc75f12d2858678259914933417e3f0f Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Fri, 21 Jul 2017 14:20:09 +0200 Subject: [PATCH 01/72] [ADD] two modules from 8.0 WIP branch --- github_connector/README.rst | 106 +++++++ github_connector/__init__.py | 2 + github_connector/__openerp__.py | 51 ++++ github_connector/data/ir_config_parameter.xml | 27 ++ github_connector/data/ir_cron.xml | 48 +++ github_connector/demo/github_organization.xml | 29 ++ .../demo/github_organization_serie.xml | 51 ++++ github_connector/demo/res_groups.xml | 17 ++ github_connector/models/__init__.py | 27 ++ .../models/abstract_github_model.py | 222 ++++++++++++++ .../models/abstract_github_model_author.py | 53 ++++ github_connector/models/git_author.py | 56 ++++ github_connector/models/git_commit.py | 94 ++++++ github_connector/models/github.py | 112 +++++++ github_connector/models/github_comment.py | 70 +++++ github_connector/models/github_issue.py | 111 +++++++ .../models/github_organization.py | 163 +++++++++++ .../models/github_organization_serie.py | 25 ++ github_connector/models/github_repository.py | 180 ++++++++++++ .../models/github_repository_branch.py | 275 ++++++++++++++++++ github_connector/models/github_team.py | 65 +++++ github_connector/models/ir_values.py | 68 +++++ github_connector/models/res_partner.py | 141 +++++++++ .../models/wizard_download_analyze_branch.py | 26 ++ .../models/wizard_load_github_model.py | 35 +++ .../models/wizard_update_branch_list.py | 17 ++ .../models/wizard_update_company_author.py | 22 ++ .../models/wizard_update_from_github.py | 26 ++ github_connector/security/ir.model.access.csv | 27 ++ .../security/ir_model_category.xml | 14 + github_connector/security/res_groups.xml | 15 + .../static/description/github_settings.png | Bin 0 -> 15409 bytes github_connector/static/description/icon.png | Bin 0 -> 29578 bytes .../description/organization_series.png | Bin 0 -> 41979 bytes .../reporting_branches_by_serie.png | Bin 0 -> 8458 bytes ...porting_commit_by_repository_and_serie.png | Bin 0 -> 16735 bytes .../description/reporting_sizes_by_serie.png | Bin 0 -> 10979 bytes .../description/repository_branch_list.png | Bin 0 -> 30294 bytes .../static/description/sync_organization.png | Bin 0 -> 18377 bytes github_connector/views/action.xml | 228 +++++++++++++++ github_connector/views/menu.xml | 140 +++++++++ github_connector/views/view_git_author.xml | 69 +++++ github_connector/views/view_git_commit.xml | 54 ++++ .../views/view_github_comment.xml | 79 +++++ github_connector/views/view_github_issue.xml | 118 ++++++++ .../views/view_github_organization.xml | 118 ++++++++ .../views/view_github_repository.xml | 108 +++++++ .../views/view_github_repository_branch.xml | 96 ++++++ github_connector/views/view_github_team.xml | 91 ++++++ github_connector/views/view_reporting.xml | 88 ++++++ github_connector/views/view_res_partner.xml | 128 ++++++++ .../view_wizard_download_analyze_branch.xml | 27 ++ .../views/view_wizard_load_github_model.xml | 27 ++ .../views/view_wizard_update_branch_list.xml | 22 ++ .../view_wizard_update_company_author.xml | 25 ++ .../views/view_wizard_update_from_github.xml | 25 ++ 56 files changed, 3618 insertions(+) create mode 100644 github_connector/README.rst create mode 100644 github_connector/__init__.py create mode 100644 github_connector/__openerp__.py create mode 100644 github_connector/data/ir_config_parameter.xml create mode 100644 github_connector/data/ir_cron.xml create mode 100644 github_connector/demo/github_organization.xml create mode 100644 github_connector/demo/github_organization_serie.xml create mode 100644 github_connector/demo/res_groups.xml create mode 100644 github_connector/models/__init__.py create mode 100644 github_connector/models/abstract_github_model.py create mode 100644 github_connector/models/abstract_github_model_author.py create mode 100644 github_connector/models/git_author.py create mode 100644 github_connector/models/git_commit.py create mode 100644 github_connector/models/github.py create mode 100644 github_connector/models/github_comment.py create mode 100644 github_connector/models/github_issue.py create mode 100644 github_connector/models/github_organization.py create mode 100644 github_connector/models/github_organization_serie.py create mode 100644 github_connector/models/github_repository.py create mode 100644 github_connector/models/github_repository_branch.py create mode 100644 github_connector/models/github_team.py create mode 100644 github_connector/models/ir_values.py create mode 100644 github_connector/models/res_partner.py create mode 100644 github_connector/models/wizard_download_analyze_branch.py create mode 100644 github_connector/models/wizard_load_github_model.py create mode 100644 github_connector/models/wizard_update_branch_list.py create mode 100644 github_connector/models/wizard_update_company_author.py create mode 100644 github_connector/models/wizard_update_from_github.py create mode 100644 github_connector/security/ir.model.access.csv create mode 100644 github_connector/security/ir_model_category.xml create mode 100644 github_connector/security/res_groups.xml create mode 100644 github_connector/static/description/github_settings.png create mode 100644 github_connector/static/description/icon.png create mode 100644 github_connector/static/description/organization_series.png create mode 100644 github_connector/static/description/reporting_branches_by_serie.png create mode 100644 github_connector/static/description/reporting_commit_by_repository_and_serie.png create mode 100644 github_connector/static/description/reporting_sizes_by_serie.png create mode 100644 github_connector/static/description/repository_branch_list.png create mode 100644 github_connector/static/description/sync_organization.png create mode 100644 github_connector/views/action.xml create mode 100644 github_connector/views/menu.xml create mode 100644 github_connector/views/view_git_author.xml create mode 100644 github_connector/views/view_git_commit.xml create mode 100644 github_connector/views/view_github_comment.xml create mode 100644 github_connector/views/view_github_issue.xml create mode 100644 github_connector/views/view_github_organization.xml create mode 100644 github_connector/views/view_github_repository.xml create mode 100644 github_connector/views/view_github_repository_branch.xml create mode 100644 github_connector/views/view_github_team.xml create mode 100644 github_connector/views/view_reporting.xml create mode 100644 github_connector/views/view_res_partner.xml create mode 100644 github_connector/views/view_wizard_download_analyze_branch.xml create mode 100644 github_connector/views/view_wizard_load_github_model.xml create mode 100644 github_connector/views/view_wizard_update_branch_list.xml create mode 100644 github_connector/views/view_wizard_update_company_author.xml create mode 100644 github_connector/views/view_wizard_update_from_github.xml diff --git a/github_connector/README.rst b/github_connector/README.rst new file mode 100644 index 00000000..ea706d9f --- /dev/null +++ b/github_connector/README.rst @@ -0,0 +1,106 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :alt: License: AGPL-3 + +====================================== +Load Github Data in your Odoo Instance +====================================== + +This module allow you to + +* recover social informations from Github. (Members of organizations, + Pull Requests, Issues, Comments, ...) +* download source code from Github + +Configuration +============= + +Once installed, you have to: + +* Open your openerp.cfg file and add extra settings to mention github + credentials, adding the following entries + +github_login = your_github_login +github_password = your_github_password + +* go to 'Settings' / 'Technical' / 'Parameters' / 'System Parameters' + * github.max_try: mention the number of call to the API, before an error + is raised. Set an high value if your connection is bad + * git.source_code_loca_path: set a local folder, that will be used to + download source code from github + * git.partial_commit_during_analyze: Set to True if you want to commit + in the database the result of the analysis after each repository analysis. + Set to True if you have a lot of repository to reduce the size of + the transaction, when you realize the first big analyse. + +.. image:: /github_connector/static/description/github_settings.png + +* Go to your(s) user(s) form to put them in the new 'Connector Github Manager' + groups. The members of this group will have the possibility to run Github + synchronization. + +Usage +===== + +To recover information from github, you have to: + +* go to 'Github' / 'Settings' / 'Sync Object' +* Select the object type you want to synchronize and its github name + +.. image:: /github_connector/static/description/sync_organization.png + +Optionaly, once organization created, you have to create series of your project + +* Go to 'Github' / 'Organizations' / click on your organization / + 'Organization Series' Tabs + +.. image:: /github_connector/static/description/organization_series.png + +For each branches of your repositories, you can download the Source Code, and +once downloaded you can analyze it. Analyze in this module is basic. (For the +time being, it just gives branches sizes). But you can develop an extra Odoo +Custom module to extend analyze function and get extra stats, depending of your +needs. + +.. image:: /github_connector/static/description/repository_branch_list.png + +Reporting +========= + +This module provides several reportings. + +**Commits by branches and by series** + +.. image:: /github_connector/static/description/reporting_commit_by_repository_and_serie.png + +**Branches by Series** + +.. image:: /github_connector/static/description/reporting_branches_by_serie.png + +**Sizes by Series** + +.. image:: /github_connector/static/description/reporting_sizes_by_serie.png + +Credits +======= + +Contributors +------------ + +* Sylvain LE GAL (https://twitter.com/legalsylvain) +* Sébastien BEAU (sebastien.beau@akretion.com) +* Benoît GUILLOT (benoit.guillot@akretion.com) + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit http://odoo-community.org. diff --git a/github_connector/__init__.py b/github_connector/__init__.py new file mode 100644 index 00000000..402ac47e --- /dev/null +++ b/github_connector/__init__.py @@ -0,0 +1,2 @@ +# -#- coding: utf-8 -#- +from . import models diff --git a/github_connector/__openerp__.py b/github_connector/__openerp__.py new file mode 100644 index 00000000..b645f29e --- /dev/null +++ b/github_connector/__openerp__.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# @author: Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + 'name': 'Github Connector', + 'summary': 'Recover information from github repositories', + 'version': '8.0.1.0.0', + 'category': 'Connector', + 'license': 'AGPL-3', + 'author': + 'Odoo Community Association (OCA), GRAP, Akretion' + ', Sylvain LE GAL', + 'depends': [ + 'base', + ], + 'data': [ + 'security/ir_model_category.xml', + 'security/res_groups.xml', + 'security/ir.model.access.csv', + 'data/ir_config_parameter.xml', + 'data/ir_cron.xml', + 'views/view_wizard_load_github_model.xml', + 'views/view_wizard_update_from_github.xml', + 'views/view_wizard_update_company_author.xml', + 'views/view_wizard_update_branch_list.xml', + 'views/view_reporting.xml', + 'views/action.xml', + 'views/view_git_author.xml', + 'views/view_git_commit.xml', + 'views/view_res_partner.xml', + 'views/view_github_organization.xml', + 'views/view_wizard_download_analyze_branch.xml', + 'views/view_github_repository.xml', + 'views/view_github_repository_branch.xml', + 'views/view_github_team.xml', + 'views/view_github_issue.xml', + 'views/view_github_comment.xml', + 'views/menu.xml', + ], + 'demo': [ + 'demo/res_groups.xml', + 'demo/github_organization.xml', + 'demo/github_organization_serie.xml', + ], + 'installable': True, + 'external_dependencies': { + 'python': ['git', 'markdown'], + }, +} diff --git a/github_connector/data/ir_config_parameter.xml b/github_connector/data/ir_config_parameter.xml new file mode 100644 index 00000000..e24b7f61 --- /dev/null +++ b/github_connector/data/ir_config_parameter.xml @@ -0,0 +1,27 @@ + + + + + + github.max_try + 5 + + + + + git.source_code_local_path + /tmp/ + + + + + git.partial_commit_during_analyze + True + + + + diff --git a/github_connector/data/ir_cron.xml b/github_connector/data/ir_cron.xml new file mode 100644 index 00000000..ff6b9a0f --- /dev/null +++ b/github_connector/data/ir_cron.xml @@ -0,0 +1,48 @@ + + + + + + Download Branches List for All repositories + 1 + + + days + -1 + + + + + + + + Download Source Code from All Github Branches + 1 + + + days + -1 + + + + + + + + Analyze All Github Branches + 1 + + + days + -1 + + + + + + + diff --git a/github_connector/demo/github_organization.xml b/github_connector/demo/github_organization.xml new file mode 100644 index 00000000..3111e171 --- /dev/null +++ b/github_connector/demo/github_organization.xml @@ -0,0 +1,29 @@ + + + + + + Odoo Community Association + OCA + + + + + diff --git a/github_connector/demo/github_organization_serie.xml b/github_connector/demo/github_organization_serie.xml new file mode 100644 index 00000000..69874d56 --- /dev/null +++ b/github_connector/demo/github_organization_serie.xml @@ -0,0 +1,51 @@ + + + + + + 1 + 5.0 + + + + + 2 + 6.0 + + + + + 3 + 6.1 + + + + + 4 + 7.0 + + + + + 5 + 8.0 + + + + + 6 + 9.0 + + + + + 7 + 10.0 + + + + diff --git a/github_connector/demo/res_groups.xml b/github_connector/demo/res_groups.xml new file mode 100644 index 00000000..96bd2265 --- /dev/null +++ b/github_connector/demo/res_groups.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + diff --git a/github_connector/models/__init__.py b/github_connector/models/__init__.py new file mode 100644 index 00000000..0a44d7a7 --- /dev/null +++ b/github_connector/models/__init__.py @@ -0,0 +1,27 @@ +# -#- coding: utf-8 -#- + +from . import github +from . import abstract_github_model +from . import abstract_github_model_author + +from . import res_partner +from . import ir_values + +from . import git_author +from . import git_commit + +from . import github_issue +from . import github_organization +from . import github_organization_serie +from . import github_repository +from . import github_repository_branch +from . import github_team +from . import github_comment + +from . import wizard_load_github_model + +from . import wizard_download_analyze_branch + +from . import wizard_update_from_github +from . import wizard_update_company_author +from . import wizard_update_branch_list diff --git a/github_connector/models/abstract_github_model.py b/github_connector/models/abstract_github_model.py new file mode 100644 index 00000000..a44fe0a8 --- /dev/null +++ b/github_connector/models/abstract_github_model.py @@ -0,0 +1,222 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import base64 +import urllib +import logging +from datetime import datetime + +from openerp import tools, api, fields, models, exceptions, _ +from .github import Github + +_logger = logging.getLogger(__name__) + + +class AbtractGithubModel(models.AbstractModel): + """ + This abstract model is used to share all features related to github model. + Note that some fields and function have to be defined in the inherited + model. (github_type for instance) + """ + + _name = 'abstract.github.model' + _github_type = None + _github_login_field = None + _need_individual_call = False + + github_id = fields.Char( + string='Github Id', readonly=True, select=True) + + github_login = fields.Char( + string='Github Technical Name', readonly=True, select=True) + + github_url = fields.Char( + string='Github URL', readonly=True) + + github_create_date = fields.Datetime( + string='Create Date on Github', readonly=True) + + github_write_date = fields.Datetime( + string='Last Write Date on Github', readonly=True) + + github_last_sync_date = fields.Datetime( + string='Last Sync Date with Github', readonly=True) + + # Overloadable Section + def github_type(self): + if self._github_type is None: + raise exceptions.Warning( + _("Unimplemented Feature"), + _("Please define github_type function in child model.")) + else: + return self._github_type + + def github_login_field(self): + if self._github_login_field is None: + raise exceptions.Warning( + _("Unimplemented Feature"), + _("Please define github_login_field function in child model.")) + else: + return self._github_login_field + + @api.model + def get_odoo_data_from_github(self, data): + return { + 'github_id': data['id'], + 'github_url': data.get('html_url', False), + 'github_login': data.get(self.github_login_field(), False), + 'github_create_date': data.get('created_at', False), + 'github_write_date': data.get('updated_at', False), + 'github_last_sync_date': + datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + } + + @api.multi + def full_update(self): + pass + + # Custom Public Function + @api.model + def get_from_id_or_create(self, data, extra_data=None): + """Search if the odoo object exists in database. If yes, returns the + object. Otherwise, creates the new object. + + :param data: dict with github 'id' and 'url' keys + :return: The searched or created object + + :Example: + + >>> self.env['github_organization'].get_from_id_or_create( + {'id': 7600578, 'url': 'https://api.github.com/orgs/OCA'}) + """ + extra_data = extra_data and extra_data or {} + + # We try to search object by id + existing_object = self.search([('github_id', '=', data['id'])]) + if existing_object: + return existing_object + + # We try to see if object exist by name (instead of id) + if self._github_login_field: + existing_object = self.search([ + ('github_login', '=', data[self._github_login_field])]) + if existing_object: + # Update the existing object with the id + existing_object.github_id = data['id'] + _logger.info( + "Existing object %s#%d with github name '%s' has been" + " updated with unique github id %s#%s" % ( + self._name, existing_object.id, + data[self._github_login_field], data['id'], + self.github_type())) + return existing_object + + if self._need_individual_call: + github_model = self.get_github_for(self.github_type()) + data = github_model.get_by_url(data['url']) + return self._create_from_github_data(data, extra_data) + + @api.model + def create_from_name(self, name): + """Call Github API, using a url using github name. Load data and + Create Odoo object accordingly, if the odoo object doesn't exist. + + :param name: the github name to load + :return: The created object + + :Example: + + >>> self.env['github_organization'].create_from_name('OCA') + >>> self.env['github_repository'].create_from_name('OCA/web') + """ + github_model = self.get_github_for(self.github_type()) + res = github_model.get([name]) + # search if ID doesn't exist in database + current_object = self.search([('github_id', '=', res['id'])]) + if not current_object: + # Create the object + return self._create_from_github_data(res) + + @api.multi + def button_update_from_github_light(self): + return self.update_from_github(False) + + @api.multi + def button_update_from_github_full(self): + return self.update_from_github(True) + + @api.multi + def update_from_github(self, child_update): + """Call Github API, using a url using github id. Load data and + update Odoo object accordingly, if the odoo object is obsolete. + (Based on last write dates) + + :param child_update: set to True if you want to reload childs + Objects linked to this object. (like members for teams) + """ + github_model = self.get_github_for(self.github_type()) + for item in self: + if item._model._name == 'github.issue': + # Github doesn't provides api to load an issue by id + res = github_model.get( + [item.repository_id.github_login, item.github_login]) + elif item._model._name == 'github.organization': + # Github doesn't provides api to load an organization by id + res = github_model.get([item.github_login]) + else: + res = github_model.get([item.github_id], by_id=True) + item._update_from_github_data(res) + if child_update: + self.full_update() + + def get_base64_image_from_github(self, url): + max_try = int( + self.env['ir.config_parameter'].get_param('github.max_try')) + for i in range(max_try): + try: + stream = urllib.urlopen(url).read() + break + except Exception as err: + _logger.warning("URL Call Error. %s" % (err.__str__())) + else: + raise err + return base64.standard_b64encode(stream) + + # Custom Private Function + @api.model + def _create_from_github_data(self, data, extra_data=None): + extra_data = extra_data and extra_data or {} + vals = self.get_odoo_data_from_github(data) + vals.update(extra_data) + return self.create(vals) + + @api.multi + def _update_from_github_data(self, data): + for item in self: + vals = self.get_odoo_data_from_github(data) + # Optimization. Due to the fact that github datas rarely change, + # and that there a lot of related / computed fields invalidation + # process, we realize a write only if data changed + to_write = {} + for k, v in vals.iteritems(): + # TODO : improve, this line raise a warning on many2one + # comparison "Comparing apples and oranges..." + if item[k] != v: + to_write[k] = v + if to_write: + item.write(to_write) + + @api.multi + def get_github_for(self, github_type): + if (not tools.config.get('github_login') or + not tools.config.get('github_password')): + raise exceptions.Warning(_("Configuration Error"), _( + "Please add 'github_login' and 'github_password' " + "in Odoo configuration file.")) + return Github( + github_type, + tools.config['github_login'], + tools.config['github_password'], + int(self.env['ir.config_parameter'].get_param('github.max_try'))) diff --git a/github_connector/models/abstract_github_model_author.py b/github_connector/models/abstract_github_model_author.py new file mode 100644 index 00000000..5d5863c8 --- /dev/null +++ b/github_connector/models/abstract_github_model_author.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, fields, models + + +class AbtractGithubModelAuthor(models.AbstractModel): + """ + This Abstract Model is used to share behaviour between some github models + that have an author_id. + * define the company related to the author. + """ + + _name = 'abstract.github.model.author' + _inherit = ['abstract.github.model'] + + author_id = fields.Many2one( + comodel_name='res.partner', string='Author', readonly=True, + required=True) + + company_author_id = fields.Many2one( + comodel_name='res.partner', string='Author Company') + + # Overloadable Section + def get_odoo_data_from_github(self, data): + partner_obj = self.env['res.partner'] + res = super(AbtractGithubModelAuthor, self)\ + .get_odoo_data_from_github(data) + partner = partner_obj.get_from_id_or_create(data['user']) + res.update({ + 'author_id': partner.id, + }) + return res + + @api.model + def create(self, vals): + # Set related company of the author, if defined + partner = self.env['res.partner'].browse(vals.get('author_id')) + vals.update({'company_author_id': partner.parent_id.id}) + res = super(AbtractGithubModelAuthor, self).create(vals) + return res + + @api.multi + def write(self, vals): + if vals.get('author_id'): + # Set related company of the author, if defined + partner = self.env['res.partner'].browse(vals.get('author_id')) + if partner.company_id: + vals.update({'company_author_id': partner.company_id.id}) + res = super(AbtractGithubModelAuthor, self).write(vals) + return res diff --git a/github_connector/models/git_author.py b/github_connector/models/git_author.py new file mode 100644 index 00000000..aba7d4db --- /dev/null +++ b/github_connector/models/git_author.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, fields, api + + +class GitAuthor(models.Model): + _name = 'git.author' + _order = 'commit_qty desc' + + # Column Section + name = fields.Char( + string='Name', store=True, select=True, readonly=True) + + email = fields.Char( + string='Email', store=True, readonly=True, select=True) + + partner_id = fields.Many2one( + string='Partner', comodel_name='res.partner') + + company_partner_id = fields.Many2one( + string='Company', comodel_name='res.partner', + domain="[('is_company', '=', True)]") + + commit_ids = fields.One2many( + comodel_name='git.commit', inverse_name='author_id', + string='Commits') + + commit_qty = fields.Integer( + string='Commits Quantity', compute='_compute_commit_qty', store=True) + + # Compute Section + @api.multi + @api.depends('commit_ids.author_id') + def _compute_commit_qty(self): + for author in self: + author.commit_qty = len(author.commit_ids) + + # Custom Section + @api.model + def create_if_not_exist(self, myGitAuthor): + partner_obj = self.env['res.partner'] + author = self.search([('email', '=', myGitAuthor.email)]) + if not author: + # Try to guess partner_id, by email + partner = partner_obj.search([ + ('email', '=', myGitAuthor.email)], limit=1) + partner_id = len(partner) and partner[0].id or False + author = self.create({ + 'name': myGitAuthor.name, + 'email': myGitAuthor.email, + 'partner_id': partner_id, + }) + return author diff --git a/github_connector/models/git_commit.py b/github_connector/models/git_commit.py new file mode 100644 index 00000000..b4e2e7db --- /dev/null +++ b/github_connector/models/git_commit.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import time + +from openerp import models, fields, api + + +class GitCommit(models.Model): + _name = 'git.commit' + + # Column Section + name = fields.Char( + string='Name', readonly=True, select=True) + + summary = fields.Char( + string='Summary', readonly=True) + + message = fields.Char( + string='Message', readonly=True) + + author_id = fields.Many2one( + string='Git Author', comodel_name='git.author', required=True, + select=True, ondelete='cascade', readonly=True) + + partner_id = fields.Many2one( + comodel_name='res.partner', string='Partner', + related='author_id.partner_id', store=True, readonly=True) + + company_partner_id = fields.Many2one( + comodel_name='res.partner', string='Company', + related='author_id.company_partner_id', store=True, readonly=True) + + authored_date = fields.Datetime( + string='Authored Date', readonly=True) + + repository_branch_id = fields.Many2one( + string='Repository Branch', comodel_name='github.repository.branch', + required=True, select=True, ondelete='cascade', readonly=True) + + repository_id = fields.Many2one( + comodel_name='github.repository', string='Repository', + related='repository_branch_id.repository_id', store=True, + readonly=True) + + organization_id = fields.Many2one( + comodel_name='github.organization', string='Organization', + related='repository_id.organization_id', store=True, + readonly=True) + + organization_serie_id = fields.Many2one( + comodel_name='github.organization.serie', string='Organization Serie', + related='repository_branch_id.organization_serie_id', store=True, + readonly=True) + + insertions_qty = fields.Integer(string='Insertions Qty', readonly=True) + deletions_qty = fields.Integer(string='Deletions Qty', readonly=True) + lines_qty = fields.Integer(string='Lines Qty', readonly=True) + files_qty = fields.Integer(string='Files Qty', readonly=True) + + # Overload Section + @api.multi + def unlink(self): + # Analyzed repository branches should be reanalyzed + if not self._context.get('dont_change_repository_branch_state', False): + repository_branch_obj = self.env['github.repository.branch'] + repository_branch_obj.search([ + ('id', 'in', self.mapped('repository_branch_id').ids), + ('state', '=', 'analyzed')]).write({'state': 'to_analyze'}) + return super(GitCommit, self).unlink() + + # Custom Section + @api.model + def create_or_replace_with_git_data(self, myGitCommit, repository_branch): + git_author_obj = self.env['git.author'] + self.search([('name', '=', myGitCommit.hexsha)]).with_context( + dont_change_repository_branch_state=True).unlink() + author = git_author_obj.create_if_not_exist(myGitCommit.author) + return self.create({ + 'name': myGitCommit.hexsha, + 'author_id': author.id, + 'repository_branch_id': repository_branch.id, + 'summary': myGitCommit.summary, + 'message': myGitCommit.message, + 'authored_date': time.strftime( + "%Y-%m-%d %H:%M", + time.gmtime(myGitCommit.committed_date)), + 'deletions_qty': myGitCommit.stats.total['deletions'], + 'lines_qty': myGitCommit.stats.total['lines'], + 'insertions_qty': myGitCommit.stats.total['insertions'], + 'files_qty': myGitCommit.stats.total['files'], + }) diff --git a/github_connector/models/github.py b/github_connector/models/github.py new file mode 100644 index 00000000..9e8fac02 --- /dev/null +++ b/github_connector/models/github.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# @author: Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +from openerp import exceptions, _ + +from requests.auth import HTTPBasicAuth +import requests +import json +import logging + +_logger = logging.getLogger(__name__) + +_MAX_NUMBER_REQUEST = 30 + +_BASE_URL = 'https://api.github.com/' + +_GITHUB_URL = 'https://github.com/' + +_GITHUB_TYPE = [ + ('organization', 'Organization'), + ('repository', 'Repository'), + ('user', 'User'), +] + +_GITHUB_TYPE_URL = { + 'organization': {'url': 'orgs/%s'}, + 'user': {'url': 'users/%s', 'url_by_id': 'user/%s'}, + 'repository': {'url': 'repos/%s', 'url_by_id': 'repositories/%s'}, + 'team': {'url_by_id': 'teams/%s'}, + 'issue': {'url': 'repos/%s/issues/%s'}, + 'organization_members': {'url': 'orgs/%s/members'}, + 'organization_repositories': {'url': 'orgs/%s/repos'}, + 'organization_teams': {'url': 'orgs/%s/teams'}, + 'team_members': {'url': 'teams/%s/members'}, + 'repository_issues': {'url': 'repos/%s/issues?state=all'}, + 'issue_comments': {'url': 'repos/%s/issues/%s/comments'}, + 'repository_branches': {'url': 'repos/%s/branches'}, +} + + +class Github(object): + + def __init__(self, github_type, login, password, max_try): + super(Github, self).__init__() + self.github_type = github_type + self.login = login + self.password = password + self.max_try = max_try + + def list(self, arguments): + page = 1 + datas = [] + while True: + pending_datas = self.get(arguments, False, page) + datas += pending_datas + if pending_datas == [] or\ + len(pending_datas) < _MAX_NUMBER_REQUEST: + break + page += 1 + return datas + + def get_by_url(self, url): + _logger.info("Calling %s" % (url)) + for i in range(self.max_try): + try: + response = requests.get( + url, auth=HTTPBasicAuth(self.login, self.password)) + break + except Exception as err: + _logger.warning("URL Call Error. %d/%d. URL: %s" % ( + i, self.max_try, err.__str__())) + else: + raise err + + if response.status_code == 401: + raise exceptions.Warning( + _("Github Access Error"), + _("Unable to authenticate to Github with the login '%s'.\n" + "You should Check your credentials in the Odoo" + " configuration file.") % (self.login)) + elif response.status_code != 200: + raise exceptions.Warning( + _("Github Error"), + _("The call to '%s' failed:\n" + "- Status Code: %d\n" + "- Reason: %s") % ( + response.url, response.status_code, response.reason)) + return json.loads(response.content) + + def get(self, arguments, by_id=False, page=None): + url = self._build_url(arguments, by_id, page) + return self.get_by_url(url) + + def _build_url(self, arguments, by_id, page): + if by_id: + url = _GITHUB_TYPE_URL[self.github_type]['url_by_id'] + else: + url = _GITHUB_TYPE_URL[self.github_type]['url'] + if self.github_type not in _GITHUB_TYPE_URL.keys(): + raise exceptions.Warning( + _("Unimplemented Connection"), + _("'%s' is not implemented.") % (self.github_type)) + complete_url = _BASE_URL + url % tuple(arguments) + + if page: + complete_url += ('?' in complete_url and '&' or '?') +\ + 'per_page=%d&page=%d' % (_MAX_NUMBER_REQUEST, page) + return complete_url diff --git a/github_connector/models/github_comment.py b/github_connector/models/github_comment.py new file mode 100644 index 00000000..292f68e5 --- /dev/null +++ b/github_connector/models/github_comment.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging + +from openerp import models, fields, api + +_logger = logging.getLogger(__name__) + +try: + import markdown +except ImportError: + _logger.debug("Cannot import 'markdown' python library.") + + +class GithubComment(models.Model): + _name = 'github.comment' + _inherit = ['abstract.github.model.author'] + _order = 'github_id' + + _github_type = 'issue' + _github_login_field = False + + _OPINION_SELECTION = [ + ('neutral', 'Neutral'), + ('approved', 'Approved'), + ('disapproved', 'Disapproved'), + ] + + # Column Section + issue_id = fields.Many2one( + comodel_name='github.issue', string='Issue / PR', readonly=True, + required=True, ondelete='cascade') + + body = fields.Char(string='Body', readonly=True) + + html_body = fields.Html( + string='HTML Body', readonly=True, compute='_compute_by_body', + multi='body', store=True) + + opinion = fields.Selection( + string='Opinion', readonly=True, compute='_compute_by_body', + multi='body', store=True, selection=_OPINION_SELECTION, + default='neutral') + + is_bot_comment = fields.Boolean( + string='Is Bot Comment', related='author_id.is_bot_account', + store=True) + + # Compute section + @api.multi + @api.depends('body') + def _compute_by_body(self): + for comment in self: + if comment.body: + comment.html_body = markdown.markdown(comment.body) + if ':-1:' in comment.body: + comment.opinion = 'disapproved' + elif ':+1:' in comment.body: + comment.opinion = 'approved' + else: + comment.opinion = 'neutral' + + # Overloadable Section + def get_odoo_data_from_github(self, data): + res = super(GithubComment, self).get_odoo_data_from_github(data) + res.update({'body': data['body']}) + return res diff --git a/github_connector/models/github_issue.py b/github_connector/models/github_issue.py new file mode 100644 index 00000000..ca982022 --- /dev/null +++ b/github_connector/models/github_issue.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging + +from openerp import models, fields, api + +_logger = logging.getLogger(__name__) + +try: + import markdown +except ImportError: + _logger.debug("Cannot import 'markdown' python library.") + + +class GithubIssue(models.Model): + _name = 'github.issue' + _inherit = ['abstract.github.model.author'] + + _github_type = 'issue' + _github_login_field = 'number' + + # Column Section + repository_id = fields.Many2one( + comodel_name='github.repository', string='Repository', readonly=True, + required=True, ondelete='cascade') + + issue_type = fields.Selection( + selection=[('issue', 'Issue'), ('pull_request', 'Pull Request')], + string='Type') + + title = fields.Char(string='Title', readonly=True, required=True) + + body = fields.Char(string='Body', readonly=True) + + html_body = fields.Html( + string='HTML Body', readonly=True, compute='_compute_html_body', + store=True) + + state = fields.Selection(selection=[ + ('open', 'Open'), ('closed', 'Closed')], + string='State', readonly=True, required=True) + + comment_ids = fields.One2many( + string='Comments', comodel_name='github.comment', + inverse_name='issue_id', readonly=True) + + comment_qty = fields.Integer( + string='Comments Quantity', compute='_compute_comment_qty', + store=True) + + approved_comment_qty = fields.Integer( + string='Approved Comments Quantity', compute='_compute_opinion', + multi='opinion', store=True) + + disapproved_comment_qty = fields.Integer( + string='Disapproved Comments Quantity', compute='_compute_opinion', + multi='opinion', store=True) + + # Compute section + @api.multi + @api.depends('body') + def _compute_html_body(self): + for issue in self: + if issue.body: + issue.html_body = markdown.markdown(issue.body) + + @api.multi + @api.depends('comment_ids.issue_id') + def _compute_comment_qty(self): + for issue in self: + issue.comment_qty = len(issue.comment_ids) + + @api.depends('comment_ids.opinion') + def _compute_opinion(self): + for issue in self: + opinions = issue.mapped('comment_ids.opinion') + issue.approved_comment_qty = opinions.count('approved') + issue.disapproved_comment_qty = opinions.count('disapproved') + + # Overloadable Section + def get_odoo_data_from_github(self, data): + res = super(GithubIssue, self).get_odoo_data_from_github(data) + res.update({ + 'title': data['title'], + 'body': data['body'], + 'state': data['state'], + 'issue_type': data.get('pull_request', False) and + 'pull_request' or 'issue', + }) + return res + + @api.multi + def full_update(self): + self.button_sync_comment() + + # Action section + @api.multi + def button_sync_comment(self): + github_comment = self.get_github_for('issue_comments') + comment_obj = self.env['github.comment'] + for issue in self: + comment_ids = [] + for data in github_comment.list( + [issue.repository_id.github_login, issue.github_login]): + comment = comment_obj.get_from_id_or_create( + data, {'issue_id': issue.id}) + comment_ids.append(comment.id) + issue.comment_ids = comment_ids diff --git a/github_connector/models/github_organization.py b/github_connector/models/github_organization.py new file mode 100644 index 00000000..8d353478 --- /dev/null +++ b/github_connector/models/github_organization.py @@ -0,0 +1,163 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, models, fields + + +class GithubOrganization(models.Model): + _name = 'github.organization' + _inherit = ['abstract.github.model'] + _order = 'name' + + _github_type = 'organization' + _github_login_field = 'login' + + # Columns Section + name = fields.Char( + string='Organization Name', required=True, readonly=True) + + image = fields.Binary(string='Image', readonly=True) + + description = fields.Char(string='Description', readonly=True) + + email = fields.Char(string='Email', readonly=True) + + website_url = fields.Char(string='Website URL', readonly=True) + + location = fields.Char(string='Location', readonly=True) + + ignored_repository_names = fields.Text( + string='Ignored Repositories', help="Set here repository names you" + " you want to ignore. One repository per line. Exemple:\n" + "odoo-community.org\n" + "OpenUpgrade\n") + + specific_repository_names = fields.Text( + string='Specific Repositories', help="Set here repository names you" + " you want download. One repository per line. The other will be" + " ignored. Exemple:\n" + "pos\n" + "server-tools\n") + + member_ids = fields.Many2many( + string='Members', comodel_name='res.partner', + relation='github_organization_partner_rel', column1='organization_id', + column2='partner_id', readonly=True) + + member_qty = fields.Integer( + string='Members Quantity', compute='_compute_member_qty', + store=True) + + repository_ids = fields.One2many( + string='Repositories', comodel_name='github.repository', + ondelete='cascade', inverse_name='organization_id', readonly=True) + + repository_qty = fields.Integer( + string='Repositories Quantity', compute='_compute_repository_qty', + store=True) + + team_ids = fields.One2many( + string='Teams', comodel_name='github.team', + inverse_name='organization_id', readonly=True) + + team_qty = fields.Integer( + string='Team Quantity', compute='_compute_team_qty', + store=True) + + organization_serie_ids = fields.One2many( + string='Organization Series', + comodel_name='github.organization.serie', + inverse_name='organization_id') + + organization_serie_qty = fields.Integer( + string='Series Quantity', compute='_compute_organization_serie_qty', + store=True) + + # Overloadable Section + @api.model + def get_odoo_data_from_github(self, data): + res = super(GithubOrganization, self).get_odoo_data_from_github(data) + res.update({ + 'name': data['name'], + 'description': data['description'], + 'location': data['location'], + 'website_url': data['blog'], + 'email': data['email'], + 'image': self.get_base64_image_from_github(data['avatar_url']), + }) + return res + + @api.multi + def full_update(self): + self.button_sync_member() + self.button_sync_repository() + self.button_sync_team() + + # Compute Section + @api.multi + @api.depends('member_ids', 'member_ids.organization_ids') + def _compute_member_qty(self): + for organization in self: + organization.member_qty = len(organization.member_ids) + + @api.multi + @api.depends('repository_ids.organization_id') + def _compute_repository_qty(self): + for organization in self: + organization.repository_qty = len(organization.repository_ids) + + @api.multi + @api.depends('team_ids.organization_id') + def _compute_team_qty(self): + for organization in self: + organization.team_qty = len(organization.team_ids) + + @api.multi + @api.depends('organization_serie_ids.organization_id') + def _compute_organization_serie_qty(self): + for organization in self: + organization.organization_serie_qty =\ + len(organization.organization_serie_ids) + + # Action section + @api.multi + def button_sync_member(self): + github_member = self.get_github_for('organization_members') + partner_obj = self.env['res.partner'] + for organization in self: + member_ids = [] + for data in github_member.list([organization.github_login]): + partner = partner_obj.get_from_id_or_create(data) + member_ids.append(partner.id) + organization.member_ids = member_ids + + @api.multi + def button_sync_repository(self): + repository_obj = self.env['github.repository'] + github_repo = self.get_github_for('organization_repositories') + for organization in self: + repository_ids = [] + ignored_list = organization.ignored_repository_names and\ + organization.ignored_repository_names.split("\n") or [] + specific_list = organization.specific_repository_names and\ + organization.specific_repository_names.split("\n") or [] + for data in github_repo.list([organization.github_login]): + if data['name'] not in ignored_list: + if not specific_list or data['name'] in specific_list: + repository = repository_obj.get_from_id_or_create(data) + repository_ids.append(repository.id) + organization.repository_ids = repository_ids + + @api.multi + def button_sync_team(self): + team_obj = self.env['github.team'] + github_team = self.get_github_for('organization_teams') + for organization in self: + team_ids = [] + for data in github_team.list([organization.github_login]): + team = team_obj.get_from_id_or_create( + data, {'organization_id': organization.id}) + team_ids.append(team.id) + organization.team_ids = team_ids diff --git a/github_connector/models/github_organization_serie.py b/github_connector/models/github_organization_serie.py new file mode 100644 index 00000000..ee7a9252 --- /dev/null +++ b/github_connector/models/github_organization_serie.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, fields + + +class GithubOrganizationSerie(models.Model): + _name = 'github.organization.serie' + _order = 'sequence, name' + + # Columns Section + name = fields.Char(string='Name', required=True) + + sequence = fields.Integer(string='Sequence', required=True) + + organization_id = fields.Many2one( + comodel_name='github.organization', string='Organization', + required=True) + + _sql_constraints = [ + ('sequence_organization_uniq', 'unique(organization_id, sequence)', + ("Sequence serie must be unique by organization.")) + ] diff --git a/github_connector/models/github_repository.py b/github_connector/models/github_repository.py new file mode 100644 index 00000000..e87d9091 --- /dev/null +++ b/github_connector/models/github_repository.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging + +from openerp import models, fields, api + +_logger = logging.getLogger(__name__) + + +class GithubRepository(models.Model): + _name = 'github.repository' + _inherit = ['abstract.github.model'] + _order = 'organization_id, name' + + _github_type = 'repository' + _github_login_field = 'full_name' + + # Column Section + organization_id = fields.Many2one( + comodel_name='github.organization', string='Organization', + required=True, select=True, readonly=True, ondelete='cascade') + + name = fields.Char( + string='Name', select=True, required=True, readonly=True) + + complete_name = fields.Char( + string='Complete Name', readonly=True, + compute='_compute_complete_name', store=True) + + description = fields.Char(string='Description', readonly=True) + + website = fields.Char(string='Website', readonly=True) + + repository_branch_ids = fields.One2many( + comodel_name='github.repository.branch', + inverse_name='repository_id', string='Branches', readonly=True) + + repository_branch_qty = fields.Integer( + string='Branches Quantity', compute='_compute_repository_branch_qty', + store=True) + + issue_ids = fields.One2many( + string='Issues + PR', comodel_name='github.issue', + inverse_name='repository_id', readonly=True) + + issue_qty = fields.Integer( + string='Issue + PR Quantity', compute='_compute_issue_qty', + multi='issue', store=True) + + open_issue_qty = fields.Integer( + string='Open Issue + PR Quantity', compute='_compute_issue_qty', + multi='issue', store=True) + + only_issue_qty = fields.Integer( + string='Issue Quantity', compute='_compute_issue_qty', + multi='issue', store=True) + + only_open_issue_qty = fields.Integer( + string='Open Issue Quantity', compute='_compute_issue_qty', + multi='issue', store=True) + + only_pull_request_qty = fields.Integer( + string='PR Quantity', compute='_compute_issue_qty', + multi='issue', store=True) + + only_open_pull_request_qty = fields.Integer( + string='Open PR Quantity', compute='_compute_issue_qty', + multi='issue', store=True) + + # Compute Section + @api.multi + @api.depends('name', 'organization_id.github_login') + def _compute_complete_name(self): + for repository in self: + repository.complete_name =\ + repository.organization_id.github_login + '/' + repository.name + + @api.multi + @api.depends('issue_ids.repository_id') + def _compute_issue_qty(self): + for repository in self: + only_issue_qty = 0 + only_open_issue_qty = 0 + only_pull_request_qty = 0 + only_open_pull_request_qty = 0 + for issue in repository.issue_ids: + if issue.issue_type == 'issue': + only_issue_qty += 1 + if issue.state == 'open': + only_open_issue_qty += 1 + else: + only_pull_request_qty += 1 + if issue.state == 'open': + only_open_pull_request_qty += 1 + repository.only_issue_qty = only_issue_qty + repository.only_open_issue_qty = only_open_issue_qty + repository.only_pull_request_qty = only_pull_request_qty + repository.only_open_pull_request_qty = only_open_pull_request_qty + repository.issue_qty = only_issue_qty + only_pull_request_qty + repository.open_issue_qty =\ + only_open_issue_qty + only_open_pull_request_qty + + @api.multi + @api.depends('repository_branch_ids.repository_id') + def _compute_repository_branch_qty(self): + for repository in self: + repository.repository_branch_qty =\ + len(repository.repository_branch_ids) + + # Overloadable Section + @api.model + def get_odoo_data_from_github(self, data): + organization_obj = self.env['github.organization'] + res = super(GithubRepository, self).get_odoo_data_from_github(data) + organization = organization_obj.get_from_id_or_create(data['owner']) + res.update({ + 'name': data['name'], + 'github_url': data['url'], + 'description': data['description'], + 'website': data['homepage'], + 'organization_id': organization.id, + }) + return res + + @api.multi + def full_update(self): + self.button_sync_issue() + self.button_sync_branch() + + # Action section + @api.multi + def button_sync_issue(self): + github_issue = self.get_github_for('repository_issues') + issue_obj = self.env['github.issue'] + for repository in self: + issue_ids = [] + for data in github_issue.list([repository.github_login]): + issue = issue_obj.get_from_id_or_create( + data, {'repository_id': repository.id}) + issue_ids.append(issue.id) + repository.issue_ids = issue_ids + + @api.multi + def button_sync_issue_with_comment(self): + self.button_sync_issue() + for repository in self: + repository.issue_ids.button_sync_comment() + + @api.model + def cron_update_branch_list(self): + branches = self.search([]) + branches.button_sync_branch() + return True + + @api.multi + def button_sync_branch(self): + github_branch = self.get_github_for('repository_branches') + branch_obj = self.env['github.repository.branch'] + for repository in self: + branch_ids = [] + correct_series =\ + repository.organization_id.organization_serie_ids\ + .mapped('name') + + for data in github_branch.list([repository.github_login]): + # We don't use get_from_id_or_create because repository + # branches does not have any ids. (very basic object in the + # Github API) + if data['name'] in correct_series: + branch = branch_obj.create_or_update_from_name( + repository.id, data['name']) + branch_ids.append(branch.id) + else: + _logger.warning( + "the branch '%s'/'%s' has been ignored." % ( + repository.name, data['name'])) + repository.branch_ids = branch_ids diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py new file mode 100644 index 00000000..7e05ff04 --- /dev/null +++ b/github_connector/models/github_repository_branch.py @@ -0,0 +1,275 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging +import os + +from subprocess import check_output +from datetime import datetime + +from .github import _GITHUB_URL +from openerp import models, fields, api +from openerp.tools.safe_eval import safe_eval + +_logger = logging.getLogger(__name__) + +try: + from git import Repo +except ImportError: + _logger.debug("Cannot import 'git' python library.") + + +class GithubRepository(models.Model): + _name = 'github.repository.branch' + _inherit = ['abstract.github.model'] + _order = 'repository_id, sequence_serie' + + _github_type = 'repository_branches' + _github_login_field = False + + _SELECTION_STATE = [ + ('to_download', 'To Download'), + ('to_analyze', 'To Analyze'), + ('analyzed', 'Analyzed'), + ] + + # Column Section + name = fields.Char( + string='Name', readonly=True, select=True) + + size = fields.Integer( + string='Size (Byte) ', readonly=True) + + mb_size = fields.Float( + string='Size (Megabyte)', store=True, compute='_compute_mb_size') + + complete_name = fields.Char( + string='Complete Name', store=True, compute='_compute_complete_name') + + repository_id = fields.Many2one( + comodel_name='github.repository', string='Repository', + required=True, select=True, readonly=True, ondelete='cascade') + + organization_id = fields.Many2one( + comodel_name='github.organization', string='Organization', + related='repository_id.organization_id', store=True, readonly=True) + + organization_serie_id = fields.Many2one( + comodel_name='github.organization.serie', string='Organization Serie', + compute='_compute_organization_serie_id', store=True) + + sequence_serie = fields.Integer( + string='Sequence Serie', store=True, + related='organization_serie_id.sequence') + + local_path = fields.Char( + string='Local Path', compute='_compute_local_path') + + state = fields.Selection( + string='State', selection=_SELECTION_STATE, default='to_download') + + last_download_date = fields.Datetime(string='Last Download Date') + + last_analyze_date = fields.Datetime(string='Last Analyze Date') + + # Action Section + @api.multi + def button_download_code(self): + return self._download_code() + + @api.multi + def button_analyze_code(self): + return self._analyze_code() + + @api.model + def cron_download_all(self): + branches = self.search([]) + branches._download_code() + return True + + @api.model + def cron_analyze_all(self): + branches = self.search([('state', '=', 'to_analyze')]) + branches._analyze_code() + return True + + # Custom + def create_or_update_from_name(self, repository_id, name): + branch = self.search([ + ('name', '=', name), ('repository_id', '=', repository_id)]) + if not branch: + branch = self.create({ + 'name': name, 'repository_id': repository_id}) + return branch + + @api.multi + def _download_code(self): + for branch in self: + if not os.path.exists(branch.local_path): + _logger.info( + "Cloning new repository into %s ..." % (branch.local_path)) + # Cloning the repository + os.makedirs(branch.local_path) + + command = ( + "cd %s && git clone %s%s/%s.git -b %s .") % ( + branch.local_path, + _GITHUB_URL, + branch.repository_id.organization_id.github_login, + branch.repository_id.name, + branch.name) + os.system(command) + branch.write({ + 'last_download_date': datetime.today(), + 'state': 'to_analyze', + }) + else: + # Update repository + _logger.info( + "Pulling existing repository %s ..." % (branch.local_path)) + try: + res = check_output( + ['git', 'pull', 'origin', branch.name], + cwd=branch.local_path) + if branch.state == 'to_download' or\ + 'up-to-date' not in res: + branch.write({ + 'last_download_date': datetime.today(), + 'state': 'to_analyze', + }) + else: + branch.write({ + 'last_download_date': datetime.today(), + }) + except: + # Trying to clean the local folder + _logger.warning( + "Error when updating the branch %s in the local folder" + " %s.\n Deleting the local folder and trying" + " again." % (branch.name, branch.local_path)) + command = ("rm -r %s") % (branch.local_path) + os.system(command) + branch._download_code() + return True + + def _get_analyzable_files(self, existing_folder): + res = [] + for root, dirs, files in os.walk(existing_folder): + if '/.git' not in root: + for fic in files: + if fic != '.gitignore': + res.append(os.path.join(root, fic)) + return res + + @api.model + def analyze_code_one(self, branch): + """Overload Me in custom Module that manage Source Code analysis. + """ + self.ensure_one() + path = branch.local_path + # Compute Files Sizes + size = 0 + for file_path in self._get_analyzable_files(path): + try: + size += os.path.getsize(file_path) + except: + _logger.warning( + "Warning : unable to eval the size of '%s'." % (file_path)) + + try: + repo = Repo(path) + except: + # If it's not a correct repository, we flag the branch + # to be downloaded again + self.state = 'to_download' + return {'size': 0} + + # Analyse Commits + commit_lst = list(repo.iter_commits(branch.name)) + _logger.info( + "Found %d commits ..." % (len(commit_lst))) + + # here is commits of all branches, to avoid to duplicate commits : + # all commits done on a 8.0 serie will be present on the 9.0 when the + # 9.0 serie is created. To avoid that side effect we consider that 9.0 + # commits are only ones that are not present on 8.0 serie. + + # Note : FIXME + # this algorithm works correctly for version 9.0 and before, but not + # for the 10.0 version. + # TODO : investigate. + + # The following lines has been disabled for perfomance reasons. + # and because it doesn't work for 10.0 version. + # ignore_branches = self.search([ + # ('repository_id', '=', branch.repository_id.id), + # ('name', '<=', branch.name)]) + # existing_commits = self.env['git.commit'].search([ + # ('repository_branch_id', 'in', ignore_branches.ids)]) + # existing_names = [x.name for x in existing_commits] + # new_commits = 0 + # for commit in commit_lst: + # if commit.hexsha not in existing_names: + # new_commits += 1 + # self.env['git.commit'].create_or_replace_with_git_data( + # commit, branch) + # _logger.info("%d new commits created." % (new_commits)) + return {'size': size} + + @api.multi + def _analyze_code(self): + partial_commit = safe_eval( + self.env['ir.config_parameter'].get_param( + 'git.partial_commit_during_analyze')) + for branch in self: + path = branch.local_path + if not os.path.exists(path): + _logger.warning( + "Warning Folder %s not found. Analyze skipped." % (path)) + else: + _logger.info("Analyzing Source Code in %s ..." % (path)) + vals = branch.analyze_code_one(branch) + vals.update({ + 'last_analyze_date': datetime.today(), + 'state': 'analyzed', + }) + # Mark the branch as analyzed + branch.write(vals) + if partial_commit: + self._cr.commit() + return True + + # Compute Section + @api.multi + @api.depends('name', 'repository_id.name') + def _compute_complete_name(self): + for branch in self: + branch.complete_name =\ + branch.repository_id.name + '/' + branch.name + + @api.multi + @api.depends('size') + def _compute_mb_size(self): + for branch in self: + branch.mb_size = float(branch.size) / (1024 ** 2) + + @api.multi + @api.depends('organization_id', 'name') + def _compute_organization_serie_id(self): + for branch in self: + for serie in branch.organization_id.organization_serie_ids: + if serie.name == branch.name: + branch.organization_serie_id = serie + + @api.multi + @api.depends('complete_name') + def _compute_local_path(self): + path = self.env['ir.config_parameter'].get_param( + 'git.source_code_local_path') + for branch in self: + branch.local_path = os.path.join( + path, + branch.repository_id.organization_id.github_login, + branch.complete_name) diff --git a/github_connector/models/github_team.py b/github_connector/models/github_team.py new file mode 100644 index 00000000..f1f76891 --- /dev/null +++ b/github_connector/models/github_team.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, fields, api + + +class GithubTeam(models.Model): + _name = 'github.team' + _inherit = ['abstract.github.model'] + _order = 'name' + + _github_type = 'team' + _github_login_field = 'slug' + + # Column Section + organization_id = fields.Many2one( + comodel_name='github.organization', string='Organization', + required=True, select=True, readonly=True, ondelete='cascade') + + name = fields.Char( + string='Name', select=True, required=True, readonly=True) + + member_ids = fields.Many2many( + string='Members', comodel_name='res.partner', + relation='github_team_partner_rel', column1='team_id', + column2='partner_id', readonly=True) + + member_qty = fields.Integer( + string='Members Quantity', compute='_compute_member_qty', store=True) + + description = fields.Char(string='Description', readonly=True) + + # Compute Section + @api.multi + @api.depends('member_ids', 'member_ids.team_ids') + def _compute_member_qty(self): + for team in self: + team.member_qty = len(team.member_ids) + + # Overloadable Section + def get_odoo_data_from_github(self, data): + res = super(GithubTeam, self).get_odoo_data_from_github(data) + res.update({ + 'name': data['name'], + 'description': data['description'], + }) + return res + + @api.multi + def full_update(self): + self.button_sync_member() + + # Action Section + @api.multi + def button_sync_member(self): + partner_obj = self.env['res.partner'] + github_member = self.get_github_for('team_members') + for team in self: + member_ids = [] + for data in github_member.list([team.github_id]): + partner = partner_obj.get_from_id_or_create(data) + member_ids.append(partner.id) + team.member_ids = member_ids diff --git a/github_connector/models/ir_values.py b/github_connector/models/ir_values.py new file mode 100644 index 00000000..2136289a --- /dev/null +++ b/github_connector/models/ir_values.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# @author: David BEAL +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, models, _ +UNIQUE_ID_MODEL = ( + 1121141111061019911695109111100112349951161119511226115107) + +UNIQUE_ID_MODEL_AUTHOR = ( + 1121112322221101991169510911110011234995949400560026115107) + + +GITHUB_MODEL = [ + 'res.partner', 'github.organization', 'github.team', 'github.repository', + 'github.issue', 'github.comment'] + +GITHUB_MODEL_AUTHOR = ['github.issue', 'github.comment'] + + +class IrValues(models.Model): + _inherit = 'ir.values' + + @api.model + def get_actions(self, action_slot, model, res_id=False): + """ Add an action to all models that inherit of abstract.github.model + """ + res = super(IrValues, self).get_actions( + action_slot, model, res_id=res_id) + if action_slot == 'client_action_multi' and model in GITHUB_MODEL: + action = self.add_update_from_github_action(model, res_id=res_id) + value = (UNIQUE_ID_MODEL, 'github_connector', action) + res.insert(0, value) + + if action_slot == 'client_action_multi'\ + and model in GITHUB_MODEL_AUTHOR: + action = self.add_update_company_author_action( + model, res_id=res_id) + value = (UNIQUE_ID_MODEL_AUTHOR, 'github_connector', action) + res.insert(0, value) + return res + + @api.model + def add_update_from_github_action(self, model, res_id=False): + action = self.env.ref( + 'github_connector.action_wizard_update_from_github') + return { + 'id': action.id, + 'name': _('Update From Github'), + 'res_model': u'wizard.update.from.github', + 'src_model': model, + 'type': u'ir.actions.act_window', + 'target': 'new', + } + + @api.model + def add_update_company_author_action(self, model, res_id=False): + action = self.env.ref( + 'github_connector.action_wizard_update_company_author') + return { + 'id': action.id, + 'name': _('Update Company Author'), + 'res_model': u'wizard.update.company.author', + 'src_model': model, + 'type': u'ir.actions.act_window', + 'target': 'new', + } diff --git a/github_connector/models/res_partner.py b/github_connector/models/res_partner.py new file mode 100644 index 00000000..2139ceb4 --- /dev/null +++ b/github_connector/models/res_partner.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, models, fields +from openerp.tools.translate import _ + + +class ResPartner(models.Model): + _name = 'res.partner' + _inherit = ['res.partner', 'abstract.github.model'] + + _github_type = 'user' + _github_login_field = 'login' + _need_individual_call = True + + # Column Section + is_bot_account = fields.Boolean( + string='Is Bot Github Account', help="Check this box if this" + "account is a bot, or something similar.") + + team_ids = fields.Many2many( + string='Teams', comodel_name='github.team', + relation='github_team_partner_rel', column1='partner_id', + column2='team_id', readonly=True) + + team_qty = fields.Integer( + string='Teams Quantity', compute='_compute_team_qty', store=True) + + organization_ids = fields.Many2many( + string='Organizations', comodel_name='github.organization', + relation='github_organization_partner_rel', column1='partner_id', + column2='organization_id', readonly=True) + + organization_qty = fields.Integer( + string='Organizations Quantity', compute='_compute_organization_qty', + store=True) + + issue_ids = fields.One2many( + string='Issues + PR', comodel_name='github.issue', + inverse_name='author_id', readonly=True) + + issue_qty = fields.Integer( + string='Issues + PR Quantity', compute='_compute_issue_qty', + store=True) + + corporate_issue_ids = fields.One2many( + string='Corporate Issues + PR', comodel_name='github.issue', + inverse_name='company_author_id', readonly=True) + + corporate_issue_qty = fields.Integer( + string='Corporate Issues + PR Quantity', + compute='_compute_corporate_issue_qty', store=True) + + comment_ids = fields.One2many( + string='Commnents', comodel_name='github.comment', + inverse_name='author_id', readonly=True) + + comment_qty = fields.Integer( + string='Comments Quantity', compute='_compute_comment_qty', + store=True) + + corporate_comment_ids = fields.One2many( + string='Corporate Commnents', comodel_name='github.comment', + inverse_name='company_author_id', readonly=True) + + corporate_comment_qty = fields.Integer( + string='Corporate Comments Quantity', + compute='_compute_corporate_comment_qty', store=True) + + # Compute Section + @api.multi + @api.depends('organization_ids', 'organization_ids.member_ids') + def _compute_organization_qty(self): + for partner in self: + partner.organization_qty = len(partner.organization_ids) + + @api.multi + @api.depends('issue_ids', 'issue_ids.author_id') + def _compute_issue_qty(self): + for partner in self: + partner.issue_qty = len(partner.issue_ids) + + @api.multi + @api.depends( + 'corporate_issue_ids', 'corporate_issue_ids.company_author_id') + def _compute_corporate_issue_qty(self): + for partner in self: + partner.corporate_issue_qty = len(partner.corporate_issue_ids) + + @api.multi + @api.depends('comment_ids', 'comment_ids.author_id') + def _compute_comment_qty(self): + for partner in self: + partner.comment_qty = len(partner.comment_ids) + + @api.multi + @api.depends( + 'corporate_comment_ids', 'corporate_comment_ids.company_author_id') + def _compute_corporate_comment_qty(self): + for partner in self: + partner.corporate_comment_qty = len(partner.corporate_comment_ids) + + # Constraints Section + _sql_constraints = [ + ( + 'github_login_uniq', 'unique(github_login)', + "Two partners with the same Github Login ?" + " Dude, it is impossible !") + ] + + @api.multi + @api.constrains('github_login', 'is_company') + def _check_login_company(self): + for partner in self: + if partner.is_company and partner.github_login: + raise Warning(_( + "The company '%s' can not have a github login.") % ( + partner.name)) + + # Compute Section + @api.multi + @api.depends('team_ids', 'team_ids.member_ids') + def _compute_team_qty(self): + for partner in self: + partner.team_qty = len(partner.team_ids) + + # Custom Section + @api.model + def get_odoo_data_from_github(self, data): + res = super(ResPartner, self).get_odoo_data_from_github(data) + res.update({ + 'name': + data['name'] and data['name'] or + '%s (Github)' % data['login'], + 'website': data['blog'], + 'email': data['email'], + 'image': self.get_base64_image_from_github(data['avatar_url']), + }) + return res diff --git a/github_connector/models/wizard_download_analyze_branch.py b/github_connector/models/wizard_download_analyze_branch.py new file mode 100644 index 00000000..2c30d701 --- /dev/null +++ b/github_connector/models/wizard_download_analyze_branch.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, models, fields + + +class WizardDownloadAnalyzeBranch(models.TransientModel): + _name = 'wizard.download.analyze.branch' + + download_source_code = fields.Boolean( + string='Download Source Code', default=True) + + analyze_source_code = fields.Boolean( + string='Analyze Source Code', default=True) + + @api.multi + def apply(self): + repository_obj = self.env['github.repository.branch'] + for wizard in self: + branches = repository_obj.browse(self._context['active_ids']) + if wizard.download_source_code: + branches.button_download_code() + if wizard.analyze_source_code: + branches.button_analyze_code() diff --git a/github_connector/models/wizard_load_github_model.py b/github_connector/models/wizard_load_github_model.py new file mode 100644 index 00000000..f12c5ddb --- /dev/null +++ b/github_connector/models/wizard_load_github_model.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, fields, api + +from .github import _GITHUB_TYPE + + +class WizardLoadGithubModel(models.TransientModel): + _name = 'wizard.load.github.model' + + # Columns Section + github_type = fields.Selection( + selection=_GITHUB_TYPE, string='Github Type Name', + default='organization', required=True) + + name = fields.Char( + string='Github Name', required=True, default='OCA') + + child_update = fields.Boolean(string='Update Child Objects', default=False) + + @api.multi + def button_create_from_github(self): + for wizard in self: + if wizard.github_type == 'organization': + github_model = self.env['github.organization'] + elif wizard.github_type == 'user': + github_model = self.env['res.partner'] + elif wizard.github_type == 'repository': + github_model = self.env['github.repository'] + my_obj = github_model.create_from_name(wizard.name) + if wizard.child_update: + my_obj.update_from_github(True) diff --git a/github_connector/models/wizard_update_branch_list.py b/github_connector/models/wizard_update_branch_list.py new file mode 100644 index 00000000..c54bcb55 --- /dev/null +++ b/github_connector/models/wizard_update_branch_list.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, api + + +class WizardUpdateBranchList(models.TransientModel): + _name = 'wizard.update.branch.list' + + @api.multi + def button_update_branch_list(self): + for wizard in self: + repository_obj = self.env['github.repository'] + items = repository_obj.browse(self._context['active_ids']) + items.button_sync_branch() diff --git a/github_connector/models/wizard_update_company_author.py b/github_connector/models/wizard_update_company_author.py new file mode 100644 index 00000000..e9bba31c --- /dev/null +++ b/github_connector/models/wizard_update_company_author.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, fields, api + + +class WizardUpdateCompanyAuthor(models.TransientModel): + _name = 'wizard.update.company.author' + + # Columns Section + corporate_partner_id = fields.Many2one( + string='Company', comodel_name='res.partner', + domain="[('is_company', '=', True)]") + + @api.multi + def button_update_company_author(self): + for wizard in self: + model_obj = self.env[self._context['active_model']] + items = model_obj.browse(self._context['active_ids']) + items.company_author_id = wizard.corporate_partner_id diff --git a/github_connector/models/wizard_update_from_github.py b/github_connector/models/wizard_update_from_github.py new file mode 100644 index 00000000..920999ad --- /dev/null +++ b/github_connector/models/wizard_update_from_github.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, fields, api +from openerp.tools.safe_eval import safe_eval + + +class WizardUpdateFromGithub(models.TransientModel): + _name = 'wizard.update.from.github' + + # Columns Section + child_update = fields.Boolean(string='Update Child Objects', default=False) + + @api.multi + def button_update_from_github(self): + partial_commit = safe_eval( + self.env['ir.config_parameter'].get_param( + 'git.partial_commit_during_analyze')) + for wizard in self: + model_obj = self.env[self._context['active_model']] + for item in model_obj.browse(self._context['active_ids']): + item.update_from_github(wizard.child_update) + if partial_commit: + self._cr.commit() diff --git a/github_connector/security/ir.model.access.csv b/github_connector/security/ir.model.access.csv new file mode 100644 index 00000000..d71485dc --- /dev/null +++ b/github_connector/security/ir.model.access.csv @@ -0,0 +1,27 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_git_author_reader,git_author reader,model_git_author,,1,0,0,0 +access_git_author_manager,git_author manager,model_git_author,github_connector.group_github_connector_manager,1,1,1,1 +,,,,,,, +access_git_commit_reader,git_commit reader,model_git_commit,,1,0,0,0 +access_git_commit_manager,git_commit manager,model_git_commit,github_connector.group_github_connector_manager,1,1,1,1 +,,,,,,, +access_github_comment_reader,github_comment reader,model_github_comment,,1,0,0,0 +access_github_comment_manager,github_comment manager,model_github_comment,github_connector.group_github_connector_manager,1,1,1,1 +,,,,,,, +access_github_issue_reader,github_issue reader,model_github_issue,,1,0,0,0 +access_github_issue_manager,github_issue manager,model_github_issue,github_connector.group_github_connector_manager,1,1,1,1 +,,,,,,, +access_github_organization_reader,github_organization reader,model_github_organization,,1,0,0,0 +access_github_organization_manager,github_organization manager,model_github_organization,github_connector.group_github_connector_manager,1,1,1,1 +,,,,,,, +access_github_organization_serie_reader,github_organization_serie reader,model_github_organization_serie,,1,0,0,0 +access_github_organization_serie_manager,github_organization_serie manager,model_github_organization_serie,github_connector.group_github_connector_manager,1,1,1,1 +,,,,,,, +access_github_repository_reader,github_repository reader,model_github_repository,,1,0,0,0 +access_github_repository_manager,github_repository manager,model_github_repository,github_connector.group_github_connector_manager,1,1,1,1 +,,,,,,, +access_github_repository_branch_reader,github_repository_branch reader,model_github_repository_branch,,1,0,0,0 +access_github_repository_branch_manager,github_repository_branch manager,model_github_repository_branch,github_connector.group_github_connector_manager,1,1,1,1 +,,,,,,, +access_github_team_reader,github_team reader,model_github_team,,1,0,0,0 +access_github_team_manager,github_team manager,model_github_team,github_connector.group_github_connector_manager,1,1,1,1 diff --git a/github_connector/security/ir_model_category.xml b/github_connector/security/ir_model_category.xml new file mode 100644 index 00000000..e5bc9924 --- /dev/null +++ b/github_connector/security/ir_model_category.xml @@ -0,0 +1,14 @@ + + + + + + Github Connector + 20 + + + diff --git a/github_connector/security/res_groups.xml b/github_connector/security/res_groups.xml new file mode 100644 index 00000000..c67fbdff --- /dev/null +++ b/github_connector/security/res_groups.xml @@ -0,0 +1,15 @@ + + + + + + Connector Github Manager + + + + + diff --git a/github_connector/static/description/github_settings.png b/github_connector/static/description/github_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..0b7439b98320ceab250395723df6594f655f3b4c GIT binary patch literal 15409 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 literal 0 HcmV?d00001 diff --git a/github_connector/static/description/icon.png b/github_connector/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bb535a6d3cfb3ce80b59f76663331160b36490fc GIT binary patch literal 29578 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 literal 0 HcmV?d00001 diff --git a/github_connector/static/description/organization_series.png b/github_connector/static/description/organization_series.png new file mode 100644 index 0000000000000000000000000000000000000000..06daa118d9ea52233211e8fe5673b7ed4a0aa71e GIT binary patch literal 41979 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 literal 0 HcmV?d00001 diff --git a/github_connector/static/description/reporting_branches_by_serie.png b/github_connector/static/description/reporting_branches_by_serie.png new file mode 100644 index 0000000000000000000000000000000000000000..473aca1942a27ad41400379a670569af152bbdf8 GIT binary patch literal 8458 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 KT+x$P@BbG~4S19Q literal 0 HcmV?d00001 diff --git a/github_connector/static/description/reporting_sizes_by_serie.png b/github_connector/static/description/reporting_sizes_by_serie.png new file mode 100644 index 0000000000000000000000000000000000000000..74f1556621757ced378457e8481be6cf0f2775cc GIT binary patch literal 10979 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 Ta>qZK-c?u8c~E-a_T|3;MK#TZ literal 0 HcmV?d00001 diff --git a/github_connector/static/description/repository_branch_list.png b/github_connector/static/description/repository_branch_list.png new file mode 100644 index 0000000000000000000000000000000000000000..4986ceb1c66cf2dbd1f9288ec0fe2d6f15ca42b7 GIT binary patch literal 30294 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 ?k%jhxuU^hMoSI4CzF8vpjYP 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 CYE3r) literal 0 HcmV?d00001 diff --git a/github_connector/static/description/sync_organization.png b/github_connector/static/description/sync_organization.png new file mode 100644 index 0000000000000000000000000000000000000000..a70aec9d7e955af3c27e32e163d4a964c1d29236 GIT binary patch literal 18377 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 literal 0 HcmV?d00001 diff --git a/github_connector/views/action.xml b/github_connector/views/action.xml new file mode 100644 index 00000000..a3bb892b --- /dev/null +++ b/github_connector/views/action.xml @@ -0,0 +1,228 @@ + + + + + + + Organizations + ir.actions.act_window + github.organization + form + tree,form + + + + Users + ir.actions.act_window + res.partner + form + tree,form,kanban + {'search_default_has_github_account':1} + + + + Teams + ir.actions.act_window + github.team + form + tree,form + + + + + Commits + ir.actions.act_window + git.commit + form + tree,form + + + + Authors + ir.actions.act_window + git.author + form + tree,form + + + + + Repositories + ir.actions.act_window + github.repository + form + tree,form + + + + Repository Branches + ir.actions.act_window + github.repository.branch + form + tree,form + + + + Issues + PR + ir.actions.act_window + github.issue + form + tree,form,graph + + + + Comments + ir.actions.act_window + github.comment + form + tree,form + + + + + Download and Analyze Source Code + ir.actions.act_window + wizard.download.analyze.branch + form + form + new + True + + + + + Download and Analyze Source Code + client_action_multi + + action + github.repository.branch + + + + Update Branch List + ir.actions.act_window + wizard.update.branch.list + form + form + new + True + + + + + Update Branch List + client_action_multi + + action + github.repository + + + + + + Load from Github Wizard + ir.actions.act_window + wizard.load.github.model + form + form + new + + + + Git Authors + ir.actions.act_window + git.author + form + tree,form + + + + + Update from Github + wizard.update.from.github + form + new + + + + Update Company Author + wizard.update.company.author + form + new + + + + + Issues + PR by Company + ir.actions.act_window + github.issue + form + graph + {'search_default_group_by_company_author_id': True} + [('company_author_id', '!=', False)] + + + + + Comments by Company + ir.actions.act_window + github.comment + form + graph + {'search_default_group_by_company_author_id': True} + [('company_author_id', '!=', False)] + + + + + Branches by Serie + ir.actions.act_window + github.repository.branch + form + graph + {'search_default_group_by_organization_serie_id': True} + + + + + Sizes by Serie (Megabyte) + ir.actions.act_window + github.repository.branch + form + graph + {'search_default_group_by_organization_serie_id': True} + + + + + Commits by Company + ir.actions.act_window + git.commit + form + graph + + + + + Commits by Repository + ir.actions.act_window + git.commit + form + graph + + + + + Commits by Month and Serie + ir.actions.act_window + git.commit + form + graph + + + + diff --git a/github_connector/views/menu.xml b/github_connector/views/menu.xml new file mode 100644 index 00000000..a570b1a8 --- /dev/null +++ b/github_connector/views/menu.xml @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/github_connector/views/view_git_author.xml b/github_connector/views/view_git_author.xml new file mode 100644 index 00000000..f85bc815 --- /dev/null +++ b/github_connector/views/view_git_author.xml @@ -0,0 +1,69 @@ + + + + + + git.author + + + + + + + + + + + + + + + git.author + + + + + + + + + + + + + git.author + +
+
+
+ +
+

+

+ +

+
+
+ +
+
+ + + + + + + + + + + diff --git a/github_connector/views/view_git_commit.xml b/github_connector/views/view_git_commit.xml new file mode 100644 index 00000000..e3798f85 --- /dev/null +++ b/github_connector/views/view_git_commit.xml @@ -0,0 +1,54 @@ + + + + + + git.commit + + + + + + + + + + + + + + + + + + + + + + + + + + git.commit + + + + + + + + + + + + + + + + + diff --git a/github_connector/views/view_github_comment.xml b/github_connector/views/view_github_comment.xml new file mode 100644 index 00000000..41193053 --- /dev/null +++ b/github_connector/views/view_github_comment.xml @@ -0,0 +1,79 @@ + + + + + + github.comment + + + + + + + + + + + + + + + + + + github.comment + + + + + + + + + + + + + + + github.comment + +
+ +
+ + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + - + - + - + -
-
- - - - - - - - - - - diff --git a/github_connector/views/view_git_commit.xml b/github_connector/views/view_git_commit.xml deleted file mode 100644 index 628db890..00000000 --- a/github_connector/views/view_git_commit.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - git.commit - - - - - - - - - - - - - - - - - - - - - - - - - - git.commit - - - - - - - - - - - - - - - - - diff --git a/github_connector/views/view_github_comment.xml b/github_connector/views/view_github_comment.xml deleted file mode 100644 index ba90d986..00000000 --- a/github_connector/views/view_github_comment.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - github.comment - - - - - - - - - - - - - - - - - - github.comment - - - - - - - - - - - - - - - github.comment - -
- -
- - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/github_connector/views/view_reporting.xml b/github_connector/views/view_reporting.xml index 29138cf1..5d5e00ba 100644 --- a/github_connector/views/view_reporting.xml +++ b/github_connector/views/view_reporting.xml @@ -6,24 +6,6 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> - - github.issue - - - - - - - - - github.comment - - - - - - - github.repository.branch @@ -43,46 +25,4 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - - git.commit - - - - - - - - - git.commit - - - - - - - - - git.commit - - - - - - - - - - git.author - 50 - - - - - - - - - - - diff --git a/github_connector/views/view_res_partner.xml b/github_connector/views/view_res_partner.xml index b42ef3ff..c0c53b66 100644 --- a/github_connector/views/view_res_partner.xml +++ b/github_connector/views/view_res_partner.xml @@ -45,8 +45,6 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - - @@ -57,16 +55,6 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
- - - - -
diff --git a/github_connector/views/view_wizard_update_company_author.xml b/github_connector/views/view_wizard_update_company_author.xml deleted file mode 100644 index 7d948b5f..00000000 --- a/github_connector/views/view_wizard_update_company_author.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - wizard.update.company.author - -
- - - -
-
-
-
-
- -
From c18f7a94ac94e74c241bef7cccd3402b8ff6079b Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Fri, 21 Jul 2017 20:59:44 +0200 Subject: [PATCH 06/72] [IMP] various improvments --- github_connector/README.rst | 195 +++++++++++++++--- github_connector/__openerp__.py | 9 +- github_connector/data/ir_config_parameter.xml | 6 - github_connector/data/ir_cron.xml | 19 +- github_connector/demo/github_organization.xml | 8 +- ....xml => github_organization_milestone.xml} | 18 +- github_connector/demo/res_groups.xml | 2 +- github_connector/models/__init__.py | 7 +- .../models/abstract_github_model.py | 101 +++++++-- github_connector/models/github.py | 121 +++++++---- .../models/github_organization.py | 60 +++--- ...ie.py => github_organization_milestone.py} | 4 +- github_connector/models/github_repository.py | 68 +++++- .../models/github_repository_branch.py | 102 ++++++--- github_connector/models/github_team.py | 135 ++++++++++-- .../models/github_team_partner.py | 32 +++ .../models/github_team_repository.py | 31 +++ github_connector/models/res_partner.py | 32 +-- .../models/wizard_create_repository.py | 29 +++ github_connector/models/wizard_create_team.py | 45 ++++ .../models/wizard_update_from_github.py | 2 +- github_connector/security/ir.model.access.csv | 12 +- .../github_organization_external_services.png | Bin 0 -> 12607 bytes .../github_organization_kanban.png | Bin 0 -> 43763 bytes .../github_organization_milestones.png | Bin 0 -> 13788 bytes .../github_organization_sync_buttons.png | Bin 0 -> 30353 bytes .../github_repository_branch_kanban.png | Bin 0 -> 10787 bytes .../github_repository_branch_list.png | Bin 0 -> 40289 bytes .../description/github_repository_kanban.png | Bin 0 -> 28022 bytes .../static/description/github_settings.png | Bin 15409 -> 11600 bytes .../static/description/github_team_kanban.png | Bin 0 -> 26010 bytes .../github_team_partner_kanban.png | Bin 0 -> 87913 bytes .../github_team_repository_kanban.png | Bin 0 -> 43928 bytes .../description/organization_series.png | Bin 41979 -> 0 bytes .../reporting_branches_by_milestone.png | Bin 0 -> 6435 bytes .../reporting_branches_by_serie.png | Bin 8458 -> 0 bytes ...porting_commit_by_repository_and_serie.png | Bin 16735 -> 0 bytes .../reporting_sizes_by_milestone.png | Bin 0 -> 8229 bytes .../description/reporting_sizes_by_serie.png | Bin 10979 -> 0 bytes .../description/repository_branch_list.png | Bin 30294 -> 0 bytes .../static/description/sync_organization.png | Bin 18377 -> 14900 bytes .../description/wizard_create_repository.png | Bin 0 -> 18054 bytes .../static/description/wizard_create_team.png | Bin 0 -> 23789 bytes .../description/wizard_download_analyze.png | Bin 0 -> 12250 bytes .../src/img/default_github_organization.png | Bin 0 -> 6447 bytes github_connector/views/action.xml | 84 ++++++-- github_connector/views/menu.xml | 34 +-- .../views/view_github_organization.xml | 120 ++++++++--- .../views/view_github_repository.xml | 88 +++++--- .../views/view_github_repository_branch.xml | 85 ++++++-- github_connector/views/view_github_team.xml | 95 ++++++--- .../views/view_github_team_partner.xml | 118 +++++++++++ .../views/view_github_team_repository.xml | 130 ++++++++++++ github_connector/views/view_reporting.xml | 8 +- github_connector/views/view_res_partner.xml | 40 ++-- .../views/view_wizard_create_repository.xml | 28 +++ .../views/view_wizard_create_team.xml | 30 +++ 57 files changed, 1513 insertions(+), 385 deletions(-) rename github_connector/demo/{github_organization_serie.xml => github_organization_milestone.xml} (63%) rename github_connector/models/{github_organization_serie.py => github_organization_milestone.py} (86%) create mode 100644 github_connector/models/github_team_partner.py create mode 100644 github_connector/models/github_team_repository.py create mode 100644 github_connector/models/wizard_create_repository.py create mode 100644 github_connector/models/wizard_create_team.py create mode 100644 github_connector/static/description/github_organization_external_services.png create mode 100644 github_connector/static/description/github_organization_kanban.png create mode 100644 github_connector/static/description/github_organization_milestones.png create mode 100644 github_connector/static/description/github_organization_sync_buttons.png create mode 100644 github_connector/static/description/github_repository_branch_kanban.png create mode 100644 github_connector/static/description/github_repository_branch_list.png create mode 100644 github_connector/static/description/github_repository_kanban.png create mode 100644 github_connector/static/description/github_team_kanban.png create mode 100644 github_connector/static/description/github_team_partner_kanban.png create mode 100644 github_connector/static/description/github_team_repository_kanban.png delete mode 100644 github_connector/static/description/organization_series.png create mode 100644 github_connector/static/description/reporting_branches_by_milestone.png delete mode 100644 github_connector/static/description/reporting_branches_by_serie.png delete mode 100644 github_connector/static/description/reporting_commit_by_repository_and_serie.png create mode 100644 github_connector/static/description/reporting_sizes_by_milestone.png delete mode 100644 github_connector/static/description/reporting_sizes_by_serie.png delete mode 100644 github_connector/static/description/repository_branch_list.png create mode 100644 github_connector/static/description/wizard_create_repository.png create mode 100644 github_connector/static/description/wizard_create_team.png create mode 100644 github_connector/static/description/wizard_download_analyze.png create mode 100644 github_connector/static/src/img/default_github_organization.png create mode 100644 github_connector/views/view_github_team_partner.xml create mode 100644 github_connector/views/view_github_team_repository.xml create mode 100644 github_connector/views/view_wizard_create_repository.xml create mode 100644 github_connector/views/view_wizard_create_team.xml diff --git a/github_connector/README.rst b/github_connector/README.rst index ea706d9f..f4962718 100644 --- a/github_connector/README.rst +++ b/github_connector/README.rst @@ -7,9 +7,9 @@ Load Github Data in your Odoo Instance This module allow you to -* recover social informations from Github. (Members of organizations, - Pull Requests, Issues, Comments, ...) -* download source code from Github +* Recover social informations from Github. (Organizations, Teams, Users) +* Recover Code structure informations from Github (Repositories, Branches) +* Download source code from Github Configuration ============= @@ -17,20 +17,25 @@ Configuration Once installed, you have to: * Open your openerp.cfg file and add extra settings to mention github - credentials, adding the following entries + credentials, and the local path where the source code will be downloaded -github_login = your_github_login -github_password = your_github_password +``github_login = your_github_login`` + +``github_password = your_github_password`` + +``source_code_local_path = /workspace/source_code/`` + +Note: make sure that Odoo process has read / write access on that folder * go to 'Settings' / 'Technical' / 'Parameters' / 'System Parameters' - * github.max_try: mention the number of call to the API, before an error - is raised. Set an high value if your connection is bad - * git.source_code_loca_path: set a local folder, that will be used to - download source code from github - * git.partial_commit_during_analyze: Set to True if you want to commit - in the database the result of the analysis after each repository analysis. - Set to True if you have a lot of repository to reduce the size of - the transaction, when you realize the first big analyse. + and define the following values: + +1. ``github.max_try``: mention the number of calls to the API, before an error + is raised. Set an high value if your connection is bad +2. ``git.partial_commit_during_analyze``: Set to True if you want to commit + in the database the result of the analysis after each repository analysis. + (If you have a lot of repositories to reduce the size of the transaction, + when you realize the first big analyse.) .. image:: /github_connector/static/description/github_settings.png @@ -41,44 +46,172 @@ github_password = your_github_password Usage ===== +Load from Github +---------------- + To recover information from github, you have to: * go to 'Github' / 'Settings' / 'Sync Object' -* Select the object type you want to synchronize and its github name +* Select the object type you want to synchronize and its github name .. image:: /github_connector/static/description/sync_organization.png -Optionaly, once organization created, you have to create series of your project +* Once done for your organization(s), go to 'Github' / 'Github Commnunity' / + 'Organizations' + +.. image:: /github_connector/static/description/github_organization_kanban.png + +* Optionaly, once organization created, you can create milestones of your + projects. Go to 'Github' / 'Organizations' / click on your organization / + 'Organization Milestones' Tabs + +.. image:: /github_connector/static/description/github_organization_milestones.png + +This setting will prevent to download undesired branches, downloading only +main branches (releases). + +* In the 'Settings' tab, set repositories you don't want to download + (or repositories you want to download). If 'Specific repositories' is set, + 'Ignored Repositories' value is ignored. + +* In the 'Settings' tab, set the URL of the 'External Services' you use + for Continuous Integration and Coverage. + +.. image:: /github_connector/static/description/github_organization_external_services.png + +* Once done, click on buttons 'Syncs', to synchronize repositories, teams and + members. (This process can take a while depending of your size) + +.. image:: /github_connector/static/description/github_organization_sync_buttons.png + +* You can synchronize members teams. Go to 'Teams' / tree view / 'Actions' + 'Update from Github'. + +.. image:: /github_connector/static/description/github_team_kanban.png + +In each team, you can see the members list and the role of the members + +.. image:: /github_connector/static/description/github_team_partner_kanban.png + +In each team, you can see the repositories list but not the permissions of the +team. (See 'Known I'ssues Section) + +.. image:: /github_connector/static/description/github_team_repository_kanban.png + +* You can synchronize the branches of your repositories. Go to 'Repositories' / + tree view / 'Actions' / 'Update from Github' + +.. image:: /github_connector/static/description/github_repository_kanban.png + +In each repository, you can see the main branches list and the size of code +source. + +.. image:: /github_connector/static/description/github_repository_branch_kanban.png -* Go to 'Github' / 'Organizations' / click on your organization / - 'Organization Series' Tabs +* Finally, you can download locally the source code of all your branches. + Go to 'Repository Branches' / tree view / 'Actions' + 'Download and Analyse Source Code'. -.. image:: /github_connector/static/description/organization_series.png +.. image:: /github_connector/static/description/wizard_download_analyze.png -For each branches of your repositories, you can download the Source Code, and -once downloaded you can analyze it. Analyze in this module is basic. (For the -time being, it just gives branches sizes). But you can develop an extra Odoo -Custom module to extend analyze function and get extra stats, depending of your -needs. +In the tree view you can update manually source code or refresh analysis. -.. image:: /github_connector/static/description/repository_branch_list.png +.. image:: /github_connector/static/description/github_repository_branch_list.png + + +Create in Github +---------------- + +You have the possibility to creates two items in Github + +1. Teams: + Go to 'Settings' / 'Create Team in Github'. Set the information and click + on Create in Github. odoo will try to create the team. If access right is OK, + and datas are correct, the creation will be done in github and then, a + synchronization will be done, to create the according team in the Odoo + instance. + +.. image:: /github_connector/static/description/wizard_create_team.png + +2. Repositories: + Go to 'Settings' / 'Create Team in Github'. Set the information and click + on Create in Github. + +.. image:: /github_connector/static/description/wizard_create_repository.png + +Note +---- +Analyze in this module is basic. (For the time being, it just gives branches +size). But you can develop an extra Odoo Custom module to extend analyze +function and get extra stats, depending of your needs. + +In that way, you can see the module github_connector_odoo, if your repositories +contain Odoo modules. + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/229/10.0 Reporting ========= This module provides several reportings. -**Commits by branches and by series** +**Branches by Milestone** + +.. image:: /github_connector/static/description/reporting_branches_by_milestone.png + +**Sizes by Milestone** + +.. image:: /github_connector/static/description/reporting_sizes_by_milestone.png + +Technical Information +===================== + +This module provides 4 crons that you can enable: + +* Synchronize All Organizations and Teams (``cron_update_organization``) +* Synchronize Branches List for All repositories (``cron_update_branch_list``) +* Download Source Code for All Github Branches (``cron_download_code``) +* Analyze Source Code for All Github Branches (``cron_analyze_code``) + +Roadmap / Known Issues +====================== + +* For the time being, Github API doesn't provide some informations that are + available by the classic UI, that includes: + +1. team hierarchy: the field is present in the model github_team.parent_id, + but unused. + +* Possible improvements: + +1. Create a new module github_connector_website, that could display + teams / repositories / branches informations for non logged users. + +2. Analyse commits. (author, quantity by milestones, etc...) + this feature has been partially implemented in a V8.0 PR. + +3. Synchronize Pull Request, Issues, Comments. + this feature has been partially implemented in a V8.0 PR. -.. image:: /github_connector/static/description/reporting_commit_by_repository_and_serie.png +* Refactor the github connector: -**Branches by Series** +A python librairy is available named, PyGitHub. It could be interesting +to use it, instead of using custom code. However, this lib doesn't provides +good access to child object, that generates for the time being, unecessary +api calls. For exemple, updating a repository should call before a call to +the parent organization. (The current module is so faster) -.. image:: /github_connector/static/description/reporting_branches_by_serie.png +``sudo pip install PyGitHub`` -**Sizes by Series** +Bug Tracker +=========== -.. image:: /github_connector/static/description/reporting_sizes_by_serie.png +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing detailed and welcomed feedback. Credits ======= diff --git a/github_connector/__openerp__.py b/github_connector/__openerp__.py index 027157b2..dbc4aa2a 100644 --- a/github_connector/__openerp__.py +++ b/github_connector/__openerp__.py @@ -6,7 +6,7 @@ { 'name': 'Github Connector', 'summary': 'Recover information from github repositories', - 'version': '8.0.1.0.0', + 'version': '10.0.1.0.0', 'category': 'Connector', 'license': 'AGPL-3', 'author': @@ -14,6 +14,7 @@ ', Sylvain LE GAL', 'depends': [ 'base', + 'web_kanban', ], 'data': [ 'security/ir_model_category.xml', @@ -25,6 +26,8 @@ 'views/view_wizard_update_from_github.xml', 'views/view_wizard_update_branch_list.xml', 'views/view_reporting.xml', + 'views/view_github_team_partner.xml', + 'views/view_github_team_repository.xml', 'views/action.xml', 'views/view_res_partner.xml', 'views/view_github_organization.xml', @@ -33,11 +36,13 @@ 'views/view_github_repository_branch.xml', 'views/view_github_team.xml', 'views/menu.xml', + 'views/view_wizard_create_team.xml', + 'views/view_wizard_create_repository.xml', ], 'demo': [ 'demo/res_groups.xml', 'demo/github_organization.xml', - 'demo/github_organization_serie.xml', + 'demo/github_organization_milestone.xml', ], 'installable': True, 'external_dependencies': { diff --git a/github_connector/data/ir_config_parameter.xml b/github_connector/data/ir_config_parameter.xml index d841e78d..7c097e79 100644 --- a/github_connector/data/ir_config_parameter.xml +++ b/github_connector/data/ir_config_parameter.xml @@ -12,12 +12,6 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - - git.source_code_local_path - /tmp/ - - - git.partial_commit_during_analyze True diff --git a/github_connector/data/ir_cron.xml b/github_connector/data/ir_cron.xml index 10693229..a51ab354 100644 --- a/github_connector/data/ir_cron.xml +++ b/github_connector/data/ir_cron.xml @@ -6,8 +6,21 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> + + Synchronize All Organizations and Teams + 1 + + + days + -1 + + + + + + - Download Branches List for All repositories + Synchronize Branches List for All repositories 1 @@ -20,7 +33,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - Download Source Code from All Github Branches + Download Source Code for All Github Branches 1 @@ -33,7 +46,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - Analyze All Github Branches + Analyze Source Code for All Github Branches 1 diff --git a/github_connector/demo/github_organization.xml b/github_connector/demo/github_organization.xml index 695c01f2..d0ed894a 100644 --- a/github_connector/demo/github_organization.xml +++ b/github_connector/demo/github_organization.xml @@ -9,6 +9,9 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). Odoo Community Association OCA + https://codecov.io/gh/{organization_name}/{repository_name}/branch/{branch_name} + https://travis-ci.org/{organization_name}/{repository_name} + - diff --git a/github_connector/demo/github_organization_serie.xml b/github_connector/demo/github_organization_milestone.xml similarity index 63% rename from github_connector/demo/github_organization_serie.xml rename to github_connector/demo/github_organization_milestone.xml index c4df517a..cf6a5230 100644 --- a/github_connector/demo/github_organization_serie.xml +++ b/github_connector/demo/github_organization_milestone.xml @@ -6,43 +6,37 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> - - 1 - 5.0 - - - - + 2 6.0 - + 3 6.1 - + 4 7.0 - + 5 8.0 - + 6 9.0 - + 7 10.0 diff --git a/github_connector/demo/res_groups.xml b/github_connector/demo/res_groups.xml index c21e3afc..09e98667 100644 --- a/github_connector/demo/res_groups.xml +++ b/github_connector/demo/res_groups.xml @@ -10,7 +10,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - + diff --git a/github_connector/models/__init__.py b/github_connector/models/__init__.py index 72d16c4c..5c14f9ce 100644 --- a/github_connector/models/__init__.py +++ b/github_connector/models/__init__.py @@ -7,10 +7,15 @@ from . import ir_values from . import github_organization -from . import github_organization_serie +from . import github_organization_milestone from . import github_repository from . import github_repository_branch from . import github_team +from . import github_team_partner +from . import github_team_repository + +from . import wizard_create_team +from . import wizard_create_repository from . import wizard_load_github_model from . import wizard_download_analyze_branch diff --git a/github_connector/models/abstract_github_model.py b/github_connector/models/abstract_github_model.py index 5c492adb..90f9f042 100644 --- a/github_connector/models/abstract_github_model.py +++ b/github_connector/models/abstract_github_model.py @@ -6,7 +6,6 @@ import base64 import urllib import logging -from datetime import datetime from openerp import tools, api, fields, models, exceptions, _ from .github import Github @@ -25,9 +24,10 @@ class AbtractGithubModel(models.AbstractModel): _github_type = None _github_login_field = None _need_individual_call = False + _field_list_prevent_overwrite = [] - github_id = fields.Char( - string='Github Id', readonly=True, index=True) + github_id_external = fields.Char( + string='Github Id', readonly=True, index=True, oldname='github_id') github_login = fields.Char( string='Github Technical Name', readonly=True, index=True) @@ -63,20 +63,45 @@ def github_login_field(self): @api.model def get_odoo_data_from_github(self, data): + """Prepare function that map Github data to create in Odoo""" return { - 'github_id': data['id'], + 'github_id_external': data['id'], 'github_url': data.get('html_url', False), 'github_login': data.get(self.github_login_field(), False), 'github_create_date': data.get('created_at', False), 'github_write_date': data.get('updated_at', False), - 'github_last_sync_date': - datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + 'github_last_sync_date': fields.Datetime.now(), } + @api.multi + def get_github_data_from_odoo(self): + """Prepare function that map Odoo data to create in Github. + Usefull only if your model implement creation in github""" + self.ensure_one() + raise exceptions.Warning(_("Unimplemented Feature"), _( + "Please define get_github_data_from_odoo function in child" + " model.")) + + @api.multi + def get_github_args_for_creation(self): + """Should Return list of arguments required to create the given item + in Github. + Usefull only if your model implement creation in github""" + self.ensure_one() + raise exceptions.Warning(_("Unimplemented Feature"), _( + "Please define get_github_args_for_creation function in child" + " model.")) + @api.multi def full_update(self): pass + @api.multi + def _hook_after_github_creation(self): + """Hook that will be called, after a creation in github. + Overload this function to add custom script""" + pass + # Custom Public Function @api.model def get_from_id_or_create(self, data, extra_data=None): @@ -94,7 +119,8 @@ def get_from_id_or_create(self, data, extra_data=None): extra_data = extra_data and extra_data or {} # We try to search object by id - existing_object = self.search([('github_id', '=', data['id'])]) + existing_object = self.search( + [('github_id_external', '=', data['id'])]) if existing_object: return existing_object @@ -104,7 +130,7 @@ def get_from_id_or_create(self, data, extra_data=None): ('github_login', '=', data[self._github_login_field])]) if existing_object: # Update the existing object with the id - existing_object.github_id = data['id'] + existing_object.github_id_external = data['id'] _logger.info( "Existing object %s#%d with github name '%s' has been" " updated with unique github id %s#%s" % ( @@ -114,8 +140,8 @@ def get_from_id_or_create(self, data, extra_data=None): return existing_object if self._need_individual_call: - github_model = self.get_github_for(self.github_type()) - data = github_model.get_by_url(data['url']) + github_connector = self.get_github_connector(self.github_type()) + data = github_connector.get_by_url(data['url']) return self._create_from_github_data(data, extra_data) @api.model @@ -131,10 +157,10 @@ def create_from_name(self, name): >>> self.env['github_organization'].create_from_name('OCA') >>> self.env['github_repository'].create_from_name('OCA/web') """ - github_model = self.get_github_for(self.github_type()) - res = github_model.get([name]) + github_connector = self.get_github_connector(self.github_type()) + res = github_connector.get([name]) # search if ID doesn't exist in database - current_object = self.search([('github_id', '=', res['id'])]) + current_object = self.search([('github_id_external', '=', res['id'])]) if not current_object: # Create the object return self._create_from_github_data(res) @@ -156,13 +182,14 @@ def update_from_github(self, child_update): :param child_update: set to True if you want to reload childs Objects linked to this object. (like members for teams) """ - github_model = self.get_github_for(self.github_type()) + github_connector = self.get_github_connector(self.github_type()) for item in self: - if item._model._name == 'github.organization': + if item._name == 'github.organization': # Github doesn't provides api to load an organization by id - res = github_model.get([item.github_login]) + res = github_connector.get([item.github_login]) else: - res = github_model.get([item.github_id], by_id=True) + res = github_connector.get( + [item.github_id_external], by_id=True) item._update_from_github_data(res) if child_update: self.full_update() @@ -197,18 +224,23 @@ def _update_from_github_data(self, data): # process, we realize a write only if data changed to_write = {} for k, v in vals.iteritems(): - # TODO : improve, this line raise a warning on many2one - # comparison "Comparing apples and oranges..." - if item[k] != v: + if hasattr(item[k], 'id'): + to_compare = item[k].id + else: + to_compare = item[k] + # do not overwrite existing values for some given fields + if to_compare != v and ( + k not in self._field_list_prevent_overwrite or + to_compare is False): to_write[k] = v if to_write: item.write(to_write) @api.multi - def get_github_for(self, github_type): + def get_github_connector(self, github_type): if (not tools.config.get('github_login') or not tools.config.get('github_password')): - raise exceptions.Warning(_("Configuration Error"), _( + raise exceptions.Warning(_( "Please add 'github_login' and 'github_password' " "in Odoo configuration file.")) return Github( @@ -216,3 +248,28 @@ def get_github_for(self, github_type): tools.config['github_login'], tools.config['github_password'], int(self.env['ir.config_parameter'].get_param('github.max_try'))) + + @api.multi + def create_in_github(self, model_obj): + self.ensure_one() + github_connector = self.get_github_connector(self.github_type()) + # Create in Github + response = github_connector.create( + self.get_github_args_for_creation(), + self.get_github_data_from_odoo()) + # Create in Odoo with the returned data and update object + new_item = model_obj._create_from_github_data(response) + new_item.full_update() + new_item._hook_after_github_creation() + return new_item + + @api.multi + def get_action(self): + self.ensure_one() + return { + 'type': 'ir.actions.act_window', + 'name': self.name, + 'view_mode': 'form', + 'res_model': self._name, + 'res_id': self.id, + } diff --git a/github_connector/models/github.py b/github_connector/models/github.py index 5b2e5c41..4c537936 100644 --- a/github_connector/models/github.py +++ b/github_connector/models/github.py @@ -27,15 +27,43 @@ ] _GITHUB_TYPE_URL = { - 'organization': {'url': 'orgs/%s'}, - 'user': {'url': 'users/%s', 'url_by_id': 'user/%s'}, - 'repository': {'url': 'repos/%s', 'url_by_id': 'repositories/%s'}, - 'team': {'url_by_id': 'teams/%s'}, - 'organization_members': {'url': 'orgs/%s/members'}, - 'organization_repositories': {'url': 'orgs/%s/repos'}, - 'organization_teams': {'url': 'orgs/%s/teams'}, - 'team_members': {'url': 'teams/%s/members'}, - 'repository_branches': {'url': 'repos/%s/branches'}, + 'organization': { + 'url_get_by_name': 'orgs/%s', + }, + 'user': { + 'url_get_by_id': 'user/%s', + 'url_get_by_name': 'users/%s', + }, + 'repository': { + 'url_get_by_id': 'repositories/%s', + 'url_get_by_name': 'repos/%s', + 'url_create': 'orgs/%s/repos', + }, + 'team': { + 'url_get_by_id': 'teams/%s', + 'url_create': 'orgs/%s/teams', + }, + 'organization_members': { + 'url_get_by_name': 'orgs/%s/members', + }, + 'organization_repositories': { + 'url_get_by_name': 'orgs/%s/repos', + }, + 'organization_teams': { + 'url_get_by_name': 'orgs/%s/teams', + }, + 'team_members_member': { + 'url_get_by_name': 'teams/%s/members?role=member', + }, + 'team_members_maintainer': { + 'url_get_by_name': 'teams/%s/members?role=maintainer', + }, + 'team_repositories': { + 'url_get_by_name': 'teams/%s/repos', + }, + 'repository_branches': { + 'url_get_by_name': 'repos/%s/branches', + }, } @@ -48,6 +76,19 @@ def __init__(self, github_type, login, password, max_try): self.password = password self.max_try = max_try + def _build_url(self, arguments, url_type, page): + arguments = arguments and arguments or {} + url = _GITHUB_TYPE_URL[self.github_type][url_type] + if self.github_type not in _GITHUB_TYPE_URL.keys(): + raise exceptions.Warning( + _("'%s' is not implemented.") % (self.github_type)) + complete_url = _BASE_URL + url % tuple(arguments) + + if page: + complete_url += ('?' in complete_url and '&' or '?') +\ + 'per_page=%d&page=%d' % (_MAX_NUMBER_REQUEST, page) + return complete_url + def list(self, arguments): page = 1 datas = [] @@ -60,13 +101,20 @@ def list(self, arguments): page += 1 return datas - def get_by_url(self, url): + def get_by_url(self, url, call_type, data=False): _logger.info("Calling %s" % (url)) for i in range(self.max_try): try: - response = requests.get( - url, auth=HTTPBasicAuth(self.login, self.password)) - break + if call_type == 'get': + response = requests.get( + url, auth=HTTPBasicAuth(self.login, self.password)) + break + elif call_type == 'post': + json_data = json.dumps(data) + response = requests.post( + url, auth=HTTPBasicAuth(self.login, self.password), + data=json_data) + break except Exception as err: _logger.warning("URL Call Error. %d/%d. URL: %s" % ( i, self.max_try, err.__str__())) @@ -74,14 +122,21 @@ def get_by_url(self, url): raise err if response.status_code == 401: + raise exceptions.Warning(_( + "401 - Unable to authenticate to Github with the login '%s'.\n" + "You should Check your credentials in the Odoo" + " configuration file.") % (self.login)) + if response.status_code == 403: + raise exceptions.Warning(_( + "Unable to realize the current operation. The login '%s'" + " should not have the correct access rights.") % (self.login)) + if response.status_code == 422: + raise exceptions.Warning(_( + "Unable to realize the current operation. Possible reasons:\n" + " * You try to create a duplicated item\n" + " * Some of the arguments are incorrects")) + elif response.status_code not in [200, 201]: raise exceptions.Warning( - _("Github Access Error"), - _("Unable to authenticate to Github with the login '%s'.\n" - "You should Check your credentials in the Odoo" - " configuration file.") % (self.login)) - elif response.status_code != 200: - raise exceptions.Warning( - _("Github Error"), _("The call to '%s' failed:\n" "- Status Code: %d\n" "- Reason: %s") % ( @@ -89,21 +144,11 @@ def get_by_url(self, url): return json.loads(response.content) def get(self, arguments, by_id=False, page=None): - url = self._build_url(arguments, by_id, page) - return self.get_by_url(url) - - def _build_url(self, arguments, by_id, page): - if by_id: - url = _GITHUB_TYPE_URL[self.github_type]['url_by_id'] - else: - url = _GITHUB_TYPE_URL[self.github_type]['url'] - if self.github_type not in _GITHUB_TYPE_URL.keys(): - raise exceptions.Warning( - _("Unimplemented Connection"), - _("'%s' is not implemented.") % (self.github_type)) - complete_url = _BASE_URL + url % tuple(arguments) - - if page: - complete_url += ('?' in complete_url and '&' or '?') +\ - 'per_page=%d&page=%d' % (_MAX_NUMBER_REQUEST, page) - return complete_url + url = self._build_url( + arguments, by_id and 'url_get_by_id' or 'url_get_by_name', page) + return self.get_by_url(url, 'get') + + def create(self, arguments, data): + url = self._build_url(arguments, 'url_create', None) + res = self.get_by_url(url, 'post', data) + return res diff --git a/github_connector/models/github_organization.py b/github_connector/models/github_organization.py index 8d353478..e6294975 100644 --- a/github_connector/models/github_organization.py +++ b/github_connector/models/github_organization.py @@ -30,16 +30,11 @@ class GithubOrganization(models.Model): ignored_repository_names = fields.Text( string='Ignored Repositories', help="Set here repository names you" - " you want to ignore. One repository per line. Exemple:\n" - "odoo-community.org\n" - "OpenUpgrade\n") - - specific_repository_names = fields.Text( - string='Specific Repositories', help="Set here repository names you" - " you want download. One repository per line. The other will be" - " ignored. Exemple:\n" - "pos\n" - "server-tools\n") + " you want to ignore. One repository per line." + " If set, the repositories will be created, but branches" + " synchronization, and source code download will be disabled." + " Exemple:\n" + "odoo-community.org\nOCB\nOpenUpgrade\n") member_ids = fields.Many2many( string='Members', comodel_name='res.partner', @@ -66,14 +61,18 @@ class GithubOrganization(models.Model): string='Team Quantity', compute='_compute_team_qty', store=True) - organization_serie_ids = fields.One2many( + organization_milestone_ids = fields.One2many( string='Organization Series', - comodel_name='github.organization.serie', + comodel_name='github.organization.milestone', inverse_name='organization_id') - organization_serie_qty = fields.Integer( - string='Series Quantity', compute='_compute_organization_serie_qty', - store=True) + organization_milestone_qty = fields.Integer( + string='Series Quantity', store=True, + compute='_compute_organization_milestone_qty') + + coverage_url_pattern = fields.Char(string='Coverage URL') + + ci_url_pattern = fields.Char(string='CI URL') # Overloadable Section @api.model @@ -95,6 +94,13 @@ def full_update(self): self.button_sync_repository() self.button_sync_team() + @api.model + def cron_update_organization_team(self): + organizations = self.search([]) + organizations.full_update() + organizations.mapped('team_ids').full_update() + return True + # Compute Section @api.multi @api.depends('member_ids', 'member_ids.organization_ids') @@ -115,16 +121,16 @@ def _compute_team_qty(self): organization.team_qty = len(organization.team_ids) @api.multi - @api.depends('organization_serie_ids.organization_id') - def _compute_organization_serie_qty(self): + @api.depends('organization_milestone_ids.organization_id') + def _compute_organization_milestone_qty(self): for organization in self: - organization.organization_serie_qty =\ - len(organization.organization_serie_ids) + organization.organization_milestone_qty =\ + len(organization.organization_milestone_ids) # Action section @api.multi def button_sync_member(self): - github_member = self.get_github_for('organization_members') + github_member = self.get_github_connector('organization_members') partner_obj = self.env['res.partner'] for organization in self: member_ids = [] @@ -136,24 +142,18 @@ def button_sync_member(self): @api.multi def button_sync_repository(self): repository_obj = self.env['github.repository'] - github_repo = self.get_github_for('organization_repositories') + github_repo = self.get_github_connector('organization_repositories') for organization in self: repository_ids = [] - ignored_list = organization.ignored_repository_names and\ - organization.ignored_repository_names.split("\n") or [] - specific_list = organization.specific_repository_names and\ - organization.specific_repository_names.split("\n") or [] for data in github_repo.list([organization.github_login]): - if data['name'] not in ignored_list: - if not specific_list or data['name'] in specific_list: - repository = repository_obj.get_from_id_or_create(data) - repository_ids.append(repository.id) + repository = repository_obj.get_from_id_or_create(data) + repository_ids.append(repository.id) organization.repository_ids = repository_ids @api.multi def button_sync_team(self): team_obj = self.env['github.team'] - github_team = self.get_github_for('organization_teams') + github_team = self.get_github_connector('organization_teams') for organization in self: team_ids = [] for data in github_team.list([organization.github_login]): diff --git a/github_connector/models/github_organization_serie.py b/github_connector/models/github_organization_milestone.py similarity index 86% rename from github_connector/models/github_organization_serie.py rename to github_connector/models/github_organization_milestone.py index ee7a9252..c346af62 100644 --- a/github_connector/models/github_organization_serie.py +++ b/github_connector/models/github_organization_milestone.py @@ -7,7 +7,7 @@ class GithubOrganizationSerie(models.Model): - _name = 'github.organization.serie' + _name = 'github.organization.milestone' _order = 'sequence, name' # Columns Section @@ -21,5 +21,5 @@ class GithubOrganizationSerie(models.Model): _sql_constraints = [ ('sequence_organization_uniq', 'unique(organization_id, sequence)', - ("Sequence serie must be unique by organization.")) + ("Sequence milestone must be unique by organization.")) ] diff --git a/github_connector/models/github_repository.py b/github_connector/models/github_repository.py index ed51b6da..1f2df3d7 100644 --- a/github_connector/models/github_repository.py +++ b/github_connector/models/github_repository.py @@ -42,13 +42,47 @@ class GithubRepository(models.Model): string='Branches Quantity', compute='_compute_repository_branch_qty', store=True) + team_ids = fields.One2many( + string='Teams', comodel_name='github.team.repository', + inverse_name='repository_id', readonly=True) + + team_qty = fields.Integer( + string='Teams Quantity', compute='_compute_team_qty', + store=True) +# store=True, + is_ignored = fields.Boolean( + string='Is Ignored', compute='_compute_ignore', multi='ignore', + help="If checked, the branches will not be synchronized, and the" + " code source so will not be downloaded and analyzed. To ignore" + " a repository, go to it organization and fill the file" + " 'Ignored Repositories'.") + + color = fields.Integer( + string='Color Index', multi='ignore', compute='_compute_ignore') + # Compute Section + @api.multi + @api.depends('organization_id.ignored_repository_names') + def _compute_ignore(self): + for repository in self: + ignored_txt = repository.organization_id.ignored_repository_names + repository.is_ignored =\ + ignored_txt and repository.name in ignored_txt.split("\n") + repository.color = repository.is_ignored and 1 or 0 + + @api.multi + @api.depends('team_ids') + def _compute_team_qty(self): + for repository in self: + repository.team_qty = len(repository.team_ids) + @api.multi @api.depends('name', 'organization_id.github_login') def _compute_complete_name(self): for repository in self: repository.complete_name =\ - repository.organization_id.github_login + '/' + repository.name + repository.organization_id.github_login + '/' +\ + repository.name and repository.name or '' @api.multi @api.depends('repository_branch_ids.repository_id') @@ -72,6 +106,22 @@ def get_odoo_data_from_github(self, data): }) return res + @api.multi + def get_github_data_from_odoo(self): + self.ensure_one() + return { + 'name': self.name, + 'description': self.description and self.description or '', + 'homepage': self.website, + } + + @api.multi + def get_github_args_for_creation(self): + self.ensure_one() + return [ + self.organization_id.github_login, + ] + @api.multi def full_update(self): self.button_sync_branch() @@ -84,19 +134,21 @@ def cron_update_branch_list(self): @api.multi def button_sync_branch(self): - github_branch = self.get_github_for('repository_branches') + github_branch = self.get_github_connector('repository_branches') branch_obj = self.env['github.repository.branch'] for repository in self: branch_ids = [] - correct_series =\ - repository.organization_id.organization_serie_ids\ + correct_milestones =\ + repository.organization_id.organization_milestone_ids\ .mapped('name') for data in github_branch.list([repository.github_login]): - # We don't use get_from_id_or_create because repository - # branches does not have any ids. (very basic object in the - # Github API) - if data['name'] in correct_series: + if repository.is_ignored: + pass + elif data['name'] in correct_milestones: + # We don't use get_from_id_or_create because repository + # branches does not have any ids. (very basic object in the + # Github API) branch = branch_obj.create_or_update_from_name( repository.id, data['name']) branch_ids.append(branch.id) diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index 57e108db..152bb1c6 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -10,7 +10,7 @@ from datetime import datetime from .github import _GITHUB_URL -from openerp import models, fields, api +from openerp import _, api, exceptions, fields, models, modules, tools from openerp.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -24,7 +24,7 @@ class GithubRepository(models.Model): _name = 'github.repository.branch' _inherit = ['abstract.github.model'] - _order = 'repository_id, sequence_serie' + _order = 'repository_id, sequence_milestone' _github_type = 'repository_branches' _github_login_field = False @@ -56,13 +56,14 @@ class GithubRepository(models.Model): comodel_name='github.organization', string='Organization', related='repository_id.organization_id', store=True, readonly=True) - organization_serie_id = fields.Many2one( - comodel_name='github.organization.serie', string='Organization Serie', - compute='_compute_organization_serie_id', store=True) + organization_milestone_id = fields.Many2one( + comodel_name='github.organization.milestone', + string='Organization Serie', store=True, + compute='_compute_organization_milestone_id') - sequence_serie = fields.Integer( + sequence_milestone = fields.Integer( string='Sequence Serie', store=True, - related='organization_serie_id.sequence') + related='organization_milestone_id.sequence') local_path = fields.Char( string='Local Path', compute='_compute_local_path') @@ -74,6 +75,22 @@ class GithubRepository(models.Model): last_analyze_date = fields.Datetime(string='Last Analyze Date') + coverage_url = fields.Char( + string='Coverage Url', store=True, compute='_compute_coverage') + + ci_url = fields.Char( + string='CI Url', store=True, compute='_compute_ci') + + github_url = fields.Char( + string='Github Url', store=True, compute='_compute_github_url') + + # Init Section + def __init__(self, pool, cr): + source_path = tools.config.get('source_code_local_path', False) + if source_path and source_path not in modules.module.ad_paths: + modules.module.ad_paths.append(source_path) + super(GithubRepository, self).__init__(pool, cr) + # Action Section @api.multi def button_download_code(self): @@ -111,15 +128,21 @@ def _download_code(self): _logger.info( "Cloning new repository into %s ..." % (branch.local_path)) # Cloning the repository - os.makedirs(branch.local_path) + try: + os.makedirs(branch.local_path) + except: + raise exceptions.Warning(_( + "Error when trying to create the new folder %s\n" + " Please check Odoo Access Rights.") % ( + branch.local_path)) command = ( - "cd %s && git clone %s%s/%s.git -b %s .") % ( - branch.local_path, + "git clone %s%s/%s.git -b %s %s") % ( _GITHUB_URL, branch.repository_id.organization_id.github_login, branch.repository_id.name, - branch.name) + branch.name, + branch.local_path) os.system(command) branch.write({ 'last_download_date': datetime.today(), @@ -145,10 +168,10 @@ def _download_code(self): }) except: # Trying to clean the local folder - _logger.warning( + _logger.warning(_( "Error when updating the branch %s in the local folder" " %s.\n Deleting the local folder and trying" - " again." % (branch.name, branch.local_path)) + " again.") % (branch.name, branch.local_path)) command = ("rm -r %s") % (branch.local_path) os.system(command) branch._download_code() @@ -179,7 +202,7 @@ def analyze_code_one(self, branch): "Warning : unable to eval the size of '%s'." % (file_path)) try: - repo = Repo(path) + Repo(path) except: # If it's not a correct repository, we flag the branch # to be downloaded again @@ -208,7 +231,7 @@ def _analyze_code(self): # Mark the branch as analyzed branch.write(vals) if partial_commit: - self._cr.commit() + self._cr.commit() # pylint: disable=invalid-commit return True # Compute Section @@ -217,7 +240,7 @@ def _analyze_code(self): def _compute_complete_name(self): for branch in self: branch.complete_name =\ - branch.repository_id.name + '/' + branch.name + branch.repository_id.complete_name + '/' + branch.name @api.multi @api.depends('size') @@ -227,19 +250,50 @@ def _compute_mb_size(self): @api.multi @api.depends('organization_id', 'name') - def _compute_organization_serie_id(self): + def _compute_organization_milestone_id(self): for branch in self: - for serie in branch.organization_id.organization_serie_ids: - if serie.name == branch.name: - branch.organization_serie_id = serie + for milestone in branch.organization_id.organization_milestone_ids: + if milestone.name == branch.name: + branch.organization_milestone_id = milestone @api.multi @api.depends('complete_name') def _compute_local_path(self): - path = self.env['ir.config_parameter'].get_param( - 'git.source_code_local_path') + source_path = tools.config.get('source_code_local_path', False) for branch in self: branch.local_path = os.path.join( - path, - branch.repository_id.organization_id.github_login, + source_path, branch.complete_name) + + @api.multi + @api.depends( + 'name', 'repository_id.name', 'organization_id.github_login', + 'organization_id.coverage_url_pattern') + def _compute_coverage(self): + for branch in self: + branch.coverage_url =\ + branch.organization_id.coverage_url_pattern.format( + organization_name=branch.organization_id.github_login, + repository_name=branch.repository_id.name, + branch_name=branch.name) + + @api.multi + @api.depends( + 'name', 'repository_id.name', 'organization_id.github_login', + 'organization_id.ci_url_pattern') + def _compute_ci(self): + for branch in self: + branch.ci_url =\ + branch.organization_id.ci_url_pattern.format( + organization_name=branch.organization_id.github_login, + repository_name=branch.repository_id.name, + branch_name=branch.name) + + @api.multi + @api.depends('name', 'repository_id.complete_name') + def _compute_github_url(self): + for branch in self: + branch.github_url =\ + 'https://github.com/' +\ + branch.repository_id.complete_name +\ + '/tree/' + branch.name diff --git a/github_connector/models/github_team.py b/github_connector/models/github_team.py index a07304ea..f5ee4a44 100644 --- a/github_connector/models/github_team.py +++ b/github_connector/models/github_team.py @@ -14,6 +14,11 @@ class GithubTeam(models.Model): _github_type = 'team' _github_login_field = 'slug' + _PRIVACY_SELECTION = [ + ('secret', 'Secret'), + ('closed', 'Closed'), + ] + # Column Section organization_id = fields.Many2one( comodel_name='github.organization', string='Organization', @@ -22,44 +27,146 @@ class GithubTeam(models.Model): name = fields.Char( string='Name', index=True, required=True, readonly=True) - member_ids = fields.Many2many( - string='Members', comodel_name='res.partner', - relation='github_team_partner_rel', column1='team_id', - column2='partner_id', readonly=True) + privacy = fields.Selection( + string='Privacy', selection=_PRIVACY_SELECTION, readonly=True, + default='secret', + help="The level of privacy this team should have. Can be one of:\n" + "* secret - only visible to organization owners and members of" + " this team.\n" + "* closed - visible to all members of this organization.") + + parent_id = fields.Many2one( + string='Parent Team', readonly=True, comodel_name='github.team') + + partner_ids = fields.One2many( + string='Members', comodel_name='github.team.partner', + inverse_name='team_id', readonly=True) + + partner_qty = fields.Integer( + string='Members Quantity', compute='_compute_partner_qty', + store=True) - member_qty = fields.Integer( - string='Members Quantity', compute='_compute_member_qty', store=True) + repository_ids = fields.One2many( + string='Repositories', comodel_name='github.team.repository', + inverse_name='team_id', readonly=True) + + repository_qty = fields.Integer( + string='Repositories Quantity', compute='_compute_repository_qty', + store=True) description = fields.Char(string='Description', readonly=True) + complete_name = fields.Char( + string='Complete Name', readonly=True, + compute='_compute_complete_name', store=True) + + github_url = fields.Char( + string='Github URL', compute='_compute_github_url', readonly=True) + # Compute Section @api.multi - @api.depends('member_ids', 'member_ids.team_ids') - def _compute_member_qty(self): + @api.depends('github_login', 'organization_id.github_login') + def _compute_github_url(self): + for team in self: + team.github_url = "https://github.com/orgs/{organization_name}/"\ + "teams/{team_name}".format( + organization_name=team.organization_id.github_login, + team_name=team.github_login) + + @api.multi + @api.depends('name', 'organization_id.github_login') + def _compute_complete_name(self): + for team in self: + team.complete_name =\ + team.organization_id.github_login + '/'\ + + (team.github_login and team.github_login or '') + + @api.multi + @api.depends('partner_ids') + def _compute_partner_qty(self): for team in self: - team.member_qty = len(team.member_ids) + team.partner_qty = len(team.partner_ids) + + @api.multi + @api.depends('repository_ids') + def _compute_repository_qty(self): + for team in self: + team.repository_qty = len(team.repository_ids) # Overloadable Section def get_odoo_data_from_github(self, data): + organization_obj = self.env['github.organization'] res = super(GithubTeam, self).get_odoo_data_from_github(data) + organization = organization_obj.get_from_id_or_create( + data['organization']) res.update({ 'name': data['name'], 'description': data['description'], + 'privacy': data['privacy'], + 'organization_id': organization.id, }) return res + @api.multi + def get_github_data_from_odoo(self): + self.ensure_one() + return { + 'name': self.name, + 'description': self.description and self.description or '', + 'privacy': self.privacy, + } + + @api.multi + def get_github_args_for_creation(self): + self.ensure_one() + return [ + self.organization_id.github_login, + ] + @api.multi def full_update(self): self.button_sync_member() + self.button_sync_repository() # Action Section @api.multi def button_sync_member(self): partner_obj = self.env['res.partner'] - github_member = self.get_github_for('team_members') + connector_member = self.get_github_connector( + 'team_members_member') + connector_maintainer = self.get_github_connector( + 'team_members_maintainer') for team in self: - member_ids = [] - for data in github_member.list([team.github_id]): + partner_data = [] + for data in connector_member.list([team.github_id_external]): + partner = partner_obj.get_from_id_or_create(data) + partner_data.append({ + 'partner_id': partner.id, 'role': 'member'}) + for data in connector_maintainer.list([team.github_id_external]): partner = partner_obj.get_from_id_or_create(data) - member_ids.append(partner.id) - team.member_ids = member_ids + partner_data.append({ + 'partner_id': partner.id, 'role': 'maintainer'}) + team.partner_ids = [ + (2, x.id, False) for x in team.partner_ids] + team.partner_ids = [(0, False, x) for x in partner_data] + + @api.multi + def button_sync_repository(self): + repository_obj = self.env['github.repository'] + connector = self.get_github_connector('team_repositories') + for team in self: + repository_data = [] + for data in connector.list([team.github_id_external]): + repository = repository_obj.get_from_id_or_create(data) + if data['permissions']['admin'] is True: + permission = 'admin' + elif data['permissions']['push'] is True: + permission = 'write' + else: + permission = 'read' + repository_data.append({ + 'repository_id': repository.id, 'permission': permission}) + + team.repository_ids = [ + (2, x.id, False) for x in team.repository_ids] + team.repository_ids = [(0, False, x) for x in repository_data] diff --git a/github_connector/models/github_team_partner.py b/github_connector/models/github_team_partner.py new file mode 100644 index 00000000..5258dfce --- /dev/null +++ b/github_connector/models/github_team_partner.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import fields, models + + +class GithubTeamPartner(models.Model): + _name = 'github.team.partner' + _order = 'team_id, partner_id' + + _ROLE_SELECTION = [ + ('member', 'Member'), + ('maintainer', 'Maintainer'), + ] + + # Column Section + team_id = fields.Many2one( + comodel_name='github.team', string='Team', + required=True, index=True, readonly=True, ondelete='cascade') + + partner_id = fields.Many2one( + comodel_name='res.partner', string='Member', + required=True, index=True, readonly=True, ondelete='cascade') + + role = fields.Selection( + selection=_ROLE_SELECTION, string='Role', required=True, + readonly=True) + + image_small = fields.Binary( + related='partner_id.image_small', readonly=True, store=True) diff --git a/github_connector/models/github_team_repository.py b/github_connector/models/github_team_repository.py new file mode 100644 index 00000000..ab63447a --- /dev/null +++ b/github_connector/models/github_team_repository.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2016-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import fields, models + + +class GithubTeamRepository(models.Model): + _name = 'github.team.repository' + _order = 'team_id, repository_id' + + _PERMISSION_SELECTION = [ + ('undefined', 'Undefined'), + ('read', 'Read'), + ('write', 'Write'), + ('admin', 'Admin'), + ] + + # Column Section + team_id = fields.Many2one( + comodel_name='github.team', string='Team', + required=True, index=True, readonly=True, ondelete='cascade') + + repository_id = fields.Many2one( + comodel_name='github.repository', string='Repository', + required=True, index=True, readonly=True, ondelete='cascade') + + permission = fields.Selection( + selection=_PERMISSION_SELECTION, string='Permission', required=True, + readonly=True) diff --git a/github_connector/models/res_partner.py b/github_connector/models/res_partner.py index 0a14a68b..5b456b55 100644 --- a/github_connector/models/res_partner.py +++ b/github_connector/models/res_partner.py @@ -14,19 +14,20 @@ class ResPartner(models.Model): _github_type = 'user' _github_login_field = 'login' _need_individual_call = True + _field_list_prevent_overwrite = ['name', 'website', 'email', 'image'] # Column Section is_bot_account = fields.Boolean( string='Is Bot Github Account', help="Check this box if this" "account is a bot, or something similar.") - team_ids = fields.Many2many( - string='Teams', comodel_name='github.team', - relation='github_team_partner_rel', column1='partner_id', - column2='team_id', readonly=True) + github_team_ids = fields.Many2many( + string='Teams', comodel_name='github.team.partner', + inverse_name='partner_id', readonly=True) - team_qty = fields.Integer( - string='Teams Quantity', compute='_compute_team_qty', store=True) + github_team_qty = fields.Integer( + string='Teams Quantity', compute='_compute_github_team_qty', + store=True) organization_ids = fields.Many2many( string='Organizations', comodel_name='github.organization', @@ -37,13 +38,6 @@ class ResPartner(models.Model): string='Organizations Quantity', compute='_compute_organization_qty', store=True) - # Compute Section - @api.multi - @api.depends('organization_ids', 'organization_ids.member_ids') - def _compute_organization_qty(self): - for partner in self: - partner.organization_qty = len(partner.organization_ids) - # Constraints Section _sql_constraints = [ ( @@ -63,10 +57,16 @@ def _check_login_company(self): # Compute Section @api.multi - @api.depends('team_ids', 'team_ids.member_ids') - def _compute_team_qty(self): + @api.depends('organization_ids', 'organization_ids.member_ids') + def _compute_organization_qty(self): + for partner in self: + partner.organization_qty = len(partner.organization_ids) + + @api.multi + @api.depends('github_team_ids') + def _compute_github_team_qty(self): for partner in self: - partner.team_qty = len(partner.team_ids) + partner.github_team_qty = len(partner.github_team_ids) # Custom Section @api.model diff --git a/github_connector/models/wizard_create_repository.py b/github_connector/models/wizard_create_repository.py new file mode 100644 index 00000000..6598c93d --- /dev/null +++ b/github_connector/models/wizard_create_repository.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2017-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, fields, models + + +class WizardCreateRepository(models.TransientModel): + _name = 'wizard.create.repository' + _inherit = ['github.repository'] + + # Overload Columns Section + name = fields.Char(readonly=False) + website = fields.Char(readonly=False) + description = fields.Char(readonly=False) + organization_id = fields.Many2one(readonly=False) + + @api.multi + def get_github_data_from_odoo(self): + self.ensure_one() + res = super(WizardCreateRepository, self).get_github_data_from_odoo() + return res + + @api.multi + def button_create_in_github(self): + self.ensure_one() + new_item = self.create_in_github(self.env['github.repository']) + return new_item.get_action() diff --git a/github_connector/models/wizard_create_team.py b/github_connector/models/wizard_create_team.py new file mode 100644 index 00000000..0b0a42d6 --- /dev/null +++ b/github_connector/models/wizard_create_team.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2017-Today: Odoo Community Association (OCA) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, fields, models + + +class WizardCreateTeam(models.TransientModel): + _name = 'wizard.create.team' + _inherit = ['github.team'] + + # Overload Columns Section + name = fields.Char(readonly=False) + description = fields.Char(readonly=False) + organization_id = fields.Many2one(readonly=False) + privacy = fields.Selection(readonly=False) + + # Columns Section + wizard_partner_ids = fields.Many2many( + string='Members', comodel_name='res.partner', + domain="[('github_login', '!=', False)]") + + wizard_repository_ids = fields.Many2many( + string='Repositories', comodel_name='github.repository') + + @api.multi + def get_github_data_from_odoo(self): + self.ensure_one() + res = super(WizardCreateTeam, self).get_github_data_from_odoo() + res.update({ + 'maintainers': [ + x.github_login for x in self.wizard_partner_ids + if x.github_login], + 'repo_names': [ + x.github_login for x in self.wizard_repository_ids + if x.github_login], + }) + return res + + @api.multi + def button_create_in_github(self): + self.ensure_one() + new_item = self.create_in_github(self.env['github.team']) + return new_item.get_action() diff --git a/github_connector/models/wizard_update_from_github.py b/github_connector/models/wizard_update_from_github.py index 920999ad..454e23eb 100644 --- a/github_connector/models/wizard_update_from_github.py +++ b/github_connector/models/wizard_update_from_github.py @@ -23,4 +23,4 @@ def button_update_from_github(self): for item in model_obj.browse(self._context['active_ids']): item.update_from_github(wizard.child_update) if partial_commit: - self._cr.commit() + self._cr.commit() # pylint: disable=invalid-commit diff --git a/github_connector/security/ir.model.access.csv b/github_connector/security/ir.model.access.csv index 92c52271..3a876318 100644 --- a/github_connector/security/ir.model.access.csv +++ b/github_connector/security/ir.model.access.csv @@ -1,15 +1,15 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_github_organization_reader,github_organization reader,model_github_organization,,1,0,0,0 access_github_organization_manager,github_organization manager,model_github_organization,github_connector.group_github_connector_manager,1,1,1,1 -,,,,,,, -access_github_organization_serie_reader,github_organization_serie reader,model_github_organization_serie,,1,0,0,0 -access_github_organization_serie_manager,github_organization_serie manager,model_github_organization_serie,github_connector.group_github_connector_manager,1,1,1,1 -,,,,,,, +access_github_organization_milestone_reader,github_organization_milestone reader,model_github_organization_milestone,,1,0,0,0 +access_github_organization_milestone_manager,github_organization_milestone manager,model_github_organization_milestone,github_connector.group_github_connector_manager,1,1,1,1 access_github_repository_reader,github_repository reader,model_github_repository,,1,0,0,0 access_github_repository_manager,github_repository manager,model_github_repository,github_connector.group_github_connector_manager,1,1,1,1 -,,,,,,, access_github_repository_branch_reader,github_repository_branch reader,model_github_repository_branch,,1,0,0,0 access_github_repository_branch_manager,github_repository_branch manager,model_github_repository_branch,github_connector.group_github_connector_manager,1,1,1,1 -,,,,,,, access_github_team_reader,github_team reader,model_github_team,,1,0,0,0 access_github_team_manager,github_team manager,model_github_team,github_connector.group_github_connector_manager,1,1,1,1 +access_github_team_partner_reader,github_team partner reader,model_github_team_partner,,1,0,0,0 +access_github_team_partner_manager,github_team partner manager,model_github_team_partner,github_connector.group_github_connector_manager,1,1,1,1 +access_github_team_repository_reader,github_team repository reader,model_github_team_repository,,1,0,0,0 +access_github_team_repository_manager,github_team repository manager,model_github_team_repository,github_connector.group_github_connector_manager,1,1,1,1 diff --git a/github_connector/static/description/github_organization_external_services.png b/github_connector/static/description/github_organization_external_services.png new file mode 100644 index 0000000000000000000000000000000000000000..b92f855212e87b87b6c098f5fc07990c62225a95 GIT binary patch literal 12607 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 literal 0 HcmV?d00001 diff --git a/github_connector/static/description/github_organization_kanban.png b/github_connector/static/description/github_organization_kanban.png new file mode 100644 index 0000000000000000000000000000000000000000..21a0d4ac81282a67d32c394046755f2550e89f87 GIT binary patch literal 43763 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�erf(P_I^hj&YJ-s1yC3zG*gIWqX4`P$*?^ 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%0D^=a8`O1a;76<<;m|*yPu077 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 Okp8S7QToxq_rCze>F^x@ literal 0 HcmV?d00001 diff --git a/github_connector/static/description/github_repository_branch_kanban.png b/github_connector/static/description/github_repository_branch_kanban.png new file mode 100644 index 0000000000000000000000000000000000000000..d77aa3a4f6dc917158b4dd1e80de3ca834c48852 GIT binary patch literal 10787 zcmc(l2UL?yx9>qf6r?C(1f=&~r8lK_kS@K0^creF6zRQ5?;u@3krD_?L~5!l5a5yHVPIeoC@IRmz`($o zL%+|za~u77ZD1{mzF>PkSJJtIegxjJjzE9D>!xVviGe}bee=XjWhbOSe@W&gXW*sn zYU>5G@UX$Kb8&UH;qE;3&Jz7^}Xx z$MhYTP_;g#t@n=Wt?}R=PIu*%OncT?CHAh+Sjs9$#w%Um?i`z} z&{zOTMM7msD{1l94+*nxLHdo2PYZnXrh8NiR2%AO1zGs-ubA6rA7Au6=DCjT>h?Jg zR7~5?9?c$Izqi~29zDw*J-fBf%%GISpfs-g)CP=8^ZV_3BF>lJUy>1TT&P^WA?kH} zf-aK8pyprTFu`>_!#?->qfLj6e$!}?RJQWcj;iDY1Brr~TTDhkt#Wmr)ucn_+eME)}@ zX2-FEbT64%0^^7z>8Aw~F7+D*4uu{fF-Z+bq6 zf$ws2P2%eaHM+SL-~0IM|5uTajDn(vo2DH2Ox3QCaEBU8Qa zc|;^JQScwWfEYUO_*+Ye{iGFcct1Wz_>vBHx}`C8l|8GuH6JB5thnhp90>l-9Sh#y zkl$*h0jl%%l#|GA0Y6^L#&B{=Dt-$g{~4IVl*Oygsxfx@wbx7YcC=yp(o-M!{LsRD zZC!b3igEr`hrH>B=#$2HE#%ju&HQ_5FB&$VBKB@d%o?=vV0*c{Z4U`BUmy}0>dRiM zOvP#o?8YZN=1F64#-&@;2k?K7?0`0n!GmGkdY1{ivtN*Bewn2Fm>!0wZJC%B8RB)( zIrnLRv=ohP{V-}*EAPh}6?O_TPUiYaOl17^u8?MCpSnuQJGGXxh~dlqo?R!yN4My{ z|M)@>SVqPg6qgYnbfHG&n{m!{C#}Y2HeRT~@51Lt+UuIDK9}x&+8o7xPQBe%b*qv9(n9r1_s;qiA+v?JE6(_g6 zIoLQ$n}|ivVX}o85^Ah8vL_X@12`|#KFgllY1GGJB^p-@;^kWbh&W9K$4jKlQP%+9 zRWam8ugx!h8|C^AJFReQ+}K*l$<`oNWZ*h&u77h}qohTSa7!M5Dj*~vjmu_pJm7Rh zM&sa>4DLYZd0U|Lr`>Y})5zy8ColDg_@r1LIWQ3t*KA1?y_7bbRK@s7{!@|AH@sM> zCk6~&)CpxE=HS@6dXd!wUD$yV5oBXoqX)AU%qkCb6e+iY0j+A%JYLr}&KPM`l<|^Y z$cP_bVmBe(H|L_ph z@D->{8me5Gr0D zDHFB2!m~fp%8cpNaRc`FYn-gXh(vLi*9DZqF_V%X2NP|Hs$>N_LC_<{Wu>Pq&-SQMjROz!Kxq0KF}>e$*-iw; z!v_CZAJfYv+eTM26+hyLz12w=_CVb2LRK1s!NI2*`(4AcGYI>qYin`a>;nnj;96l`>EEVVl7rRA6sh(=xFf6*}`*=$d3VCUE-G;ObZ*> zNxYVCWOLEc0Lq9@M;d9ig^tq{zZ5*^z>44R$0GVz!kF`#A-VXRG6x+El2&X@o<{-n z^^W`e4g<1a<4gPWz%gNf2ZE3!8ygJP!eRG%yvp+IyTvc3 z&o_cNt`IWdv6P{&7e7A2MnVfN)CB5|qyd`HARvIi*rGvSkLQkb#b|iC@-c|V5UWgI zInx;0KZK6!pvXSK9}_)KT+G@tKgV;eBZ!L&KRX4MyLSYo+7=(5*+?R`g;46bzP6N9v@Dy~I4X1fmb#Rw1E^s|0%tMhzed<9815y!veef`;gCNNm_l&r@RlVli}$lt z?#gYmDM55_80lr+P44J`Ni#y>nBL&E`68{h7EbW%5klZ(kN*CW zv;yrUR$7{>#|&%d_q8nf6#dT3T`8NPpSm0^ZSOM%d|qxj&eS77RQ@N}1GMLApLUeu zTYbq$Wop_J=6qZss{9x>mxmyKmE~t>%FMZSQrU zVMA#)O+u8wH$THXw5@)&l7u@#@U&J#6~@tE#m%W?8-KxVB?FbOXWS@nu6h|~tlB_*!DvIe*mAQWEE%bmE0{Vy0HLK;J%}Wh`(TerUm zobJLNsGcmO%S41Z>X&tu6%`cl%n`a$7WB{*Jkben=psexZO;^!0r z!zU-*+uIHwI7?WhG^=#fHi?=Y@(YfB#l%>h*&b#Gk~vZ{Gl1riD+ z==Z+iZtvxPiqD!$qP%GJ;2v+;sZW}#Z5 z8}Sw!ify*>vU5>#M6rJDJ>9ydkBhRI%RQT6tPz^CzA^7?KWsoO88J%4&o}7sT17Wi z*Z9f;MJNQNrZ2>IZatDZ!qed3W`43o_wxa5nppU_jpIzCA5NHIf_`J>um;CE!Y!i4 z9$!uEzNMiji`g~ysQCLKSKMu(86{6Als+;mUF@ z!uvZ>B%?Vp4kv7a&P`d@M7e7G)FlHj{Ej@X%W>ZgV%PSQM~lIi2kuYC%f{-W!}WIa zb36ohK$&>!lZxbT)^mf>TKB-o6t3Wd`YF_YxYYZ^r0c4T_#}Z(_+*B4=AAuLy`Zq) z3Y~#q;BTq^c%{&RM5hxE1P1o_#y?MDV&Z?1bQ`Vp2Z?LlRBq&a3g)A~RvsaLuTac8 zId2sIi`xeO7e%Chz1k^m6_az^R(ctq%|I?80|ahGAro^b8J^^-4}fPBrfe&N=63 z+c7l*R8dLaT<7c#2@|~nQer$NMc@-J>6}7b_7nF(wO{91O_f`>Jt~yXekPL0wl)lm z5a! zm-9(Pr&_z=>EYjbcHe_Ykc(omR$_~*pS7P2?iuzk&L7>EIyYS80W&-%)P6tTd4NxW zrJWJ%`G{v) zX6{Muv(uplRycuDNUm0PE=3JwsS(FEthxC@>U2$vIw_*>beLQHxzhX1*WbS2r-l!R zA;cEM5%=dKi9|keDf{Zv(bE^&~n`(gN{ z2&##PH4taf$S)d68%Na7N9G=U?OT8;j9w>A712IIIdA57ie*}*2pp)U#q3BT1f_l+ zZ~<(sZkGaxw?tH`P&Vn{?S6dgqtwh+17x?5VcVgUr#4jx8SCa?3}SIxw*PMr*s0Yz!uYH;#|0?L~%*NeiPuD^oX@7FfQ*ro{i-`6j)t;9#Ko)tr#9tfj zK;c}I{>x1nl&)%;owTxY76+NqsNaJ~jSyBh z&&s0{d11(f&aamfm%+0rB8UUUX-`$zE|1X{ zVXU4)$2uczNqQwM+ZFPzguOpL@#}S_@?O7~ zhWPdUNNHN6&nh<2A8kZP@X`s(8t~|a-ZU_5_V_(lAm&qg#@HVl z*KO)CF;8}p=wvbOhF)!@r$DLNpN$&6Tnv|90BmmVG0APcFgW%~R(!U6+=pHN#tnhB zKml_nq(2dwYs}Twx_(ayqp+EJ&_7~zEoAp>yR|Lev+3Q}B*TZW*fB0Il3=7gTKZ2V z0WwFX_HyNxcS*3Q*T)o=r|&KcEe z2}TL`E#LU3{{z~#gnzVcG)pL}yudNs!95oy!3n0$9eqxCR73z-)&v8!k*ub(P3bvy zwhcS%V>+{-#QCUy`fv6^dG*cSZWfn@xk&WUY*wK$a@vavIeI%>PC4UtXD!uSL**v7iTt6XGpH) zNajkz2ciR`*R0A)vYYR2` zTm^%JG;pMX+uS$g=c&hyQE-9yx_C%?nWYZxP0i1XBtS|e@nji(w#5P>v7*V)evO`( z6sC6?pPelH&InemanE|%y8<6m`^FC#sG&XZC2h`MjyACztsv^2{8141&Mrk41gMZROrU1F}xXG#N3u;DBAsc&+ zm8DmI>H&*F6*rI8U)d&+Imj!MOzQganECi5pz|*aH)QG6&Yma#Bc;&DR232jjwFF^ zd=7=N3gfFnrMiQ^Vea_;e~aqgIlf|KW)7ceusfP-7>%3qWpJ1q&Xvf@&d$cH%|h$Z zx!-!Ulkf1ito5j9%Q4{SZT4K3+^$m^f18+`ECT{vhjfSo_p;GBVl?xNMMusr8>#5y;%%gwR>kgXiKTmpR`cM)5mzD?Vq;qu!F^htN z9*3&~2juY#v8^{7QOBUmhw2i>H=fFIFcjQ+o+ zfd6N7^nX&zYYimg@o<2t?fUCG-|U%9I*C1_qRPSWXL@=M6DA>k^|39KwJ&BLFUbZx zdG5)=##Q7mM-c5gK+$xus%6>~%!%6)@@rT8XjJ2cpm~|}4fPHTY5gLhwno!B@V@h0 zjcTm~_s5}pC&{IkCnF#{*=eP^n!B#DAPiw0;but6t~aHr%QKA`ThMmnDTn7|7o;~7 zTgpRf+pN5d@uw0%noT`mm8MmwYB>==9(m$S?fB~~oZ41<_Zi);`wMBd1@+Zm6iz0s zQNdNw1RHc@Lg?#b)_cX`!2rhn4`|aXFT%55a#cf zGfZT&Ud1siTpz{Hr4AkMGwgOs$X$Z9DT<P?d6u`VV@6=)%P!p43Tjp0(*YB z)K22lcF;CXjU7un?0%E}ch21PXMM89X1?+CN4{fs;=Wl$W%~9CmWco8h3vyM2r<&GGiqnOA#Om1u&-!HS!i-c?O&&o7===+zd9 zG`_LN6SdUT8=F=5U%1$k+*CwSUz;;g7Kb#b)|z=%n0TP%l?|rX&T@gSn0;BwWF`JI zq#@2;JX&Ne+ShFu*vzAvL@BU0HyDRCEW5%QS|F05TfN$u$%YqT=foVhx1Or+qXpPx zkV_cL=Bt3TW~QdLX|G)%vYf0}DhNK^J8_rGjKq3d>0kQ}psDwiq%h~x(@%+DepLM? z@^1$m#BAaL4`n5^Ld->m*e=ZUM~a-}M4B;nPh=k?I63AMgjnuz!KWl^W8hbA{8>V^ zD;#f5(8iekMs*#l>!a@t_%3a%oB# zUk+^fnKj*Zz}slrbZ_y?VwELTpe+`Kpwq8!Tbd}1=o*qu$A#vzg6J?07ZyN>j`$CF z)M;vC`puwLlSL!VR?D`DOwS|SoZg&NA$}9LWSSp11J(f65Oc}qq85Ryd>ajtP5%Ji zFuxuSb^SR3xNEc1OFsoqN|T;RK&@&S4y#FPEFce*IXo*^$AaCxXs#d=v-&Nsp8l35 zbjx|x?*NU$+k-gQp3$@<>t~TLh>=H>hM2RmPlBWfaClg%9g!qK<_CpmHLo`PepsY5tEED0jNe7JSfBjf)GVH3<08n@OHTAfPu7Z6c z)$vpLn~{xg$J0^ib^Fg#bIk_o`9dCkg9#gkP3nwbzufqz!KV3YbXE42dCPZeR>jbNR0bSKXQIWZAXAZd^>zsP{Pq5RfEzBaOC_u2TT(T|y<>ufkJd8tjLoK|7l1G;Q9j^kLIb{@9?tGoRw3p4cX&~q;VF!X5D)h4(;6gO`U zikJd6l-Lqt>=F!n5zfGgsrB8-XhZsqHY<+?1j)%oF~mb21f!zKWfVa$t{rQ7c=v&9(aG<2__K)%Xex|Jz+?m6Dk49|IyQTi{ zU8e4@pDQPDoD^iv-L2jleDV`pWN*X#ZD}T)f~o0RRv{c-kn_(#a6kQzmXc_wfYJZ&wJVzaQhJ=Zr# zg5Yz>!?iMdM;8rh{T|Nl?N{MDKpsOmc7yw%H~NLRGrlO``wY^u2K+mm#ie}Imfqr@ zUy*1%=lEHl1CRaw$6rga2O@LQres9zr{tsV^#Js#g1ad`E~V4C4t%Xx%zm5Gk}0n}L0J8_WUK9^ZufY$V+k{w&R$lB1%$FpbSp93(X^Zde?)6z)@ zz3)3m5)b9bY}S8vngxe`<>+TO8ip~ac?Jl}>VFC=Exl7$C6dA&9BM}eUHc+~5KFnW z2eKuptWe2FCN1M9Q;y&4@lKaoc7pEymTM%#fDkE@(~^TR+J(Sv&UV!4%8GEY#?rE9 z6T0yW2e#}0PKSHB0SLprmLqi+@ImhZRTO&mV#*l%aAu~{onpwh>1E%aWcm1C*q;eYUg77HhXtDKDrs}dXnwfDmv-RxG|udI(svK6 zU|myFgV%f7b?I`utsKNpH#fX4Ed}-kajaNy{8g(#Z(vyKNxu>r?XB*+? zO)_Ukh~~tD9^ntxt{m3}j~;aYYCS#MjztT41@O4ooIyRl>uT;=NecAz{X}?h-^f%^ z_9mI_^aKRD1>rVd^gMY2$836+l{VK~kHg$rD|Uv#%Lur_;>i*y8(6+UsLI+xrIx*$X^ zC3sgQhP&bzTSH2oGGc?yYQ=$0ct@zxD2UM^rc}k1+rFhxLLX(Y_Fzo*M7k;7;$WN2 z{7#SqclG>~+r$)Pux$um1R;fb(>X$d-DQE-ASMhdSSD1pxgIv`=tw3kx>@nv+;pbW zzd)himXF4krIwhL>3#llCp@IH;8&Xk-%I+qCn8Gdb&LKw>}3 zEPFK$Lckxi2syf@xl%XVPv_VGpF@5NXc!^>41?Q zktcb*&Yo|cNTo?e5;wI+xGgil-RDc*iD)-lt(onA_G>=Q2E_}ZN)lz@!F>Hx3X-53 z-8J4VP#Vx=WTX){&E&fGshts)P`a2cWH~AIPn@iBCD#`>a)-E}Q#2byj|?n{4uS}K z&!leWo|46VDe31j?AO)+MdLp5I6sEuGJnCi`A6L`stS z{|h{0ogzA-je#BgJ}jfgflhs>#}fR3Z#s1LK4c131epjy-g4W-x7}dJTgITLEzEL6 z+WlmjbEZR-L#}j<@I?{P?yJ@L>XXYU0@sf#nu5`e?a^`{rzX8&eaTrF77ZUyq0lLy#$I?uTycu zV`q~oF|>O#{;oCd(he?Is9Rv~+wp%$oN!wI5T~H8)Tm8>IMV5S9fE2KnLRR80kxXLkJ}fwc5x+Dk zJ&03?Gebj(PIRBwsz_Y^?>Go;Ew(ORf1X$7r-2U-UvEh0y0q`A6@Cbx{~i=ICAep^ zo-xC5fhRE8NZ4X|YJWlD!!b_@ZeKxSx4Q#0B+m5F4hLRZn^gh*&%AZ!11QY$o`&V_ z9WgxE%<~nOBck>c1m(Kqqp71<@XYWf#H5=fp4-|2;qG%?6H)*GVY z2uAhBM^ZYh=_oOx_E+ilaxO5X7TvR#_Qt8s{t6X=e*r>77p3S87t~7dlV4qlR0L@f zsr5J(E*V*-q`S+>#aIcVo|!-p<(hBc274=pw#?L_*|o~a$I&IKNdu_?K(Z{YOqZv<45Y`XZ;WBX$d>_Z=) zQmohI?=XsVK<_1BqO%vQ7GBgsz*xVfjpF$Sgg5QCi(6 z!E8q?P`AuW<8Lz5V_VwGN7d``SB-1hQmz%&3r=6<_=P=I8LF$9BXfm^&yMINHXQ$% z2T7DVeAjpULxcXb(!@sOJ2FD}!W4wHwkBj8J0IlIOLyb;^P{J*fIlbr#>f6&L7xMv zcj#^~HFIMGlf$3gK$xUszm*h^n-2WLdBIZ@W}f3M=sqkX9(|w_LrG3uw&uBc=)VE} CL0I$v literal 0 HcmV?d00001 diff --git a/github_connector/static/description/github_repository_branch_list.png b/github_connector/static/description/github_repository_branch_list.png new file mode 100644 index 0000000000000000000000000000000000000000..8971ff63c6c313423d0cc298ea53af3716567304 GIT binary patch literal 40289 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 z zA{AS)Jxe#qsOi4M0^i@8Z0c0X`dE0^!Ch1-IC9(>Yu`tqU|v?$oX0m zoEXZmrE-Nv=zSph9M-ol`UmARbwR5CWESO>Q6f;*1ttPQ1YpXpZ6s<;ba5U%&uKBB zghvL6;&e2l51LP?MRAia21oQ3Ia4;?^nDT@os(f*cnZ_E$^I+`cw9z)zzq`5M%o2x z2+JRXE41Wun2S6aIUBKpryA+<4568#-VqJGHX)X|h$2B_#s*H9g4HFAgokYW%j(xW(TTP)r_a(d^13;uy<%kaV9V z<7IKOwvT3?;o6fuzxh zX{dFdkdk@#E^<`tonWtdOP+?>#)QRr*o4H!hS}sD!Q3~`eTjba$4%y$?T)JK=@rLT zxC!@&i&%Us9|IG&rFGob@3kn80R6Wy@m!1iUbNhFH?3M!^%Rult_OPDjVFEgY&RJr zYG-+JpF7{lloOrPvuFk4z$vc`e%sU`__(Day0eF4%A2Z51SP6v;kD{ zq_j-iw^OU$T!6m-l(V2Dy2bH+Cz@MgXsSxS`k0P~ueSCYki8@)&zVLS*T7cO$9f`4 z6Q8c3l6MlqlwXLhw9j>gckm{L0glwikI5%K-HLMHZcDjQVVCVq9EP%bt=8Qgeta#6O|3|7>fMC?Pkj zA*}VNj2Z}HuLpkVT+GC(ADp>O(A;(`gMC~MEtqHt;gufxnBZ97JA(DHK$I#bcYC0h zC}~t)lT}rG&Ed;R_uvy`MKB`i^jktT*W2w0`RQ;hJn)=C~4s^q9Apm7(H>Y+{^W=4TEE%f!!)g`_)=QoZ ze=^$;Dz8dO-0stNf-oy_`7+dH{5q5Zu*qRpP zEi*f2hnTYCA230YBaAnV0Qa~HW&Pkd#BoK1;nXxAo*G!CwxnV4^NxN*N&jYhtt#x|surCp+ zwl7>FYGA%r*$9cGRo5~FTK3s4e5GIDd4`i~P9Dxs9w7KmOs_m`0V%&wN>AnjC)Y8! z-Ak^FJB&DAF>m(Ms~iYmFry`A$om%^l+iI5?V&1q!c)^w>{NDMWu0PrE9267$JP3Y zR0b;@jpp&);IMqZ=##w=xhPN}iN_<-cWH;_ zbimenF+HsrTiv)eYXM!DxPAd}{U6oi3>|Z?v-Fjt{Ctd=ntXF0%H}gQv7^|=6QvW#&x{T9tDyVcia#7%)i!dbuGrjT^P)d zW8?nJ(ISjz8}h{V{c7LbR&B8t;kO6NkZPDpzvj3`T4HEEDJShIB8>4+{QYb_BbB^7 z=1{J7CtsZZD3&u4M_J|PvCqvp?-1h>S0BCNws%D>v&=S^YN?|e#H}7kGW5}#&EcS+ zeC!JxPLxDog}l!k6`P`f)d_jN(k;m?^ene8e=lkxgWG;e?W1~3<#qOnfrS*XMCB9n zEra>%@0V!)=1*)9zeV(_;a>Cs9NOC20)m3ncVdF~IyQNDc|&H`=~Loa3%HnCepuSD zsFb)I9EYSA;UFt}L3;|A%YUg_Y?q5LBOKsaj+!d%(%_*a``owLjdXp+uJqx zvK(QsG}6&mxY*)QIA5c+4O!1px1v1M=dF3LTrAS8-94TCR9qNiT#IOpYt|a5ST6Y| zxqQw@iF^ld9eKa;2cRdA1&8zCrk+l8{^Ci>3Q06|~O_Jdct!*c${%Zk5$ z+!qiMLV4A9;nr2Elntf~7F!A1WDtL&^a|1S*{EoT4E m-{k%Z_Mra?NdI3({6|sZ?2u`O5Ptg_X=tkIsi2hYU;huiO`^d7 literal 0 HcmV?d00001 diff --git a/github_connector/static/description/github_repository_kanban.png b/github_connector/static/description/github_repository_kanban.png new file mode 100644 index 0000000000000000000000000000000000000000..9d2a59180eced09687d9870c9fdbdd11cb87de34 GIT binary patch literal 28022 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


n%cb3 zGB8@tHox0|SRLlD?F%Y$A>Wcu-_^#%)#hlwpENo4Mb+KBUSH6PM(tMplyD*mnUn!o z1)?lTT33QTrm6Y*E)_B+QJ~`*a(|N|9XW9i^A77gxXbhNLX@R7&sHY1gR09rN4l); zcGf_+e0#{8!oG0R&J5Eosr`iw;7?$H7NjK~bdUOpuCCuoE(y8x{@wpZQ-M}Y-y{UG z%H`vU*LuO(Y^B*hQHZX^p6r>kigWFBcXrVXM;yY=Ms zZy1cyS1#zEvhD3UoN03B+3O_a@Qb}A@wP$@kvb7*9V$@Sym+jGOlU%u4hjl*!gd+| z6e*?0&))y*OS9b{BNfZW+u0NPh}dw1i5snE-6|{nNryH}^1U{3#Fb&uD$-sK==%}i zKL6Qrzr6zxxN$FZ0b9xzmTu9Lr}k=Iug40f=RN3?Qh4$pMa_Sth+VIlF1(UG0Xadr z#a62`l>%Cc_nbe{!j4#&nFEpk{_c@88vkYRZk`~*#q2*c+O@AcQb?ncZn$e}@!#53 zBb7f>rzA41`C$w*FmI6Aoqw(fjEMhb7}Y<#)tSsU`sU`yMCxwDc44)Vh!{P+9kY;7 z!qn6hCepc%w7>qG%oWhBx8mg8jOS(Tb;F6$*w|?A=r}SvE0T{%OpqXtOnPEuWK?(> zjkLv%(?4hv6HxF_6Gg>x)?ZZf{2kIofEl`gOp^X{{WB2k@*Xwu;vTn$wHpI@MjDE& Ml%izO8{Mz}2SprZ761SM literal 0 HcmV?d00001 diff --git a/github_connector/static/description/github_settings.png b/github_connector/static/description/github_settings.png index 0b7439b98320ceab250395723df6594f655f3b4c..e2c92d764fa0bc797b5a2bfe0f555d88b022203c 100644 GIT binary patch literal 11600 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 diff --git a/github_connector/static/description/github_team_kanban.png b/github_connector/static/description/github_team_kanban.png new file mode 100644 index 0000000000000000000000000000000000000000..ed6a1e0a4e7d92127f2421241656e50ed6a307e1 GIT binary patch literal 26010 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

^B|yv+0GqdZLd{@i)?oIqbk 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 literal 0 HcmV?d00001 diff --git a/github_connector/static/description/github_team_partner_kanban.png b/github_connector/static/description/github_team_partner_kanban.png new file mode 100644 index 0000000000000000000000000000000000000000..2c44ddd8dc338dd1cf993342b31791b4e92aa8d7 GIT binary patch literal 87913 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

<9_!OQuTFot%ga$5 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

cq-Kw_gAe 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 diff --git a/github_connector/static/description/reporting_branches_by_milestone.png b/github_connector/static/description/reporting_branches_by_milestone.png new file mode 100644 index 0000000000000000000000000000000000000000..c57c6ed4a875bd6275330fed227c0a80d6e9dc91 GIT binary patch literal 6435 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 Y2uYKJMSBlepBw-a19SaaUHAL{0oU`--v9sr literal 0 HcmV?d00001 diff --git a/github_connector/static/description/reporting_branches_by_serie.png b/github_connector/static/description/reporting_branches_by_serie.png deleted file mode 100644 index 473aca1942a27ad41400379a670569af152bbdf8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8458 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 KT+x$P@BbG~4S19Q diff --git a/github_connector/static/description/reporting_sizes_by_milestone.png b/github_connector/static/description/reporting_sizes_by_milestone.png new file mode 100644 index 0000000000000000000000000000000000000000..e27faae6cae74472cd712b559f2d3621f68aaa3a GIT binary patch literal 8229 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 Ta>qZK-c?u8c~E-a_T|3;MK#TZ diff --git a/github_connector/static/description/repository_branch_list.png b/github_connector/static/description/repository_branch_list.png deleted file mode 100644 index 4986ceb1c66cf2dbd1f9288ec0fe2d6f15ca42b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30294 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 ?k%jhxuU^hMoSI4CzF8vpjYP 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 CYE3r) diff --git a/github_connector/static/description/sync_organization.png b/github_connector/static/description/sync_organization.png index a70aec9d7e955af3c27e32e163d4a964c1d29236..69339f3d889d4081fdec0ece21fcd78bd037916a 100644 GIT binary patch literal 14900 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 diff --git a/github_connector/static/description/wizard_create_repository.png b/github_connector/static/description/wizard_create_repository.png new file mode 100644 index 0000000000000000000000000000000000000000..bd6f609fa59b87ee197926341f32cbacfb78167f GIT binary patch literal 18054 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 z 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 literal 0 HcmV?d00001 diff --git a/github_connector/static/description/wizard_create_team.png b/github_connector/static/description/wizard_create_team.png new file mode 100644 index 0000000000000000000000000000000000000000..a810ad0a208d87103c77f135f3265e38f0b5e347 GIT binary patch literal 23789 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 LT3#bub&vip|AAot literal 0 HcmV?d00001 diff --git a/github_connector/static/description/wizard_download_analyze.png b/github_connector/static/description/wizard_download_analyze.png new file mode 100644 index 0000000000000000000000000000000000000000..a8b27e9e311b24259aa1832adb70984478e47663 GIT binary patch literal 12250 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 literal 0 HcmV?d00001 diff --git a/github_connector/static/src/img/default_github_organization.png b/github_connector/static/src/img/default_github_organization.png new file mode 100644 index 0000000000000000000000000000000000000000..9187bcdd5480451ed9fd9b5f3d5dd064865a07f7 GIT binary patch literal 6447 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 literal 0 HcmV?d00001 diff --git a/github_connector/views/action.xml b/github_connector/views/action.xml index 408f019f..e5ab58ed 100644 --- a/github_connector/views/action.xml +++ b/github_connector/views/action.xml @@ -12,7 +12,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). ir.actions.act_window github.organization form - tree,form + kanban,tree,form @@ -20,7 +20,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). ir.actions.act_window res.partner form - tree,form,kanban + kanban,tree,form {'search_default_has_github_account':1} @@ -29,7 +29,43 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). ir.actions.act_window github.team form - tree,form + kanban,tree,form + + + + Teams + ir.actions.act_window + github.team.partner + form + + kanban,tree,form + + + + Members + ir.actions.act_window + github.team.partner + form + + kanban,tree,form + + + + Team + ir.actions.act_window + github.team.repository + form + + kanban,tree,form + + + + Repositories + ir.actions.act_window + github.team.repository + form + + kanban,tree,form @@ -38,7 +74,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). ir.actions.act_window github.repository form - tree,form + kanban,tree,form @@ -46,7 +82,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). ir.actions.act_window github.repository.branch form - tree,form + kanban,tree,form @@ -98,6 +134,24 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). new + + Create Team in Github Wizard + ir.actions.act_window + wizard.create.team + form + form + new + + + + Create Repo in Github Wizard + ir.actions.act_window + wizard.create.repository + form + form + new + + Update from Github wizard.update.from.github @@ -106,24 +160,24 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - - Branches by Serie + + Branches by Milestone ir.actions.act_window github.repository.branch form - graph - {'search_default_group_by_organization_serie_id': True} - + graph,pivot + {'search_default_group_by_organization_milestone_id': True} + - - Sizes by Serie (Megabyte) + + Sizes by Milestone ir.actions.act_window github.repository.branch form - graph - {'search_default_group_by_organization_serie_id': True} - + graph,pivot + {'search_default_group_by_organization_milestone_id': True} + diff --git a/github_connector/views/menu.xml b/github_connector/views/menu.xml index e83c3c61..fef979e8 100644 --- a/github_connector/views/menu.xml +++ b/github_connector/views/menu.xml @@ -59,30 +59,32 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). name="Sync Object" action="action_wizard_load_github_model"/> + + + + - - - - - + sequence="1" + action="action_github_branch_by_milestone"/> - + sequence="2" + action="action_github_size_by_milestone"/> diff --git a/github_connector/views/view_github_organization.xml b/github_connector/views/view_github_organization.xml index 92b44f2a..e5ae6a40 100644 --- a/github_connector/views/view_github_organization.xml +++ b/github_connector/views/view_github_organization.xml @@ -20,8 +20,8 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). github.organization - + @@ -34,12 +34,15 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

-
@@ -51,20 +54,19 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-
@@ -75,38 +77,36 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - - + + - - + + + - - - + + + - - - - - - + - + +

-

- -

+

-
- -
-
+ - + - + +

-
- - -
-
- + + - - - - - - + - - -
- - - - - - - + -
- - - - - - -
-
+
- - - + + + - + - - - + + + - + - - + + - + - -
-

-

+

+ +

+

+ +

- - - + + + - + - -
-

+

+ +

- +

- - - - + + + + - + - - - - + - + - + - + +
+

+ +

+

+ +

+
@@ -180,7 +199,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). github.organization - + @@ -193,12 +212,13 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
- -
+
+ +
+

diff --git a/github_connector/views/view_github_repository.xml b/github_connector/views/view_github_repository.xml index d4b1b97e..8f9b19fd 100644 --- a/github_connector/views/view_github_repository.xml +++ b/github_connector/views/view_github_repository.xml @@ -28,7 +28,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). github.repository - + @@ -52,28 +52,45 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
@@ -102,7 +119,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). name="button_update_from_github_light" type="object" string="Light Sync" - class="btn btn-default" + class="btn btn-light" icon="fa-angle-right" groups="github_connector.group_github_connector_manager" /> @@ -110,7 +127,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). name="button_update_from_github_full" type="object" string="Full Sync" - class="btn btn-default" + class="btn btn-light" icon="fa-angle-double-right" groups="github_connector.group_github_connector_manager" /> diff --git a/github_connector/views/view_github_repository_branch.xml b/github_connector/views/view_github_repository_branch.xml index 2c9e5164..70b3480d 100644 --- a/github_connector/views/view_github_repository_branch.xml +++ b/github_connector/views/view_github_repository_branch.xml @@ -61,7 +61,10 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). github.repository.branch - + github.team - + @@ -64,12 +64,11 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
diff --git a/github_connector/wizards/__init__.py b/github_connector/wizards/__init__.py index 7c2d1c8b..a6cb4c87 100644 --- a/github_connector/wizards/__init__.py +++ b/github_connector/wizards/__init__.py @@ -1,7 +1,3 @@ from . import wizard_create_team from . import wizard_create_repository - from . import wizard_load_github_model -from . import wizard_download_analyze_branch -from . import wizard_update_from_github -from . import wizard_update_branch_list diff --git a/github_connector/wizards/view_wizard_download_analyze_branch.xml b/github_connector/wizards/view_wizard_download_analyze_branch.xml deleted file mode 100644 index d4560343..00000000 --- a/github_connector/wizards/view_wizard_download_analyze_branch.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - Download and Analyze Source Code - wizard.download.analyze.branch - -
- - - - -
-
-
-
-
-
diff --git a/github_connector/wizards/view_wizard_update_branch_list.xml b/github_connector/wizards/view_wizard_update_branch_list.xml deleted file mode 100644 index fc265cea..00000000 --- a/github_connector/wizards/view_wizard_update_branch_list.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - wizard.update.branch.list - -
-
-
-
-
-
-
diff --git a/github_connector/wizards/view_wizard_update_from_github.xml b/github_connector/wizards/view_wizard_update_from_github.xml deleted file mode 100644 index 66775a6e..00000000 --- a/github_connector/wizards/view_wizard_update_from_github.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - wizard.update.from.github - -
- - - -
-
-
-
-
-
diff --git a/github_connector/wizards/wizard_create_repository.py b/github_connector/wizards/wizard_create_repository.py index d9a13b96..5dacf0ec 100644 --- a/github_connector/wizards/wizard_create_repository.py +++ b/github_connector/wizards/wizard_create_repository.py @@ -2,7 +2,7 @@ # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import api, fields, models +from odoo import fields, models class WizardCreateRepository(models.TransientModel): @@ -16,13 +16,11 @@ class WizardCreateRepository(models.TransientModel): description = fields.Char(readonly=False) organization_id = fields.Many2one(readonly=False) - @api.multi def get_github_data_from_odoo(self): self.ensure_one() - res = super(WizardCreateRepository, self).get_github_data_from_odoo() + res = super().get_github_data_from_odoo() return res - @api.multi def button_create_in_github(self): self.ensure_one() new_item = self.create_in_github(self.env["github.repository"]) diff --git a/github_connector/wizards/wizard_create_team.py b/github_connector/wizards/wizard_create_team.py index d5f77ac7..cb85f135 100644 --- a/github_connector/wizards/wizard_create_team.py +++ b/github_connector/wizards/wizard_create_team.py @@ -2,7 +2,7 @@ # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import api, fields, models +from odoo import fields, models class WizardCreateTeam(models.TransientModel): @@ -27,10 +27,9 @@ class WizardCreateTeam(models.TransientModel): string="Team Repositories", comodel_name="github.repository" ) - @api.multi def get_github_data_from_odoo(self): self.ensure_one() - res = super(WizardCreateTeam, self).get_github_data_from_odoo() + res = super().get_github_data_from_odoo() res.update( { "maintainers": [ @@ -43,7 +42,6 @@ def get_github_data_from_odoo(self): ) return res - @api.multi def button_create_in_github(self): self.ensure_one() new_item = self.create_in_github(self.env["github.team"]) diff --git a/github_connector/wizards/wizard_download_analyze_branch.py b/github_connector/wizards/wizard_download_analyze_branch.py deleted file mode 100644 index bd951ef0..00000000 --- a/github_connector/wizards/wizard_download_analyze_branch.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) 2016-Today: Odoo Community Association (OCA) -# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from odoo import api, fields, models - - -class WizardDownloadAnalyzeBranch(models.TransientModel): - _name = "wizard.download.analyze.branch" - _description = "Wizard Download Analyze Branch" - - download_source_code = fields.Boolean(string="Download Source Code", default=True) - - analyze_source_code = fields.Boolean(string="Analyze Source Code", default=True) - - @api.multi - def apply(self): - repository_obj = self.env["github.repository.branch"] - for wizard in self: - branches = repository_obj.browse(self._context["active_ids"]) - if wizard.download_source_code: - branches.button_download_code() - if wizard.analyze_source_code: - branches.button_analyze_code() diff --git a/github_connector/wizards/wizard_load_github_model.py b/github_connector/wizards/wizard_load_github_model.py index 1a5034b2..aa3a1e71 100644 --- a/github_connector/wizards/wizard_load_github_model.py +++ b/github_connector/wizards/wizard_load_github_model.py @@ -2,7 +2,7 @@ # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import api, fields, models +from odoo import fields, models from ..models.github import _GITHUB_TYPE @@ -23,7 +23,6 @@ class WizardLoadGithubModel(models.TransientModel): child_update = fields.Boolean(string="Update Child Objects", default=False) - @api.multi def button_create_from_github(self): for wizard in self: if wizard.github_type == "organization": diff --git a/github_connector/wizards/wizard_update_branch_list.py b/github_connector/wizards/wizard_update_branch_list.py deleted file mode 100644 index 9be8ef4e..00000000 --- a/github_connector/wizards/wizard_update_branch_list.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (C) 2016-Today: Odoo Community Association (OCA) -# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from odoo import api, models - - -class WizardUpdateBranchList(models.TransientModel): - _name = "wizard.update.branch.list" - _description = "Wizard Update Branch List" - - @api.multi - def button_update_branch_list(self): - for wizard in self: - repository_obj = self.env["github.repository"] - items = repository_obj.browse(self._context["active_ids"]) - items.button_sync_branch() diff --git a/github_connector/wizards/wizard_update_from_github.py b/github_connector/wizards/wizard_update_from_github.py deleted file mode 100644 index b45450b9..00000000 --- a/github_connector/wizards/wizard_update_from_github.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2016-Today: Odoo Community Association (OCA) -# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from odoo import api, fields, models -from odoo.tools.safe_eval import safe_eval - - -class WizardUpdateFromGithub(models.TransientModel): - _name = "wizard.update.from.github" - _description = "Wizard Update From Github" - - # Columns Section - child_update = fields.Boolean(string="Update Child Objects", default=False) - - @api.multi - def button_update_from_github(self): - partial_commit = safe_eval( - self.sudo() - .env["ir.config_parameter"] - .get_param("git.partial_commit_during_analysis") - ) - for wizard in self: - model_obj = self.env[self._context["active_model"]] - for item in model_obj.browse(self._context["active_ids"]): - item.update_from_github(wizard.child_update) - if partial_commit: - self._cr.commit() # pylint: disable=invalid-commit From 6ee2fd6c2452c03db403b3b39b54a02f3f99188e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20D=C3=ADaz?= Date: Mon, 20 Apr 2020 14:47:27 +0200 Subject: [PATCH 32/72] [IMP] github_connector: Adapt to new API --- github_connector/i18n/github_connector.pot | 1129 +++++++++++++++++ .../models/github_repository_branch.py | 6 +- 2 files changed, 1132 insertions(+), 3 deletions(-) create mode 100644 github_connector/i18n/github_connector.pot diff --git a/github_connector/i18n/github_connector.pot b/github_connector/i18n/github_connector.pot new file mode 100644 index 00000000..b827834e --- /dev/null +++ b/github_connector/i18n/github_connector.pot @@ -0,0 +1,1129 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * github_connector +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_tree +msgid "# Branches" +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/github.py:0 +#, python-format +msgid "'%s' is not implemented." +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/github.py:0 +#, python-format +msgid "" +"401 - Unable to authenticate to Github with the login '%s'.\n" +"You should check your credentials in the Odoo configuration file." +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +msgid "" +" Members\n" +" Member" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_form +msgid "" +" Branches\n" +" Branch" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_form +msgid "" +" Teams\n" +" Team" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +msgid "" +" Repositories\n" +" Repository" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +msgid "" +" Teams\n" +" Team" +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/res_partner.py:0 +#, python-format +msgid "A company ('%s') can not have a Github login associated." +msgstr "" + +#. module: github_connector +#: model:ir.model.fields.selection,name:github_connector.selection__github_team_repository__permission__admin +msgid "Admin" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_tree +msgid "Analyze Source Code" +msgstr "" + +#. module: github_connector +#: model:ir.actions.server,name:github_connector.cron_analyze_code_ir_actions_server +#: model:ir.cron,cron_name:github_connector.cron_analyze_code +#: model:ir.cron,name:github_connector.cron_analyze_code +msgid "Analyze Source Code for All Github Branches" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields.selection,name:github_connector.selection__github_repository_branch__state__analyzed +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_search +msgid "Analyzed" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_team_partner_from_team_kanban +msgid "Avatar" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository__repository_branch_ids +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__repository_branch_ids +msgid "Branches" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_form +msgid "Branches Sync." +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_github_branch_by_serie +#: model:ir.ui.menu,name:github_connector.menu_branch_by_serie +msgid "Branches by Serie" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__ci_url +msgid "CI URL" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__ci_url_pattern +msgid "CI URL Pattern" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_wizard_create_repository_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_wizard_create_team_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_wizard_load_github_model_form +msgid "Cancel" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,help:github_connector.field_res_partner__is_bot_account +#: model:ir.model.fields,help:github_connector.field_res_users__is_bot_account +msgid "Check this box if this account is a bot or similar." +msgstr "" + +#. module: github_connector +#: model:ir.model.fields.selection,name:github_connector.selection__github_team__privacy__closed +#: model:ir.model.fields.selection,name:github_connector.selection__wizard_create_team__privacy__closed +msgid "Closed" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository__color +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__color +msgid "Color Index" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository__complete_name +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__complete_name +#: model:ir.model.fields,field_description:github_connector.field_github_team__complete_name +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__complete_name +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__complete_name +msgid "Complete Name" +msgstr "" + +#. module: github_connector +#: model:res.groups,name:github_connector.group_github_connector_manager +msgid "Connector Github Manager" +msgstr "" + +#. module: github_connector +#: model:res.groups,name:github_connector.group_github_connector_user +msgid "Connector Github User" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_res_partner +msgid "Contact" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__coverage_url +msgid "Coverage URL" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__coverage_url_pattern +msgid "Coverage URL Pattern" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_abstract_github_model__github_create_date +#: model:ir.model.fields,field_description:github_connector.field_github_organization__github_create_date +#: model:ir.model.fields,field_description:github_connector.field_github_repository__github_create_date +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__github_create_date +#: model:ir.model.fields,field_description:github_connector.field_github_team__github_create_date +#: model:ir.model.fields,field_description:github_connector.field_res_partner__github_create_date +#: model:ir.model.fields,field_description:github_connector.field_res_users__github_create_date +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__github_create_date +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__github_create_date +msgid "Create Date on Github" +msgstr "" + +#. module: github_connector +#: model:ir.ui.menu,name:github_connector.menu_wizard_create_repository +msgid "Create Repo in Github" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_wizard_create_repository +msgid "Create Repo in Github Wizard" +msgstr "" + +#. module: github_connector +#: model:ir.ui.menu,name:github_connector.menu_wizard_create_team +msgid "Create Team in Github" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_wizard_create_team +msgid "Create Team in Github Wizard" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_wizard_create_repository_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_wizard_create_team_form +msgid "Create in Github" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__create_uid +#: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__create_uid +#: model:ir.model.fields,field_description:github_connector.field_github_repository__create_uid +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__create_uid +#: model:ir.model.fields,field_description:github_connector.field_github_team__create_uid +#: model:ir.model.fields,field_description:github_connector.field_github_team_partner__create_uid +#: model:ir.model.fields,field_description:github_connector.field_github_team_repository__create_uid +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__create_uid +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__create_uid +#: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model__create_uid +msgid "Created by" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__create_date +#: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__create_date +#: model:ir.model.fields,field_description:github_connector.field_github_repository__create_date +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__create_date +#: model:ir.model.fields,field_description:github_connector.field_github_team__create_date +#: model:ir.model.fields,field_description:github_connector.field_github_team_partner__create_date +#: model:ir.model.fields,field_description:github_connector.field_github_team_repository__create_date +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__create_date +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__create_date +#: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model__create_date +msgid "Created on" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__description +#: model:ir.model.fields,field_description:github_connector.field_github_repository__description +#: model:ir.model.fields,field_description:github_connector.field_github_team__description +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__description +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__description +msgid "Description" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_abstract_github_model__display_name +#: model:ir.model.fields,field_description:github_connector.field_github_organization__display_name +#: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__display_name +#: model:ir.model.fields,field_description:github_connector.field_github_repository__display_name +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__display_name +#: model:ir.model.fields,field_description:github_connector.field_github_team__display_name +#: model:ir.model.fields,field_description:github_connector.field_github_team_partner__display_name +#: model:ir.model.fields,field_description:github_connector.field_github_team_repository__display_name +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__display_name +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__display_name +#: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model__display_name +msgid "Display Name" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_tree +msgid "Download Source Code" +msgstr "" + +#. module: github_connector +#: model:ir.actions.server,name:github_connector.cron_download_code_ir_actions_server +#: model:ir.cron,cron_name:github_connector.cron_download_code +#: model:ir.cron,name:github_connector.cron_download_code +msgid "Download Source Code for All Github Branches" +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/abstract_github_model.py:0 +#, python-format +msgid "Duplicate object with Github login %s" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__email +msgid "Email" +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/github_repository_branch.py:0 +#, python-format +msgid "" +"Error when trying to create the folder %s\n" +" Please check Odoo Access Rights." +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/github_repository_branch.py:0 +#, python-format +msgid "" +"Error when trying to create the main folder %s\n" +" Please check Odoo Access Rights.\n" +" %s" +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/github_repository_branch.py:0 +#, python-format +msgid "" +"Error when updating the branch %s in the local folder %s.\n" +" Deleting the local folder and trying again." +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +msgid "External Services" +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/abstract_github_model.py:0 +#, python-format +msgid "" +"Feature not Implemented : Please define 'get_github_args_for_creation' " +"function in child model." +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/abstract_github_model.py:0 +#, python-format +msgid "" +"Feature not Implemented : Please define 'get_github_data_from_odoo' function" +" in child model." +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/abstract_github_model.py:0 +#, python-format +msgid "" +"Feature not Implemented : Please define 'github_login_field' function in " +"child model." +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/abstract_github_model.py:0 +#, python-format +msgid "" +"Feature not Implemented : Please define 'github_type' function in child " +"model." +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_team_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_res_partner_form +msgid "Full Sync" +msgstr "" + +#. module: github_connector +#: model:ir.ui.menu,name:github_connector.menu_github +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_team_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_res_partner_form +msgid "Github" +msgstr "" + +#. module: github_connector +#: model:ir.ui.menu,name:github_connector.menu_github_community +msgid "Github Community" +msgstr "" + +#. module: github_connector +#: model:ir.module.category,name:github_connector.module_category_github_connector +msgid "Github Connector" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_abstract_github_model__github_id_external +#: model:ir.model.fields,field_description:github_connector.field_github_organization__github_id_external +#: model:ir.model.fields,field_description:github_connector.field_github_repository__github_id_external +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__github_id_external +#: model:ir.model.fields,field_description:github_connector.field_github_team__github_id_external +#: model:ir.model.fields,field_description:github_connector.field_res_partner__github_id_external +#: model:ir.model.fields,field_description:github_connector.field_res_users__github_id_external +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__github_id_external +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__github_id_external +msgid "Github Id" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_res_partner_search +msgid "Github Login" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model__name +msgid "Github Name" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_github_organization_serie +msgid "Github Organization Serie" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_github_repository +#: model:ir.ui.menu,name:github_connector.menu_github_repository_root +msgid "Github Repository" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_github_repository_branch +msgid "Github Repository Branch" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_github_team +msgid "Github Team" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_github_team_partner +msgid "Github Team Partner" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_github_team_repository +msgid "Github Team Repository" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_abstract_github_model__github_login +#: model:ir.model.fields,field_description:github_connector.field_github_organization__github_login +#: model:ir.model.fields,field_description:github_connector.field_github_repository__github_login +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__github_login +#: model:ir.model.fields,field_description:github_connector.field_github_team__github_login +#: model:ir.model.fields,field_description:github_connector.field_res_partner__github_login +#: model:ir.model.fields,field_description:github_connector.field_res_users__github_login +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__github_login +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__github_login +msgid "Github Technical Name" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model__github_type +msgid "Github Type Name" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_abstract_github_model__github_url +#: model:ir.model.fields,field_description:github_connector.field_github_organization__github_url +#: model:ir.model.fields,field_description:github_connector.field_github_repository__github_url +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__github_url +#: model:ir.model.fields,field_description:github_connector.field_github_team__github_url +#: model:ir.model.fields,field_description:github_connector.field_res_partner__github_url +#: model:ir.model.fields,field_description:github_connector.field_res_users__github_url +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__github_url +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__github_url +msgid "Github URL" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_abstract_github_model +msgid "Github abstract model" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_github_organization +msgid "Github organization" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_search +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_search +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_team_search +msgid "Group By" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_res_partner_search +msgid "Has Github Account" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_abstract_github_model__id +#: model:ir.model.fields,field_description:github_connector.field_github_organization__id +#: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__id +#: model:ir.model.fields,field_description:github_connector.field_github_repository__id +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__id +#: model:ir.model.fields,field_description:github_connector.field_github_team__id +#: model:ir.model.fields,field_description:github_connector.field_github_team_partner__id +#: model:ir.model.fields,field_description:github_connector.field_github_team_repository__id +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__id +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__id +#: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model__id +msgid "ID" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,help:github_connector.field_github_repository__is_ignored +#: model:ir.model.fields,help:github_connector.field_wizard_create_repository__is_ignored +msgid "" +"If checked, the branches will not be synchronized, and the code source will " +"this way not be downloaded and analyzed. To ignore a repository, go to the " +"organization and add the file 'Ignored Repositories'." +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__ignored_repository_names +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +msgid "Ignored Repositories" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__image +msgid "Image" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_res_partner__is_bot_account +#: model:ir.model.fields,field_description:github_connector.field_res_users__is_bot_account +msgid "Is Bot Github Account" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository__is_ignored +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__is_ignored +msgid "Is Ignored" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__last_analyze_date +msgid "Last Analyze Date" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__last_download_date +msgid "Last Download Date" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_abstract_github_model____last_update +#: model:ir.model.fields,field_description:github_connector.field_github_organization____last_update +#: model:ir.model.fields,field_description:github_connector.field_github_organization_serie____last_update +#: model:ir.model.fields,field_description:github_connector.field_github_repository____last_update +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch____last_update +#: model:ir.model.fields,field_description:github_connector.field_github_team____last_update +#: model:ir.model.fields,field_description:github_connector.field_github_team_partner____last_update +#: model:ir.model.fields,field_description:github_connector.field_github_team_repository____last_update +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository____last_update +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team____last_update +#: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model____last_update +msgid "Last Modified on" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_abstract_github_model__github_last_sync_date +#: model:ir.model.fields,field_description:github_connector.field_github_organization__github_last_sync_date +#: model:ir.model.fields,field_description:github_connector.field_github_repository__github_last_sync_date +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__github_last_sync_date +#: model:ir.model.fields,field_description:github_connector.field_github_team__github_last_sync_date +#: model:ir.model.fields,field_description:github_connector.field_res_partner__github_last_sync_date +#: model:ir.model.fields,field_description:github_connector.field_res_users__github_last_sync_date +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__github_last_sync_date +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__github_last_sync_date +msgid "Last Sync Date with Github" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__write_uid +#: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__write_uid +#: model:ir.model.fields,field_description:github_connector.field_github_repository__write_uid +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__write_uid +#: model:ir.model.fields,field_description:github_connector.field_github_team__write_uid +#: model:ir.model.fields,field_description:github_connector.field_github_team_partner__write_uid +#: model:ir.model.fields,field_description:github_connector.field_github_team_repository__write_uid +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__write_uid +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__write_uid +#: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__write_date +#: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__write_date +#: model:ir.model.fields,field_description:github_connector.field_github_repository__write_date +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__write_date +#: model:ir.model.fields,field_description:github_connector.field_github_team__write_date +#: model:ir.model.fields,field_description:github_connector.field_github_team_partner__write_date +#: model:ir.model.fields,field_description:github_connector.field_github_team_repository__write_date +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__write_date +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__write_date +#: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model__write_date +msgid "Last Updated on" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_abstract_github_model__github_write_date +#: model:ir.model.fields,field_description:github_connector.field_github_organization__github_write_date +#: model:ir.model.fields,field_description:github_connector.field_github_repository__github_write_date +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__github_write_date +#: model:ir.model.fields,field_description:github_connector.field_github_team__github_write_date +#: model:ir.model.fields,field_description:github_connector.field_res_partner__github_write_date +#: model:ir.model.fields,field_description:github_connector.field_res_users__github_write_date +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__github_write_date +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__github_write_date +msgid "Last Write Date on Github" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_team_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_res_partner_form +msgid "Light Sync" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_wizard_load_github_model_form +msgid "Load From Github" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_wizard_load_github_model +msgid "Load from Github Wizard" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__local_path +msgid "Local Path" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__location +msgid "Location" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields.selection,name:github_connector.selection__github_team_partner__role__maintainer +msgid "Maintainer" +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/abstract_github_model.py:0 +#: code:addons/github_connector/models/github.py:0 +#, python-format +msgid "Maximum attempts reached." +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_kanban +msgid "Mb" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_team_partner__partner_id +#: model:ir.model.fields.selection,name:github_connector.selection__github_team_partner__role__member +msgid "Member" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_github_team_partner_from_team +#: model:ir.model.fields,field_description:github_connector.field_github_organization__member_ids +#: model:ir.model.fields,field_description:github_connector.field_github_team__partner_ids +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__partner_ids +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_team_form +msgid "Members" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_team_form +msgid "Members Sync." +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__name +#: model:ir.model.fields,field_description:github_connector.field_github_repository__name +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__name +#: model:ir.model.fields,field_description:github_connector.field_github_team__name +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__name +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__name +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_search +msgid "Name" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_search +msgid "Name or Description" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_search +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_team_search +msgid "Name or Github Name" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository__repository_branch_qty +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__repository_branch_qty +msgid "Number of Branches" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__member_qty +#: model:ir.model.fields,field_description:github_connector.field_github_team__partner_qty +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__partner_qty +msgid "Number of Members" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_res_partner__organization_qty +#: model:ir.model.fields,field_description:github_connector.field_res_users__organization_qty +msgid "Number of Organizations" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__repository_qty +#: model:ir.model.fields,field_description:github_connector.field_github_team__repository_qty +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__repository_qty +msgid "Number of Repositories" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__organization_serie_qty +msgid "Number of Series" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__team_qty +#: model:ir.model.fields,field_description:github_connector.field_github_repository__team_qty +#: model:ir.model.fields,field_description:github_connector.field_res_partner__github_team_qty +#: model:ir.model.fields,field_description:github_connector.field_res_users__github_team_qty +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__team_qty +msgid "Number of Teams" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__organization_id +#: model:ir.model.fields,field_description:github_connector.field_github_repository__organization_id +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__organization_id +#: model:ir.model.fields,field_description:github_connector.field_github_team__organization_id +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__organization_id +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__organization_id +#: model:ir.model.fields.selection,name:github_connector.selection__wizard_load_github_model__github_type__organization +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_search +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_search +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_team_search +msgid "Organization" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__name +msgid "Organization Name" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__organization_serie_id +msgid "Organization Serie" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__organization_serie_ids +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +msgid "Organization Series" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_github_organization +#: model:ir.model.fields,field_description:github_connector.field_res_partner__organization_ids +#: model:ir.model.fields,field_description:github_connector.field_res_users__organization_ids +#: model:ir.ui.menu,name:github_connector.menu_github_organization +#: model_terms:ir.ui.view,arch_db:github_connector.view_res_partner_form +msgid "Organizations" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_team__parent_id +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__parent_id +msgid "Parent Team" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_team_repository__permission +msgid "Permission" +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/abstract_github_model.py:0 +#, python-format +msgid "" +"Please add 'github_login' and 'github_password' in Odoo configuration file." +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_team__privacy +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__privacy +msgid "Privacy" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields.selection,name:github_connector.selection__github_team_repository__permission__read +msgid "Read" +msgstr "" + +#. module: github_connector +#: model:ir.ui.menu,name:github_connector.menu_reporting +msgid "Reports" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_github_repository +#: model:ir.actions.act_window,name:github_connector.action_github_team_repository_from_team +#: model:ir.model.fields,field_description:github_connector.field_github_organization__repository_ids +#: model:ir.model.fields,field_description:github_connector.field_github_team__repository_ids +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__repository_ids +#: model:ir.ui.menu,name:github_connector.menu_github_repository +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_team_form +msgid "Repositories" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +msgid "Repositories Sync." +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__repository_id +#: model:ir.model.fields,field_description:github_connector.field_github_team_repository__repository_id +#: model:ir.model.fields.selection,name:github_connector.selection__wizard_load_github_model__github_type__repository +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_search +msgid "Repository" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_github_repository_branch +#: model:ir.ui.menu,name:github_connector.menu_github_repository_branch +msgid "Repository Branches" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_team_form +msgid "Repository Sync." +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_team_partner__role +msgid "Role" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields.selection,name:github_connector.selection__github_team__privacy__secret +#: model:ir.model.fields.selection,name:github_connector.selection__wizard_create_team__privacy__secret +msgid "Secret" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__sequence +msgid "Sequence" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__sequence_serie +msgid "Sequence Serie" +msgstr "" + +#. module: github_connector +#: model:ir.model.constraint,message:github_connector.constraint_github_organization_serie_sequence_organization_uniq +msgid "Sequence serie must be unique by organization." +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_search +msgid "Serie" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,help:github_connector.field_github_organization__ignored_repository_names +msgid "" +"Set here repository names you want to ignore. One repository per line. If set, the repositories will be created, but branches synchronization and source code download will be disabled. Exemple:\n" +"purchase-workflow\n" +"OCB\n" +"OpenUpgrade\n" +msgstr "" + +#. module: github_connector +#: model:ir.ui.menu,name:github_connector.menu_github_settings +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +msgid "Settings" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__size +msgid "Size (Byte) " +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__mb_size +msgid "Size (Megabyte)" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_github_size_by_serie +#: model:ir.ui.menu,name:github_connector.menu_size_by_serie +msgid "Sizes by Serie" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__state +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_search +msgid "State" +msgstr "" + +#. module: github_connector +#: model:ir.ui.menu,name:github_connector.menu_wizard_load_github_model +msgid "Sync Object" +msgstr "" + +#. module: github_connector +#: model:ir.actions.server,name:github_connector.cron_update_organization_ir_actions_server +#: model:ir.cron,cron_name:github_connector.cron_update_organization +#: model:ir.cron,name:github_connector.cron_update_organization +msgid "Synchronize All Organizations and Teams" +msgstr "" + +#. module: github_connector +#: model:ir.actions.server,name:github_connector.cron_update_branch_list_ir_actions_server +#: model:ir.cron,cron_name:github_connector.cron_update_branch_list +#: model:ir.cron,name:github_connector.cron_update_branch_list +msgid "Synchronize Branches List for All Repositories" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_github_team_repository_from_repository +#: model:ir.model.fields,field_description:github_connector.field_github_team_partner__team_id +#: model:ir.model.fields,field_description:github_connector.field_github_team_repository__team_id +msgid "Team" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__wizard_partner_ids +msgid "Team Members" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__wizard_repository_ids +msgid "Team Repositories" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_github_team +#: model:ir.actions.act_window,name:github_connector.action_github_team_partner_from_partner +#: model:ir.model.fields,field_description:github_connector.field_github_organization__team_ids +#: model:ir.model.fields,field_description:github_connector.field_github_repository__team_ids +#: model:ir.model.fields,field_description:github_connector.field_res_partner__github_team_ids +#: model:ir.model.fields,field_description:github_connector.field_res_users__github_team_ids +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__team_ids +#: model:ir.ui.menu,name:github_connector.menu_github_team +#: model_terms:ir.ui.view,arch_db:github_connector.view_res_partner_form +msgid "Teams" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +msgid "Teams Sync." +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +msgid "Technical Settings" +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/github.py:0 +#, python-format +msgid "" +"The call to '%s' failed:\n" +"- Status Code: %d\n" +"- Reason: %s" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,help:github_connector.field_github_team__privacy +#: model:ir.model.fields,help:github_connector.field_wizard_create_team__privacy +msgid "" +"The level of privacy this team should have. Can be one of:\n" +"* secret - only visible to organization owners and members of this team.\n" +"* closed - visible to all members of this organization." +msgstr "" + +#. module: github_connector +#: model:ir.model.fields.selection,name:github_connector.selection__github_repository_branch__state__to_analyze +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_search +msgid "To Analyze" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields.selection,name:github_connector.selection__github_repository_branch__state__to_download +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_search +msgid "To Download" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_tree +msgid "Total" +msgstr "" + +#. module: github_connector +#: model:ir.model.constraint,message:github_connector.constraint_res_partner_github_login_uniq +msgid "Two different partners cannot have the same Github Login" +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/github.py:0 +#, python-format +msgid "" +"Unable to realize the current operation. Possible reasons:\n" +" * You try to create a duplicated item\n" +" * Some of the arguments are incorrect" +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/github.py:0 +#, python-format +msgid "" +"Unable to realize the current operation. The login '%s' does not have the " +"correct access rights." +msgstr "" + +#. module: github_connector +#: model:ir.model.fields.selection,name:github_connector.selection__github_team_repository__permission__undefined +msgid "Undefined" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model__child_update +msgid "Update Child Objects" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_tree +msgid "Update Source Code" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_tree +msgid "Update Source Code Analyzis" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields.selection,name:github_connector.selection__wizard_load_github_model__github_type__user +msgid "User" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_res_partner +#: model:ir.ui.menu,name:github_connector.menu_res_partner +msgid "Users" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository__website +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__website +msgid "Website" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__website_url +msgid "Website URL" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_wizard_create_repository +msgid "Wizard Create Repository" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_wizard_create_team +msgid "Wizard Create Team" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_wizard_load_github_model +msgid "Wizard Load Github Model" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields.selection,name:github_connector.selection__github_team_repository__permission__write +msgid "Write" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_wizard_create_repository_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_wizard_create_team_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_wizard_load_github_model_form +msgid "or" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +msgid "organization_serie_ids" +msgstr "" + +#. module: github_connector +#: code:addons/github_connector/models/github_repository_branch.py:0 +#, python-format +msgid "source_code_local_path should be defined in your configuration file" +msgstr "" diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index 49d8cec6..ccac7b52 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -8,7 +8,7 @@ from datetime import datetime from subprocess import check_output -from odoo import _, api, exceptions, fields, models, modules, tools +from odoo import _, addons, api, exceptions, fields, models, tools from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -110,8 +110,8 @@ def __init__(self, pool, cr): source_path, e, ) - if source_path and source_path not in modules.module.ad_paths: - modules.module.ad_paths.append(source_path) + if source_path and source_path not in addons.__path__: + addons.__path__.append(source_path) super().__init__(pool, cr) # Action Section From 7764d1a6c242c7f8850ad1d40d1f081b5de9886a Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Tue, 7 Jul 2020 16:55:51 +0200 Subject: [PATCH 33/72] [FIX] github_connector: Proper GitHub URL for repository branches Fixes #52 --- github_connector/models/github_repository_branch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index ccac7b52..454b2858 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -348,6 +348,6 @@ def _compute_github_url(self): for branch in self: branch.github_url = "https://github.com/{}/{}/tree/{}".format( branch.organization_id.github_login, - branch.repository_id.complete_name, + branch.repository_id.name, branch.name, ) From 692bf9c62e0d8cd127ef537d8c4bda66aa9a6356 Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Wed, 8 Jul 2020 08:55:45 +0200 Subject: [PATCH 34/72] [FIX] github_connector: Fix branch complete name Continuation of 6cc412a, needed for folder structure. Fixes #52 --- github_connector/models/github_repository_branch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index 454b2858..320348e2 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -276,7 +276,7 @@ def _analyze_code(self): def _compute_complete_name(self): for branch in self: branch.complete_name = ( - branch.repository_id.complete_name + "/" + branch.name + branch.repository_id.name + "/" + branch.name ) @api.depends("size") From 5f299027488128df8114c38da5ef556f8e82663d Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Wed, 8 Jul 2020 09:00:48 +0200 Subject: [PATCH 35/72] [FIX] black --- github_connector/models/github_repository_branch.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index 320348e2..33cf2792 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -275,9 +275,7 @@ def _analyze_code(self): @api.depends("name", "repository_id.name") def _compute_complete_name(self): for branch in self: - branch.complete_name = ( - branch.repository_id.name + "/" + branch.name - ) + branch.complete_name = branch.repository_id.name + "/" + branch.name @api.depends("size") def _compute_mb_size(self): From e15481d685fb4f1e252491bd8f691418d776814d Mon Sep 17 00:00:00 2001 From: Carlos Roca Date: Tue, 28 Jul 2020 10:54:10 +0200 Subject: [PATCH 36/72] [IMP] github_connector: Added the option to authenticate with tokens --- github_connector/README.rst | 41 +++++---- github_connector/__manifest__.py | 2 +- github_connector/i18n/github_connector.pot | 3 +- .../models/abstract_github_model.py | 20 +++-- github_connector/models/github.py | 71 ++++++---------- .../models/github_repository_branch.py | 5 +- github_connector/readme/CONFIGURE.rst | 17 ++++ github_connector/readme/CONTRIBUTORS.rst | 2 + github_connector/readme/ROADMAP.rst | 12 +-- github_connector/readme/USAGE.rst | 10 --- .../static/description/index.html | 84 +++++++++++-------- 11 files changed, 141 insertions(+), 126 deletions(-) diff --git a/github_connector/README.rst b/github_connector/README.rst index e1e31e1a..a54e4502 100644 --- a/github_connector/README.rst +++ b/github_connector/README.rst @@ -49,9 +49,16 @@ Once installed, you have to: Note: make sure that Odoo process has read / write access on that folder + * ``github_token = your_github_access_token`` + +or + * ``github_login = your_github_login`` * ``github_password = your_github_password`` +Note: if token and login/password are provided, the token will be used. +The login/password auth will be deprecated by GitHub in the future. + #. Go to 'Settings' / 'Technical' / 'Parameters' / 'System Parameters' and define the following values: @@ -70,6 +77,16 @@ Note: make sure that Odoo process has read / write access on that folder groups. The members of this group will have the possibility to run Github synchronization. +Technical Information +~~~~~~~~~~~~~~~~~~~~~ + +This module provides 4 crons that you can enable: + +* Synchronize All Organizations and Teams (``cron_update_organization``) +* Synchronize Branches List for All repositories (``cron_update_branch_list``) +* Download Source Code for All Github Branches (``cron_download_code``) +* Analyze Source Code for All Github Branches (``cron_analyze_code``) + Usage ===== @@ -209,16 +226,6 @@ This module provides several reports .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/reporting_sizes_by_serie.png -Technical Information -~~~~~~~~~~~~~~~~~~~~~ - -This module provides 4 crons that you can enable: - -* Synchronize All Organizations and Teams (``cron_update_organization``) -* Synchronize Branches List for All repositories (``cron_update_branch_list``) -* Download Source Code for All Github Branches (``cron_download_code``) -* Analyze Source Code for All Github Branches (``cron_analyze_code``) - Known issues / Roadmap ====================== @@ -230,14 +237,14 @@ Known issues / Roadmap * Possible improvements: -1. Create a new module github_connector_website, that could display - teams / repositories / branches informations for non logged users. + 1. Create a new module github_connector_website, that could display + teams / repositories / branches informations for non logged users. -2. Analyze commits (author, quantity by series, etc...): - this feature has been partially implemented in a V8.0 PR. + 2. Analyze commits (author, quantity by series, etc...): + this feature has been partially implemented in a V8.0 PR. -3. Synchronize Pull Request, Issues, Comments: - this feature has been partially implemented in a V8.0 PR. + 3. Synchronize Pull Request, Issues, Comments: + this feature has been partially implemented in a V8.0 PR. * Refactor the github connector: @@ -280,9 +287,11 @@ Contributors * Enrique Martín (enriquemartin@digital5.es) * `Tecnativa `_:", + * Pedro M. Baeza * Vicent Cubells * Alexandre Díaz * Ernesto Tejeda + * Carlos Roca Maintainers ~~~~~~~~~~~ diff --git a/github_connector/__manifest__.py b/github_connector/__manifest__.py index 27a160e8..45e0aa5a 100644 --- a/github_connector/__manifest__.py +++ b/github_connector/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Github Connector", "summary": "Synchronize information from Github repositories", - "version": "13.0.1.0.0", + "version": "13.0.2.0.0", "category": "Connector", "license": "AGPL-3", "author": "Odoo Community Association (OCA), " "GRAP, Akretion, " "Tecnativa", diff --git a/github_connector/i18n/github_connector.pot b/github_connector/i18n/github_connector.pot index b827834e..9c72a920 100644 --- a/github_connector/i18n/github_connector.pot +++ b/github_connector/i18n/github_connector.pot @@ -808,7 +808,8 @@ msgstr "" #: code:addons/github_connector/models/abstract_github_model.py:0 #, python-format msgid "" -"Please add 'github_login' and 'github_password' in Odoo configuration file." +"Please add the couple 'github_login' and 'github_password' or 'github_token'" +" in Odoo configuration file." msgstr "" #. module: github_connector diff --git a/github_connector/models/abstract_github_model.py b/github_connector/models/abstract_github_model.py index 111a40f6..8152c0fd 100644 --- a/github_connector/models/abstract_github_model.py +++ b/github_connector/models/abstract_github_model.py @@ -276,22 +276,24 @@ def _update_from_github_data(self, data): item.write(to_write) def get_github_connector(self, github_type): - if not tools.config.get("github_login") or not tools.config.get( + no_login = not tools.config.get("github_login") or not tools.config.get( "github_password" - ): + ) + no_token = not tools.config.get("github_token") + if no_login and no_token: raise exceptions.Warning( _( - "Please add 'github_login' and 'github_password' " - "in Odoo configuration file." + "Please add the couple 'github_login' and 'github_password'" + " or 'github_token'" + " in Odoo configuration file." ) ) return Github( github_type, - login=tools.config["github_login"], - password=tools.config["github_password"], - max_try=int( - self.sudo().env["ir.config_parameter"].get_param("github.max_try", 1) - ), + tools.config.get("github_login", ""), + tools.config.get("github_password", ""), + int(self.sudo().env["ir.config_parameter"].get_param("github.max_try")), + tools.config.get("github_token", ""), ) def create_in_github(self, model_obj): diff --git a/github_connector/models/github.py b/github_connector/models/github.py index b6028046..e3f20591 100644 --- a/github_connector/models/github.py +++ b/github_connector/models/github.py @@ -8,7 +8,7 @@ import logging import requests -from requests.auth import HTTPBasicAuth +from requests.auth import AuthBase, HTTPBasicAuth from odoo import _, exceptions @@ -52,12 +52,14 @@ class Github(object): - def __init__(self, github_type, login, password, max_try): + def __init__(self, github_type, login, password, max_try, token=None): super().__init__() self.github_type = github_type - self.login = login - self.password = password self.max_try = max_try + if token: + self.auth = HTTPTokenAuth(token) + else: + self.auth = HTTPBasicAuth(login, password) def _build_url(self, arguments, url_type, page): arguments = arguments and arguments or {} @@ -72,13 +74,6 @@ def _build_url(self, arguments, url_type, page): ) + "per_page=%d&page=%d" % (_MAX_NUMBER_REQUEST, page) return complete_url - def get_http_url(self): - """ Returns the http url to github with the identifications - :rtype: string - """ - identification = ":".join([self.login, self.password]) - return "https://{}@github.com/".format(identification) - def list(self, arguments): page = 1 datas = [] @@ -94,12 +89,16 @@ def get_by_url(self, url, call_type, data=False): _logger.info("Calling %s" % url) for i in range(self.max_try): try: - request_func = self.get_request_function(call_type) - response = request_func(url, data) - break + if call_type == "get": + response = requests.get(url, auth=self.auth) + break + elif call_type == "post": + json_data = json.dumps(data) + response = requests.post(url, auth=self.auth, data=json_data) + break except Exception as err: _logger.warning( - "URL Call Error. %d/%d. URL: %s", i, self.max_try, err.__str__() + "URL Call Error. %d/%d. URL: %s", i, self.max_try, err.__str__(), ) else: raise exceptions.Warning(_("Maximum attempts reached.")) @@ -136,36 +135,6 @@ def get_by_url(self, url, call_type, data=False): ) return response.json() - def get_request_function(self, call_type): - """ Return the request function to use depending on the call_type and the - identification type. - - - :param str call_type: CRUD method. Can be get or post. - :rtype: callable - """ - supported_crud_methods = ("get", "post") - msg = "`{}` is not a supported CRUD method. Use one of the following {}".format( - call_type, supported_crud_methods - ) - assert call_type in supported_crud_methods, msg - # We want the same signature for all the functions returned to ease the usage. - # The caller should not have to # consider cases. Cases are handled here. - - auth = HTTPBasicAuth(self.login, self.password) - - def get(u, _): - return requests.get(u, auth=auth) - - def post(u, d): - json_data = json.dumps(d) - return requests.post(u, auth=auth, data=json_data) - - if call_type == "get": - return get - - return post - def get(self, arguments, by_id=False, page=None): url = self._build_url( arguments, by_id and "url_get_by_id" or "url_get_by_name", page @@ -177,3 +146,15 @@ def create(self, arguments, data): url = self._build_url(arguments, "url_create", None) res = self.get_by_url(url, "post", data) return res + + +class HTTPTokenAuth(AuthBase): + + header_format_str = "token {}" + + def __init__(self, token): + self.token = token + + def __call__(self, request): + request.headers["Authorization"] = self.header_format_str.format(self.token) + return request diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index 33cf2792..89686959 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -11,6 +11,8 @@ from odoo import _, addons, api, exceptions, fields, models, tools from odoo.tools.safe_eval import safe_eval +from .github import _GITHUB_URL + _logger = logging.getLogger(__name__) try: @@ -143,7 +145,6 @@ def create_or_update_from_name(self, repository_id, name): return branch def _download_code(self): - client = self.get_github_connector("") for branch in self: if not os.path.exists(branch.local_path): _logger.info("Cloning new repository into %s ..." % branch.local_path) @@ -160,7 +161,7 @@ def _download_code(self): ) command = ("git clone %s%s/%s.git -b %s %s") % ( - client.get_http_url(), + _GITHUB_URL, branch.repository_id.organization_id.github_login, branch.repository_id.name, branch.name, diff --git a/github_connector/readme/CONFIGURE.rst b/github_connector/readme/CONFIGURE.rst index 3ee12f55..b04aed32 100644 --- a/github_connector/readme/CONFIGURE.rst +++ b/github_connector/readme/CONFIGURE.rst @@ -7,9 +7,16 @@ Once installed, you have to: Note: make sure that Odoo process has read / write access on that folder + * ``github_token = your_github_access_token`` + +or + * ``github_login = your_github_login`` * ``github_password = your_github_password`` +Note: if token and login/password are provided, the token will be used. +The login/password auth will be deprecated by GitHub in the future. + #. Go to 'Settings' / 'Technical' / 'Parameters' / 'System Parameters' and define the following values: @@ -27,3 +34,13 @@ Note: make sure that Odoo process has read / write access on that folder #. Go to your(s) user(s) form to add them in the new 'Connector Github Manager' groups. The members of this group will have the possibility to run Github synchronization. + +Technical Information +~~~~~~~~~~~~~~~~~~~~~ + +This module provides 4 crons that you can enable: + +* Synchronize All Organizations and Teams (``cron_update_organization``) +* Synchronize Branches List for All repositories (``cron_update_branch_list``) +* Download Source Code for All Github Branches (``cron_download_code``) +* Analyze Source Code for All Github Branches (``cron_analyze_code``) diff --git a/github_connector/readme/CONTRIBUTORS.rst b/github_connector/readme/CONTRIBUTORS.rst index 74cf144c..68a8ae22 100644 --- a/github_connector/readme/CONTRIBUTORS.rst +++ b/github_connector/readme/CONTRIBUTORS.rst @@ -4,6 +4,8 @@ * Enrique Martín (enriquemartin@digital5.es) * `Tecnativa `_:", + * Pedro M. Baeza * Vicent Cubells * Alexandre Díaz * Ernesto Tejeda + * Carlos Roca diff --git a/github_connector/readme/ROADMAP.rst b/github_connector/readme/ROADMAP.rst index 4d287554..8f000a5e 100644 --- a/github_connector/readme/ROADMAP.rst +++ b/github_connector/readme/ROADMAP.rst @@ -6,14 +6,14 @@ * Possible improvements: -1. Create a new module github_connector_website, that could display - teams / repositories / branches informations for non logged users. + 1. Create a new module github_connector_website, that could display + teams / repositories / branches informations for non logged users. -2. Analyze commits (author, quantity by series, etc...): - this feature has been partially implemented in a V8.0 PR. + 2. Analyze commits (author, quantity by series, etc...): + this feature has been partially implemented in a V8.0 PR. -3. Synchronize Pull Request, Issues, Comments: - this feature has been partially implemented in a V8.0 PR. + 3. Synchronize Pull Request, Issues, Comments: + this feature has been partially implemented in a V8.0 PR. * Refactor the github connector: diff --git a/github_connector/readme/USAGE.rst b/github_connector/readme/USAGE.rst index 73ecc74d..785222ca 100644 --- a/github_connector/readme/USAGE.rst +++ b/github_connector/readme/USAGE.rst @@ -133,13 +133,3 @@ This module provides several reports **Sizes by Serie** .. image:: ../static/description/reporting_sizes_by_serie.png - -Technical Information -~~~~~~~~~~~~~~~~~~~~~ - -This module provides 4 crons that you can enable: - -* Synchronize All Organizations and Teams (``cron_update_organization``) -* Synchronize Branches List for All repositories (``cron_update_branch_list``) -* Download Source Code for All Github Branches (``cron_download_code``) -* Analyze Source Code for All Github Branches (``cron_analyze_code``) diff --git a/github_connector/static/description/index.html b/github_connector/static/description/index.html index 18a6d00f..77733837 100644 --- a/github_connector/static/description/index.html +++ b/github_connector/static/description/index.html @@ -378,17 +378,19 @@

Github Connector

Table of contents

-

Usage

+

Usage

-

Initial upload from Github

+

Initial upload from Github

To fetch information from Github, you have to:

  1. go to ‘Github’ / ‘Settings’ / ‘Sync Object’

    @@ -462,7 +482,7 @@

    Initial upload from Github

-

Select branches to download

+

Select branches to download

This setting will prevent to download undesired branches, downloading only main branches (releases):

    @@ -481,7 +501,7 @@

    Select branches to download

-

Team / members synchronization

+

Team / members synchronization

You can synchronize members teams:

  1. Go to ‘Teams’ / tree view / ‘Actions’ / ‘Update from Github’.

    @@ -497,7 +517,7 @@

    Team / members synchronization

-

Repositories synchronization

+

Repositories synchronization

You can synchronize the branches of your repositories:

  1. Go to ‘Repositories’ / @@ -511,7 +531,7 @@

    Repositories synchronization

-

Fetching the source code

+

Fetching the source code

Finally, you can download locally the source code of all your branches:

  1. Go to ‘Repository Branches’ / tree view / ‘Actions’ / ‘Download and Analyse Source Code’.

    @@ -523,7 +543,7 @@

    Fetching the source code

-

Data creation in Github

+

Data creation in Github

You have the possibility to creates two items in Github directly from Odoo

  1. Teams:

    @@ -547,7 +567,7 @@

    Data creation in Github

-

Note

+

Note

Analysis in this module is basic: for the time being, it just gives branches size.

Nevertheless, you can develop an extra Odoo Custom module to extend analysis @@ -556,35 +576,25 @@

Note

contain Odoo modules.

-

Reporting

+

Reporting

This module provides several reports

Branches by Serie

https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/reporting_branches_by_serie.png

Sizes by Serie

https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/reporting_sizes_by_serie.png
-
-

Technical Information

-

This module provides 4 crons that you can enable:

-
    -
  • Synchronize All Organizations and Teams (cron_update_organization)
  • -
  • Synchronize Branches List for All repositories (cron_update_branch_list)
  • -
  • Download Source Code for All Github Branches (cron_download_code)
  • -
  • Analyze Source Code for All Github Branches (cron_analyze_code)
  • -
-

Known issues / Roadmap

-
    -
  • For the time being, Github API doesn’t provide some informations that are -available by the classic UI, that includes:
      +
        +
      • For the time being, Github API doesn’t provide some informations that are +available by the classic UI, that includes:

        +
        1. team hierarchy: the field is present in the model github_team.parent_id, but unused.
      • -
      • Possible improvements:
      • -
      +
    1. Possible improvements:

      1. Create a new module github_connector_website, that could display teams / repositories / branches informations for non logged users.
      2. @@ -593,7 +603,7 @@

        Known issues / Roadmap

      3. Synchronize Pull Request, Issues, Comments: this feature has been partially implemented in a V8.0 PR.
      -
        +
      • Refactor the github connector:

        A python library called PyGitHub is available. It could be interesting to use it, instead of using custom code. However, this lib doesn’t provide @@ -632,9 +642,11 @@

        Contributors

      • Benoît GUILLOT (benoit.guillot@akretion.com)
      • Enrique Martín (enriquemartin@digital5.es)
      • Tecnativa:”,
          +
        • Pedro M. Baeza
        • Vicent Cubells
        • Alexandre Díaz
        • Ernesto Tejeda
        • +
        • Carlos Roca
      From 817fdd9e1d5e136b035cb14d32fdc565e3d34040 Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Wed, 5 Aug 2020 10:46:28 +0200 Subject: [PATCH 37/72] [FIX] github_connector: Don't fail on empty local path on tests As we can't create configuration file on Travis and other CI environments easily, better to not fail in such case, that is not relevant for the tests done. --- github_connector/__manifest__.py | 2 +- github_connector/models/github_repository_branch.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/github_connector/__manifest__.py b/github_connector/__manifest__.py index 45e0aa5a..d3d42d84 100644 --- a/github_connector/__manifest__.py +++ b/github_connector/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Github Connector", "summary": "Synchronize information from Github repositories", - "version": "13.0.2.0.0", + "version": "13.0.2.0.1", "category": "Connector", "license": "AGPL-3", "author": "Odoo Community Association (OCA), " "GRAP, Akretion, " "Tecnativa", diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index 89686959..58834fdb 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -100,7 +100,7 @@ class GithubRepository(models.Model): # Init Section def __init__(self, pool, cr): source_path = tools.config.get("source_code_local_path", False) - if not os.path.exists(source_path): + if source_path and not os.path.exists(source_path): try: os.makedirs(source_path) except Exception as e: @@ -293,7 +293,7 @@ def _compute_organization_serie_id(self): @api.depends("complete_name") def _compute_local_path(self): source_path = tools.config.get("source_code_local_path", False) - if not source_path: + if not source_path and not tools.config["test_enable"]: raise exceptions.Warning( _( "source_code_local_path should be defined in your " From 231b00016a4ef65fecad6093ec892fefc2ef9d80 Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Wed, 5 Aug 2020 11:26:21 +0200 Subject: [PATCH 38/72] [FIX] github_connector: Can't join path with boolean Change False to "" --- github_connector/models/github_repository_branch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index 58834fdb..b0b18bdd 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -292,7 +292,7 @@ def _compute_organization_serie_id(self): @api.depends("complete_name") def _compute_local_path(self): - source_path = tools.config.get("source_code_local_path", False) + source_path = tools.config.get("source_code_local_path", "") if not source_path and not tools.config["test_enable"]: raise exceptions.Warning( _( From b208afbf8738ccf6fb2d83ff302b0176d8d6f3ca Mon Sep 17 00:00:00 2001 From: Carlos Roca Date: Mon, 10 Aug 2020 10:29:56 +0200 Subject: [PATCH 39/72] [IMP] github_connector: Added the SOURCE_CODE_LOCAL_PATH environment variable --- github_connector/README.rst | 3 +++ github_connector/__manifest__.py | 8 +++++-- .../demo/github_repository_branch_demo.xml | 23 +++++++++++++++++++ .../models/github_repository_branch.py | 9 ++++++-- github_connector/readme/CONFIGURE.rst | 3 +++ .../static/description/index.html | 2 ++ 6 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 github_connector/demo/github_repository_branch_demo.xml diff --git a/github_connector/README.rst b/github_connector/README.rst index a54e4502..eed6f6a6 100644 --- a/github_connector/README.rst +++ b/github_connector/README.rst @@ -47,6 +47,9 @@ Once installed, you have to: * ``source_code_local_path = /workspace/source_code/`` +Note: you can define the route as environment variable using the key +SOURCE_CODE_LOCAL_PATH + Note: make sure that Odoo process has read / write access on that folder * ``github_token = your_github_access_token`` diff --git a/github_connector/__manifest__.py b/github_connector/__manifest__.py index d3d42d84..c1590fb6 100644 --- a/github_connector/__manifest__.py +++ b/github_connector/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Github Connector", "summary": "Synchronize information from Github repositories", - "version": "13.0.2.0.1", + "version": "13.0.2.1.0", "category": "Connector", "license": "AGPL-3", "author": "Odoo Community Association (OCA), " "GRAP, Akretion, " "Tecnativa", @@ -31,7 +31,11 @@ "wizards/view_wizard_create_team.xml", "wizards/view_wizard_create_repository.xml", ], - "demo": ["demo/github_organization.xml", "demo/github_organization_serie.xml"], + "demo": [ + "demo/github_organization.xml", + "demo/github_organization_serie.xml", + "demo/github_repository_branch_demo.xml", + ], "installable": True, "external_dependencies": {"python": ["GitPython"]}, } diff --git a/github_connector/demo/github_repository_branch_demo.xml b/github_connector/demo/github_repository_branch_demo.xml new file mode 100644 index 00000000..e5234696 --- /dev/null +++ b/github_connector/demo/github_repository_branch_demo.xml @@ -0,0 +1,23 @@ + + + + + + Organization 1 + organization1_login + + + + repository_1 + + + + + branch_1 + + + + diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index b0b18bdd..cbe33d99 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -99,7 +99,7 @@ class GithubRepository(models.Model): # Init Section def __init__(self, pool, cr): - source_path = tools.config.get("source_code_local_path", False) + source_path = self._get_source_path() if source_path and not os.path.exists(source_path): try: os.makedirs(source_path) @@ -116,6 +116,11 @@ def __init__(self, pool, cr): addons.__path__.append(source_path) super().__init__(pool, cr) + def _get_source_path(self): + return tools.config.get("source_code_local_path", "") or os.environ.get( + "SOURCE_CODE_LOCAL_PATH", "" + ) + # Action Section def button_download_code(self): return self._download_code() @@ -292,7 +297,7 @@ def _compute_organization_serie_id(self): @api.depends("complete_name") def _compute_local_path(self): - source_path = tools.config.get("source_code_local_path", "") + source_path = self._get_source_path() if not source_path and not tools.config["test_enable"]: raise exceptions.Warning( _( diff --git a/github_connector/readme/CONFIGURE.rst b/github_connector/readme/CONFIGURE.rst index b04aed32..925cd31f 100644 --- a/github_connector/readme/CONFIGURE.rst +++ b/github_connector/readme/CONFIGURE.rst @@ -5,6 +5,9 @@ Once installed, you have to: * ``source_code_local_path = /workspace/source_code/`` +Note: you can define the route as environment variable using the key +SOURCE_CODE_LOCAL_PATH + Note: make sure that Odoo process has read / write access on that folder * ``github_token = your_github_access_token`` diff --git a/github_connector/static/description/index.html b/github_connector/static/description/index.html index 77733837..d31ff40a 100644 --- a/github_connector/static/description/index.html +++ b/github_connector/static/description/index.html @@ -413,6 +413,8 @@

      Configuration

+

Note: you can define the route as environment variable using the key +SOURCE_CODE_LOCAL_PATH

Note: make sure that Odoo process has read / write access on that folder

    From 8c97e001ccc3a8578f6945d2a2a6f77b3e95d45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Fri, 19 Feb 2021 16:29:13 +0100 Subject: [PATCH 40/72] [FIX] github_connector: Prevent error when archive records and later process try to create again + Add test to check it --- github_connector/README.rst | 1 + github_connector/__manifest__.py | 2 +- .../models/abstract_github_model.py | 10 +++++--- github_connector/readme/CONTRIBUTORS.rst | 1 + .../static/description/index.html | 1 + github_connector/tests/__init__.py | 4 ++++ .../tests/test_github_connector.py | 24 +++++++++++++++++++ 7 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 github_connector/tests/__init__.py create mode 100644 github_connector/tests/test_github_connector.py diff --git a/github_connector/README.rst b/github_connector/README.rst index eed6f6a6..15939bfe 100644 --- a/github_connector/README.rst +++ b/github_connector/README.rst @@ -295,6 +295,7 @@ Contributors * Alexandre Díaz * Ernesto Tejeda * Carlos Roca + * Víctor Martínez Maintainers ~~~~~~~~~~~ diff --git a/github_connector/__manifest__.py b/github_connector/__manifest__.py index c1590fb6..98cedb08 100644 --- a/github_connector/__manifest__.py +++ b/github_connector/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Github Connector", "summary": "Synchronize information from Github repositories", - "version": "13.0.2.1.0", + "version": "13.0.2.1.1", "category": "Connector", "license": "AGPL-3", "author": "Odoo Community Association (OCA), " "GRAP, Akretion, " "Tecnativa", diff --git a/github_connector/models/abstract_github_model.py b/github_connector/models/abstract_github_model.py index 8152c0fd..fd762323 100644 --- a/github_connector/models/abstract_github_model.py +++ b/github_connector/models/abstract_github_model.py @@ -152,13 +152,15 @@ def get_from_id_or_create(self, data, extra_data=None): extra_data = extra_data and extra_data or {} # We try to search object by id - existing_object = self.search([("github_id_external", "=", data["id"])]) + existing_object = self.with_context(active_test=False).search( + [("github_id_external", "=", data["id"])] + ) if existing_object: return existing_object # We try to see if object exist by name (instead of id) if self._github_login_field and self._github_login_field in data: - existing_object = self.search( + existing_object = self.with_context(active_test=False).search( [("github_login", "=", data[self._github_login_field])] ) if len(existing_object) == 1: @@ -201,7 +203,9 @@ def create_from_name(self, name): github_connector = self.get_github_connector(self.github_type()) res = github_connector.get([name]) # search if ID doesn't exist in database - current_object = self.search([("github_id_external", "=", res["id"])]) + current_object = self.with_context(active_test=False).search( + [("github_id_external", "=", res["id"])] + ) if not current_object: # Create the object return self._create_from_github_data(res) diff --git a/github_connector/readme/CONTRIBUTORS.rst b/github_connector/readme/CONTRIBUTORS.rst index 68a8ae22..9c69dcaf 100644 --- a/github_connector/readme/CONTRIBUTORS.rst +++ b/github_connector/readme/CONTRIBUTORS.rst @@ -9,3 +9,4 @@ * Alexandre Díaz * Ernesto Tejeda * Carlos Roca + * Víctor Martínez diff --git a/github_connector/static/description/index.html b/github_connector/static/description/index.html index d31ff40a..cb7f8968 100644 --- a/github_connector/static/description/index.html +++ b/github_connector/static/description/index.html @@ -649,6 +649,7 @@

    Contributors

  • Alexandre Díaz
  • Ernesto Tejeda
  • Carlos Roca
  • +
  • Víctor Martínez
diff --git a/github_connector/tests/__init__.py b/github_connector/tests/__init__.py new file mode 100644 index 00000000..8d01db1d --- /dev/null +++ b/github_connector/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2021 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_github_connector diff --git a/github_connector/tests/test_github_connector.py b/github_connector/tests/test_github_connector.py new file mode 100644 index 00000000..41f2a971 --- /dev/null +++ b/github_connector/tests/test_github_connector.py @@ -0,0 +1,24 @@ +# Copyright 2021 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests import common + + +class TestGithubConnector(common.SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.model = cls.env["res.partner"] + cls.model._need_individual_call = False + + def test_partner_get_from_id_or_create(self): + data = {"id": "10", "name": "Mr Odoo", "url": "https://github.com"} + partner = self.model.get_from_id_or_create(data) + self.assertEqual(partner.name, data["name"]) + # Check create process not really create new record + res = self.model.get_from_id_or_create(data) + self.assertEqual(partner.id, res.id) + # Try to archive record and try to create again + partner.active = False + res = self.model.get_from_id_or_create(data) + self.assertEqual(partner.id, res.id) From ea794e8951ad9cd6d6ef379a19ca95e4bef20091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Wed, 16 Sep 2020 12:13:10 +0200 Subject: [PATCH 41/72] [IMP] github_connector: Code analysis --- github_connector/README.rst | 47 +++- github_connector/__init__.py | 1 + github_connector/__manifest__.py | 9 +- .../demo/github_analysis_rule_demo.xml | 27 ++ .../demo/github_analysis_rule_group_demo.xml | 10 + .../demo/github_organization_serie.xml | 10 + github_connector/i18n/github_connector.pot | 234 ++++++++++++++++++ github_connector/models/__init__.py | 3 + .../models/github_analysis_rule.py | 45 ++++ .../models/github_analysis_rule_group.py | 11 + .../models/github_analysis_rule_info.py | 34 +++ .../models/github_organization.py | 5 + github_connector/models/github_repository.py | 3 + .../models/github_repository_branch.py | 80 ++++++ github_connector/readme/DESCRIPTION.rst | 1 + github_connector/readme/INSTALL.rst | 9 + github_connector/readme/ROADMAP.rst | 4 - github_connector/readme/USAGE.rst | 29 +++ github_connector/report/__init__.py | 1 + ...thub_repository_branch_rule_info_report.py | 89 +++++++ ...epository_branch_rule_info_report_view.xml | 46 ++++ github_connector/security/ir.model.access.csv | 5 + github_connector/security/res_groups.xml | 5 +- ...hub_repository_branch_rule_info_report.png | Bin 0 -> 53717 bytes .../static/description/index.html | 111 ++++++--- github_connector/tests/__init__.py | 3 +- .../tests/test_github_analysis_rule.py | 152 ++++++++++++ github_connector/views/action.xml | 10 + github_connector/views/menu.xml | 14 ++ .../views/view_github_analysis_rule.xml | 51 ++++ .../views/view_github_analysis_rule_group.xml | 29 +++ .../views/view_github_organization.xml | 4 + .../views/view_github_repository.xml | 4 + .../views/view_github_repository_branch.xml | 29 +++ 34 files changed, 1066 insertions(+), 49 deletions(-) create mode 100644 github_connector/demo/github_analysis_rule_demo.xml create mode 100644 github_connector/demo/github_analysis_rule_group_demo.xml create mode 100644 github_connector/models/github_analysis_rule.py create mode 100644 github_connector/models/github_analysis_rule_group.py create mode 100644 github_connector/models/github_analysis_rule_info.py create mode 100644 github_connector/readme/INSTALL.rst create mode 100644 github_connector/report/__init__.py create mode 100644 github_connector/report/github_repository_branch_rule_info_report.py create mode 100644 github_connector/report/github_repository_branch_rule_info_report_view.xml create mode 100644 github_connector/static/description/github_repository_branch_rule_info_report.png create mode 100644 github_connector/tests/test_github_analysis_rule.py create mode 100644 github_connector/views/view_github_analysis_rule.xml create mode 100644 github_connector/views/view_github_analysis_rule_group.xml diff --git a/github_connector/README.rst b/github_connector/README.rst index 15939bfe..b763c352 100644 --- a/github_connector/README.rst +++ b/github_connector/README.rst @@ -31,12 +31,26 @@ This module allows you to: * Fetch into Odoo Code structure information from Github (Repositories, Branches) * Download source code from Github +* Analyze repository code from rules previously created **Table of contents** .. contents:: :local: +Installation +============ + +To install this addon, you need to install some python dependencies + +.. code-block:: bash + + ``sudo pip install PyGitHub`` + ``sudo pip install pygount`` + ``sudo pip install pathspec`` + +Analysis source code is generated by https://github.com/roskakori/pygount + Configuration ============= @@ -180,6 +194,31 @@ Finally, you can download locally the source code of all your branches: .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_repository_branch_list.png +Analysis source code +~~~~~~~~~~~~~~~~~~~~~~~~ + +It's possible to create custom analysis rules that relate to a GitHub organization, GitHub repository and/or GitHub repository branch to analyze code. + +#. Go to 'Settings' / 'Analysis rule groups' and create records that allow to organize the rules + +#. Go to 'Settings' / 'Analysis rules' and create rules, for example: + + 1. Name: All code, Group: General, Paths: ``*`` + 2. Name: Python code, Group: General, Paths: ``*.py`` + 3. Name: Xml code, Group: General, Paths: ``*.xml`` + 4. Name: Repository 1, Group: Custom, Paths: /path/ + +Note: Paths field in 'Analysis rule' allow to put multiple paths for line, path format is according to https://git-scm.com/docs/gitignore#_pattern_format + +#. Go to *GitHub > GitHub Community > Organizations* and define Analysis rules (optional) +#. Go to *GitHub > GitHub Repository > Repositories* and define Analysis rules (optional) +#. Go to *GitHub > GitHub Repository > Repository Branches* and define Analysis rules (optional) + +Analysis source code is executed when 'Update Source Code Analysis' button in some 'Repository Branch', get all the Analysis rules (Repository + Organization) and analyze code and generate info about it +Other option to Analysis source code is in cron called 'Analyze Source Code for All Github Branches' + +You can see in 'Repository Branch' / 'Code Analysis' the info obtained from analysis rules. + Data creation in Github ~~~~~~~~~~~~~~~~~~~~~~~ @@ -229,6 +268,10 @@ This module provides several reports .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/reporting_sizes_by_serie.png +**Repository branch analysis rule** + +.. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_repository_branch_rule_info_report.png + Known issues / Roadmap ====================== @@ -257,10 +300,6 @@ Known issues / Roadmap API calls. For example, updating a repository should call before a call to the parent organization (The current module is so faster). -.. code-block:: bash - - ``sudo pip install PyGitHub`` - Bug Tracker =========== diff --git a/github_connector/__init__.py b/github_connector/__init__.py index aee8895e..cf6083cf 100644 --- a/github_connector/__init__.py +++ b/github_connector/__init__.py @@ -1,2 +1,3 @@ from . import models +from . import report from . import wizards diff --git a/github_connector/__manifest__.py b/github_connector/__manifest__.py index 98cedb08..e4c0e2f0 100644 --- a/github_connector/__manifest__.py +++ b/github_connector/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Github Connector", "summary": "Synchronize information from Github repositories", - "version": "13.0.2.1.1", + "version": "13.0.3.0.0", "category": "Connector", "license": "AGPL-3", "author": "Odoo Community Association (OCA), " "GRAP, Akretion, " "Tecnativa", @@ -23,19 +23,24 @@ "views/view_github_team_repository.xml", "views/action.xml", "views/view_res_partner.xml", + "views/view_github_analysis_rule.xml", + "views/view_github_analysis_rule_group.xml", "views/view_github_organization.xml", "views/view_github_repository.xml", "views/view_github_repository_branch.xml", "views/view_github_team.xml", "views/menu.xml", + "report/github_repository_branch_rule_info_report_view.xml", "wizards/view_wizard_create_team.xml", "wizards/view_wizard_create_repository.xml", ], "demo": [ + "demo/github_analysis_rule_group_demo.xml", + "demo/github_analysis_rule_demo.xml", "demo/github_organization.xml", "demo/github_organization_serie.xml", "demo/github_repository_branch_demo.xml", ], "installable": True, - "external_dependencies": {"python": ["GitPython"]}, + "external_dependencies": {"python": ["GitPython", "pygount", "pathspec"]}, } diff --git a/github_connector/demo/github_analysis_rule_demo.xml b/github_connector/demo/github_analysis_rule_demo.xml new file mode 100644 index 00000000..5decd0bd --- /dev/null +++ b/github_connector/demo/github_analysis_rule_demo.xml @@ -0,0 +1,27 @@ + + + + + Python files + + *.py + + + XML files + + *.xml + + + JS files + + *.js + + + Test files + + /tests/*.py + + diff --git a/github_connector/demo/github_analysis_rule_group_demo.xml b/github_connector/demo/github_analysis_rule_group_demo.xml new file mode 100644 index 00000000..c4723242 --- /dev/null +++ b/github_connector/demo/github_analysis_rule_group_demo.xml @@ -0,0 +1,10 @@ + + + + + Odoo modules + + diff --git a/github_connector/demo/github_organization_serie.xml b/github_connector/demo/github_organization_serie.xml index f123092e..9db7cb96 100644 --- a/github_connector/demo/github_organization_serie.xml +++ b/github_connector/demo/github_organization_serie.xml @@ -45,4 +45,14 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 12.0 + + 10 + 13.0 + + + + 11 + 14.0 + + diff --git a/github_connector/i18n/github_connector.pot b/github_connector/i18n/github_connector.pot index 9c72a920..44f816b2 100644 --- a/github_connector/i18n/github_connector.pot +++ b/github_connector/i18n/github_connector.pot @@ -13,11 +13,55 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" +#. module: github_connector +#: model:ir.model,name:github_connector.model_github_repository_branch_rule_info +msgid " Github Repository Branch Rule Info" +msgstr "" + #. module: github_connector #: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_tree msgid "# Branches" msgstr "" +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_info_mixin__code_count +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__code_count +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__code_count +msgid "# Code" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_info_mixin__documentation_count +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__documentation_count +msgid "# Doc." +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__documentation_count +msgid "# Documentation" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_info_mixin__empty_count +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__empty_count +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__empty_count +msgid "# Empty" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_info_mixin__string_count +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__string_count +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__string_count +msgid "# String" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_info_mixin__total_count +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__total_count +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__total_count +msgid "# Total" +msgstr "" + #. module: github_connector #: code:addons/github_connector/models/github.py:0 #, python-format @@ -78,6 +122,46 @@ msgstr "" msgid "Admin" msgstr "" +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_info_mixin__analysis_rule_id +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__analysis_rule_id +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__analysis_rule_id +msgid "Analysis Rule" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_organization__analysis_rule_ids +#: model:ir.model.fields,field_description:github_connector.field_github_repository__analysis_rule_ids +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__analysis_rule_ids +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__analysis_rule_ids +msgid "Analysis Rules" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__analysis_rule_info_ids +msgid "Analysis Rules (info)" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_github_analysis_rule +msgid "Analysis rule" +msgstr "" + +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_github_analysis_rule_group +msgid "Analysis rule group" +msgstr "" + +#. module: github_connector +#: model:ir.ui.menu,name:github_connector.menu_github_analysis_rule_group +msgid "Analysis rule groups" +msgstr "" + +#. module: github_connector +#: model:ir.ui.menu,name:github_connector.menu_github_analysis_rule +msgid "Analysis rules" +msgstr "" + #. module: github_connector #: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form #: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_tree @@ -148,6 +232,13 @@ msgstr "" msgid "Closed" msgstr "" +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_form +msgid "Code Analysis" +msgstr "" + #. module: github_connector #: model:ir.model.fields,field_description:github_connector.field_github_repository__color #: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__color @@ -228,10 +319,13 @@ msgid "Create in Github" msgstr "" #. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule__create_uid +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_group__create_uid #: model:ir.model.fields,field_description:github_connector.field_github_organization__create_uid #: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__create_uid #: model:ir.model.fields,field_description:github_connector.field_github_repository__create_uid #: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__create_uid +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__create_uid #: model:ir.model.fields,field_description:github_connector.field_github_team__create_uid #: model:ir.model.fields,field_description:github_connector.field_github_team_partner__create_uid #: model:ir.model.fields,field_description:github_connector.field_github_team_repository__create_uid @@ -242,10 +336,13 @@ msgid "Created by" msgstr "" #. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule__create_date +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_group__create_date #: model:ir.model.fields,field_description:github_connector.field_github_organization__create_date #: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__create_date #: model:ir.model.fields,field_description:github_connector.field_github_repository__create_date #: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__create_date +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__create_date #: model:ir.model.fields,field_description:github_connector.field_github_team__create_date #: model:ir.model.fields,field_description:github_connector.field_github_team_partner__create_date #: model:ir.model.fields,field_description:github_connector.field_github_team_repository__create_date @@ -255,6 +352,12 @@ msgstr "" msgid "Created on" msgstr "" +#. module: github_connector +#: model:ir.model.fields,help:github_connector.field_github_analysis_rule__paths +#: model:ir.model.fields,help:github_connector.field_github_repository_branch_rule_info_report__paths +msgid "Define with pathspec especification" +msgstr "" + #. module: github_connector #: model:ir.model.fields,field_description:github_connector.field_github_organization__description #: model:ir.model.fields,field_description:github_connector.field_github_repository__description @@ -266,10 +369,15 @@ msgstr "" #. module: github_connector #: model:ir.model.fields,field_description:github_connector.field_abstract_github_model__display_name +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule__display_name +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_group__display_name +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_info_mixin__display_name #: model:ir.model.fields,field_description:github_connector.field_github_organization__display_name #: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__display_name #: model:ir.model.fields,field_description:github_connector.field_github_repository__display_name #: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__display_name +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__display_name +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__display_name #: model:ir.model.fields,field_description:github_connector.field_github_team__display_name #: model:ir.model.fields,field_description:github_connector.field_github_team_partner__display_name #: model:ir.model.fields,field_description:github_connector.field_github_team_repository__display_name @@ -383,6 +491,21 @@ msgstr "" msgid "Github" msgstr "" +#. module: github_connector +#: model:ir.model,name:github_connector.model_github_analysis_rule +msgid "Github Analysis Rule" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_github_analysis_rule_group +msgid "Github Analysis Rule Group" +msgstr "" + +#. module: github_connector +#: model:ir.model,name:github_connector.model_github_analysis_rule_info_mixin +msgid "Github Analysis Rule Mixin" +msgstr "" + #. module: github_connector #: model:ir.ui.menu,name:github_connector.menu_github_community msgid "Github Community" @@ -432,6 +555,11 @@ msgstr "" msgid "Github Repository Branch" msgstr "" +#. module: github_connector +#: model:ir.model,name:github_connector.model_github_repository_branch_rule_info_report +msgid "Github Repository Branch Rule Info Report" +msgstr "" + #. module: github_connector #: model:ir.model,name:github_connector.model_github_team msgid "Github Team" @@ -488,6 +616,14 @@ msgstr "" msgid "Github organization" msgstr "" +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule__group_id +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_info_mixin__group_id +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__group_id +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__group_id +msgid "Group" +msgstr "" + #. module: github_connector #: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_search #: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_search @@ -502,10 +638,15 @@ msgstr "" #. module: github_connector #: model:ir.model.fields,field_description:github_connector.field_abstract_github_model__id +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule__id +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_group__id +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_info_mixin__id #: model:ir.model.fields,field_description:github_connector.field_github_organization__id #: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__id #: model:ir.model.fields,field_description:github_connector.field_github_repository__id #: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__id +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__id +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__id #: model:ir.model.fields,field_description:github_connector.field_github_team__id #: model:ir.model.fields,field_description:github_connector.field_github_team_partner__id #: model:ir.model.fields,field_description:github_connector.field_github_team_repository__id @@ -559,10 +700,15 @@ msgstr "" #. module: github_connector #: model:ir.model.fields,field_description:github_connector.field_abstract_github_model____last_update +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule____last_update +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_group____last_update +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_info_mixin____last_update #: model:ir.model.fields,field_description:github_connector.field_github_organization____last_update #: model:ir.model.fields,field_description:github_connector.field_github_organization_serie____last_update #: model:ir.model.fields,field_description:github_connector.field_github_repository____last_update #: model:ir.model.fields,field_description:github_connector.field_github_repository_branch____last_update +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info____last_update +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report____last_update #: model:ir.model.fields,field_description:github_connector.field_github_team____last_update #: model:ir.model.fields,field_description:github_connector.field_github_team_partner____last_update #: model:ir.model.fields,field_description:github_connector.field_github_team_repository____last_update @@ -586,10 +732,13 @@ msgid "Last Sync Date with Github" msgstr "" #. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule__write_uid +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_group__write_uid #: model:ir.model.fields,field_description:github_connector.field_github_organization__write_uid #: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__write_uid #: model:ir.model.fields,field_description:github_connector.field_github_repository__write_uid #: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__write_uid +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__write_uid #: model:ir.model.fields,field_description:github_connector.field_github_team__write_uid #: model:ir.model.fields,field_description:github_connector.field_github_team_partner__write_uid #: model:ir.model.fields,field_description:github_connector.field_github_team_repository__write_uid @@ -600,10 +749,13 @@ msgid "Last Updated by" msgstr "" #. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule__write_date +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_group__write_date #: model:ir.model.fields,field_description:github_connector.field_github_organization__write_date #: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__write_date #: model:ir.model.fields,field_description:github_connector.field_github_repository__write_date #: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__write_date +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__write_date #: model:ir.model.fields,field_description:github_connector.field_github_team__write_date #: model:ir.model.fields,field_description:github_connector.field_github_team_partner__write_date #: model:ir.model.fields,field_description:github_connector.field_github_team_repository__write_date @@ -693,9 +845,12 @@ msgid "Members Sync." msgstr "" #. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule__name +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_group__name #: model:ir.model.fields,field_description:github_connector.field_github_organization_serie__name #: model:ir.model.fields,field_description:github_connector.field_github_repository__name #: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__name +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__name #: model:ir.model.fields,field_description:github_connector.field_github_team__name #: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__name #: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__name @@ -784,6 +939,11 @@ msgstr "" msgid "Organization Series" msgstr "" +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__organization_serie_id +msgid "Organization serie" +msgstr "" + #. module: github_connector #: model:ir.actions.act_window,name:github_connector.action_github_organization #: model:ir.model.fields,field_description:github_connector.field_res_partner__organization_ids @@ -799,6 +959,12 @@ msgstr "" msgid "Parent Team" msgstr "" +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule__paths +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__paths +msgid "Paths" +msgstr "" + #. module: github_connector #: model:ir.model.fields,field_description:github_connector.field_github_team_repository__permission msgid "Permission" @@ -846,12 +1012,19 @@ msgstr "" #. module: github_connector #: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__repository_id +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__repository_id #: model:ir.model.fields,field_description:github_connector.field_github_team_repository__repository_id #: model:ir.model.fields.selection,name:github_connector.selection__wizard_load_github_model__github_type__repository #: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_search msgid "Repository" msgstr "" +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__repository_branch_id +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__repository_branch_id +msgid "Repository Branch" +msgstr "" + #. module: github_connector #: model:ir.actions.act_window,name:github_connector.action_github_repository_branch #: model:ir.ui.menu,name:github_connector.menu_github_repository_branch @@ -863,11 +1036,31 @@ msgstr "" msgid "Repository Sync." msgstr "" +#. module: github_connector +#: model:ir.actions.act_window,name:github_connector.action_github_repository_branch_rule_info_report +#: model:ir.ui.menu,name:github_connector.menu_action_github_repository_branch_rule_info_report +#: model_terms:ir.ui.view,arch_db:github_connector.action_github_repository_branch_rule_info_report_graph +#: model_terms:ir.ui.view,arch_db:github_connector.action_github_repository_branch_rule_info_report_pivot +msgid "Repository branch analysis rule" +msgstr "" + #. module: github_connector #: model:ir.model.fields,field_description:github_connector.field_github_team_partner__role msgid "Role" msgstr "" +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +msgid "Rule info (Repository)" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_analysis_rule_info_mixin__scanned_files +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info__scanned_files +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch_rule_info_report__scanned_files +msgid "Scanned files" +msgstr "" + #. module: github_connector #: model:ir.model.fields.selection,name:github_connector.selection__github_team__privacy__secret #: model:ir.model.fields.selection,name:github_connector.selection__wizard_create_team__privacy__secret @@ -986,6 +1179,7 @@ msgid "Teams Sync." msgstr "" #. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_analysis_rule_form #: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form msgid "Technical Settings" msgstr "" @@ -1025,6 +1219,36 @@ msgstr "" msgid "Total" msgstr "" +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +msgid "Total code" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +msgid "Total documentation" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +msgid "Total empty" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +msgid "Total scanned" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +msgid "Total string" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_form +msgid "Total total" +msgstr "" + #. module: github_connector #: model:ir.model.constraint,message:github_connector.constraint_res_partner_github_login_uniq msgid "Two different partners cannot have the same Github Login" @@ -1111,6 +1335,16 @@ msgstr "" msgid "Write" msgstr "" +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_analysis_rule_form +msgid "You can see reference documentation and some examples in:" +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_analysis_rule_form +msgid "https://git-scm.com/docs/gitignore#_pattern_format" +msgstr "" + #. module: github_connector #: model_terms:ir.ui.view,arch_db:github_connector.view_wizard_create_repository_form #: model_terms:ir.ui.view,arch_db:github_connector.view_wizard_create_team_form diff --git a/github_connector/models/__init__.py b/github_connector/models/__init__.py index dbacfe6d..cecd2499 100644 --- a/github_connector/models/__init__.py +++ b/github_connector/models/__init__.py @@ -3,6 +3,9 @@ from . import res_partner +from . import github_analysis_rule +from . import github_analysis_rule_group +from . import github_analysis_rule_info from . import github_organization from . import github_organization_serie from . import github_repository diff --git a/github_connector/models/github_analysis_rule.py b/github_connector/models/github_analysis_rule.py new file mode 100644 index 00000000..ff5162e5 --- /dev/null +++ b/github_connector/models/github_analysis_rule.py @@ -0,0 +1,45 @@ +# Copyright 2020 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import pathspec +from pygount import SourceAnalysis + +from odoo import fields, models + + +class GithubAnalysisRule(models.Model): + _name = "github.analysis.rule" + _description = "Github Analysis Rule" + + name = fields.Char(string="Name", required=True) + group_id = fields.Many2one( + string="Group", comodel_name="github.analysis.rule.group", required=True + ) + """ + Example paths: https://git-scm.com/docs/gitignore#_pattern_format + """ + paths = fields.Text( + string="Paths", + help="Define with pathspec especification", + default="*", + required=True, + ) + + def _get_matches(self, path): + """ + Get all matches from rule paths (multiple per line allow in rule) + in a local path + """ + spec = pathspec.PathSpec.from_lines("gitwildmatch", self.paths.splitlines()) + return spec.match_tree(path) + + def _analysis_file(self, path): + file_res = SourceAnalysis.from_file(path, "") + return { + "path": file_res._path, + "language": file_res._language, + "code": file_res._code, + "documentation": file_res._documentation, + "empty": file_res._empty, + "string": file_res._string, + } diff --git a/github_connector/models/github_analysis_rule_group.py b/github_connector/models/github_analysis_rule_group.py new file mode 100644 index 00000000..487ad6ad --- /dev/null +++ b/github_connector/models/github_analysis_rule_group.py @@ -0,0 +1,11 @@ +# Copyright 2020 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class GithubAnalysisRule(models.Model): + _name = "github.analysis.rule.group" + _description = "Github Analysis Rule Group" + + name = fields.Char(string="Name", required=True) diff --git a/github_connector/models/github_analysis_rule_info.py b/github_connector/models/github_analysis_rule_info.py new file mode 100644 index 00000000..c0006dcb --- /dev/null +++ b/github_connector/models/github_analysis_rule_info.py @@ -0,0 +1,34 @@ +# Copyright 2020 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + + +class GithubAnalysisRuleInfoMixin(models.AbstractModel): + _name = "github.analysis.rule.info.mixin" + _description = "Github Analysis Rule Mixin" + + analysis_rule_id = fields.Many2one( + string="Analysis Rule", comodel_name="github.analysis.rule", + ) + group_id = fields.Many2one( + string="Group", related="analysis_rule_id.group_id", readonly=True + ) + code_count = fields.Integer(string="# Code") + documentation_count = fields.Integer(string="# Doc.") + empty_count = fields.Integer(string="# Empty") + string_count = fields.Integer(string="# String") + total_count = fields.Integer( + string="# Total", store=True, compute="_compute_total_count" + ) + scanned_files = fields.Integer(string="Scanned files") + + @api.depends("code_count", "documentation_count", "empty_count", "string_count") + def _compute_total_count(self): + for item in self: + item.total_count = ( + item.code_count + + item.documentation_count + + item.empty_count + + item.string_count + ) diff --git a/github_connector/models/github_organization.py b/github_connector/models/github_organization.py index 19032d82..82aba864 100644 --- a/github_connector/models/github_organization.py +++ b/github_connector/models/github_organization.py @@ -1,4 +1,5 @@ # Copyright (C) 2016-Today: Odoo Community Association (OCA) +# Copyright 2020 Tecnativa - Víctor Martínez # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -87,6 +88,10 @@ class GithubOrganization(models.Model): ci_url_pattern = fields.Char(string="CI URL Pattern") + analysis_rule_ids = fields.Many2many( + string="Analysis Rules", comodel_name="github.analysis.rule" + ) + # Overloadable Section @api.model def get_conversion_dict(self): diff --git a/github_connector/models/github_repository.py b/github_connector/models/github_repository.py index 3155a8eb..3491e7a8 100644 --- a/github_connector/models/github_repository.py +++ b/github_connector/models/github_repository.py @@ -78,6 +78,9 @@ class GithubRepository(models.Model): color = fields.Integer( string="Color Index", multi="ignore", compute="_compute_ignore" ) + analysis_rule_ids = fields.Many2many( + string="Analysis Rules", comodel_name="github.analysis.rule" + ) # Compute Section @api.depends("organization_id.ignored_repository_names") diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index cbe33d99..2041ebd9 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -1,4 +1,5 @@ # Copyright (C) 2016-Today: Odoo Community Association (OCA) +# Copyright 2020 Tecnativa - Víctor Martínez # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -96,6 +97,14 @@ class GithubRepository(models.Model): github_url = fields.Char( string="Github URL", store=True, compute="_compute_github_url" ) + analysis_rule_ids = fields.Many2many( + string="Analysis Rules", comodel_name="github.analysis.rule" + ) + analysis_rule_info_ids = fields.One2many( + string="Analysis Rules (info)", + comodel_name="github.repository.branch.rule.info", + inverse_name="repository_branch_id", + ) # Init Section def __init__(self, pool, cr): @@ -229,6 +238,16 @@ def analyze_code_one(self): """ self.ensure_one() path = self.local_path + # github_analysis_rule + rule_ids = ( + self.repository_id.organization_id.analysis_rule_ids + + self.repository_id.analysis_rule_ids + + self.analysis_rule_ids + ) + for rule_id in rule_ids: + self._delete_analysis_rule_model_info(rule_id) + for vals in self._prepare_analysis_rule_info_vals(rule_id): + self.env[self._prepare_analysis_rule_model_info(rule_id)].create(vals) # Compute Files Sizes size = 0 for file_path in self._get_analyzable_files(path): @@ -277,6 +296,55 @@ def _analyze_code(self): ) return True + def _prepare_analysis_rule_model_info(self, analysis_rule_id): + """Define model data info that override with other addons""" + return "github.repository.branch.rule.info" + + def _delete_analysis_rule_model_info(self, analysis_rule_id): + """Remove existing info data to create new records""" + self.env[self._prepare_analysis_rule_model_info(analysis_rule_id)].search( + [ + ("analysis_rule_id", "=", analysis_rule_id.id), + ("repository_branch_id", "=", self.id), + ] + ).sudo().unlink() + + def _prepare_analysis_rule_info_vals(self, analysis_rule_id): + """Prepare info vals""" + res = self._operation_analysis_rule_id(analysis_rule_id) + return [ + { + "analysis_rule_id": analysis_rule_id.id, + "repository_branch_id": self.id, + "code_count": res["code"], + "documentation_count": res["documentation"], + "empty_count": res["empty"], + "string_count": res["string"], + "scanned_files": len(res["paths"]), + } + ] + + def _operation_analysis_rule_id(self, analysis_rule_id): + """This function allow to override with other addons that need + to change this analysis + """ + res = { + "paths": [], + "code": 0, + "documentation": 0, + "empty": 0, + "string": 0, + } + for match in analysis_rule_id._get_matches(self.local_path): + # _logger.info("analyse file %s "% match) + res_file = analysis_rule_id._analysis_file(self.local_path + "/" + match) + res["paths"].append(res_file["path"]) + # define values + for key in ("code", "documentation", "empty", "string"): + res[key] += res_file[key] + + return res + # Compute Section @api.depends("name", "repository_id.name") def _compute_complete_name(self): @@ -355,3 +423,15 @@ def _compute_github_url(self): branch.repository_id.name, branch.name, ) + + +class GithubRepositoryBranchRuleInfo(models.TransientModel): + _inherit = "github.analysis.rule.info.mixin" + _name = "github.repository.branch.rule.info" + _description = " Github Repository Branch Rule Info" + + repository_branch_id = fields.Many2one( + string="Repository Branch", + comodel_name="github.repository.branch", + ondelete="cascade", + ) diff --git a/github_connector/readme/DESCRIPTION.rst b/github_connector/readme/DESCRIPTION.rst index e98227fc..f3cea8e6 100644 --- a/github_connector/readme/DESCRIPTION.rst +++ b/github_connector/readme/DESCRIPTION.rst @@ -4,3 +4,4 @@ This module allows you to: * Fetch into Odoo Code structure information from Github (Repositories, Branches) * Download source code from Github +* Analyze repository code from rules previously created diff --git a/github_connector/readme/INSTALL.rst b/github_connector/readme/INSTALL.rst new file mode 100644 index 00000000..d291d83c --- /dev/null +++ b/github_connector/readme/INSTALL.rst @@ -0,0 +1,9 @@ +To install this addon, you need to install some python dependencies + +.. code-block:: bash + + ``sudo pip install PyGitHub`` + ``sudo pip install pygount`` + ``sudo pip install pathspec`` + +Analysis source code is generated by https://github.com/roskakori/pygount diff --git a/github_connector/readme/ROADMAP.rst b/github_connector/readme/ROADMAP.rst index 8f000a5e..4ba9db9f 100644 --- a/github_connector/readme/ROADMAP.rst +++ b/github_connector/readme/ROADMAP.rst @@ -22,7 +22,3 @@ good access to child object, generating for the time being, unnecessary API calls. For example, updating a repository should call before a call to the parent organization (The current module is so faster). - -.. code-block:: bash - - ``sudo pip install PyGitHub`` diff --git a/github_connector/readme/USAGE.rst b/github_connector/readme/USAGE.rst index 785222ca..891d897d 100644 --- a/github_connector/readme/USAGE.rst +++ b/github_connector/readme/USAGE.rst @@ -85,6 +85,31 @@ Finally, you can download locally the source code of all your branches: .. image:: ../static/description/github_repository_branch_list.png +Analysis source code +~~~~~~~~~~~~~~~~~~~~~~~~ + +It's possible to create custom analysis rules that relate to a GitHub organization, GitHub repository and/or GitHub repository branch to analyze code. + +#. Go to 'Settings' / 'Analysis rule groups' and create records that allow to organize the rules + +#. Go to 'Settings' / 'Analysis rules' and create rules, for example: + + 1. Name: All code, Group: General, Paths: ``*`` + 2. Name: Python code, Group: General, Paths: ``*.py`` + 3. Name: Xml code, Group: General, Paths: ``*.xml`` + 4. Name: Repository 1, Group: Custom, Paths: /path/ + +Note: Paths field in 'Analysis rule' allow to put multiple paths for line, path format is according to https://git-scm.com/docs/gitignore#_pattern_format + +#. Go to *GitHub > GitHub Community > Organizations* and define Analysis rules (optional) +#. Go to *GitHub > GitHub Repository > Repositories* and define Analysis rules (optional) +#. Go to *GitHub > GitHub Repository > Repository Branches* and define Analysis rules (optional) + +Analysis source code is executed when 'Update Source Code Analysis' button in some 'Repository Branch', get all the Analysis rules (Repository + Organization) and analyze code and generate info about it +Other option to Analysis source code is in cron called 'Analyze Source Code for All Github Branches' + +You can see in 'Repository Branch' / 'Code Analysis' the info obtained from analysis rules. + Data creation in Github ~~~~~~~~~~~~~~~~~~~~~~~ @@ -133,3 +158,7 @@ This module provides several reports **Sizes by Serie** .. image:: ../static/description/reporting_sizes_by_serie.png + +**Repository branch analysis rule** + +.. image:: ../static/description/github_repository_branch_rule_info_report.png diff --git a/github_connector/report/__init__.py b/github_connector/report/__init__.py new file mode 100644 index 00000000..1d7ac39c --- /dev/null +++ b/github_connector/report/__init__.py @@ -0,0 +1 @@ +from . import github_repository_branch_rule_info_report diff --git a/github_connector/report/github_repository_branch_rule_info_report.py b/github_connector/report/github_repository_branch_rule_info_report.py new file mode 100644 index 00000000..2bab2157 --- /dev/null +++ b/github_connector/report/github_repository_branch_rule_info_report.py @@ -0,0 +1,89 @@ +# Copyright 2020 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models, tools + + +class GithubRepositoryBranchRuleInfoReport(models.Model): + _inherit = "github.analysis.rule" + _name = "github.repository.branch.rule.info.report" + _description = "Github Repository Branch Rule Info Report" + _auto = False + + analysis_rule_id = fields.Many2one( + string="Analysis Rule", comodel_name="github.analysis.rule", + ) + group_id = fields.Many2one( + string="Group", related="analysis_rule_id.group_id", readonly=True + ) + repository_branch_id = fields.Many2one( + string="Repository Branch", comodel_name="github.repository.branch", + ) + repository_id = fields.Many2one( + string="Repository", comodel_name="github.repository", + ) + organization_serie_id = fields.Many2one( + string="Organization serie", comodel_name="github.organization.serie", + ) + code_count = fields.Integer(string="# Code") + documentation_count = fields.Integer(string="# Documentation") + empty_count = fields.Integer(string="# Empty") + string_count = fields.Integer(string="# String") + total_count = fields.Integer(string="# Total") + scanned_files = fields.Integer(string="Scanned files") + + def _query(self, with_clause="", fields=None, groupby="", from_clause=""): + if fields is None: + fields = {} + with_ = ("WITH %s" % with_clause) if with_clause else "" + + select_ = """ + min(grbri.id) as id, + gar.id as analysis_rule_id, + garg.id as group_id, + grb.id as repository_branch_id, + gr.id as repository_id, + gos.id as organization_serie_id, + sum(grbri.code_count) as code_count, + sum(grbri.documentation_count) as documentation_count, + sum(grbri.string_count) as string_count, + sum(grbri.empty_count) as empty_count, + sum(grbri.total_count) as total_count, + sum(grbri.scanned_files) as scanned_files + """ + + from_ = ( + """ + github_repository_branch_rule_info as grbri + left join github_analysis_rule as gar on grbri.analysis_rule_id = gar.id + left join github_analysis_rule_group as garg on gar.group_id = garg.id + left join github_repository_branch as grb + on grbri.repository_branch_id = grb.id + left join github_organization_serie as gos + on grb.organization_serie_id = gos.id + left join github_repository as gr on grb.repository_id = gr.id + %s + """ + % from_clause + ) + + groupby_ = """ + gar.id, + garg.id, + grb.id, + gr.id, + gos.id %s + """ % ( + groupby + ) + + return "{} (SELECT {} FROM {} WHERE grbri.id > 0 GROUP BY {})".format( + with_, select_, from_, groupby_, + ) + + def init(self): + tools.drop_view_if_exists(self.env.cr, self._table) + # pylint: disable=E8103 + self.env.cr.execute( + """CREATE or REPLACE VIEW {} as ({})""".format(self._table, self._query()) + ) diff --git a/github_connector/report/github_repository_branch_rule_info_report_view.xml b/github_connector/report/github_repository_branch_rule_info_report_view.xml new file mode 100644 index 00000000..6ba61694 --- /dev/null +++ b/github_connector/report/github_repository_branch_rule_info_report_view.xml @@ -0,0 +1,46 @@ + + + + + github.repository.branch.rule.info.report + + + + + + + + + github.repository.branch.rule.info.report + + + + + + + + + Repository branch analysis rule + github.repository.branch.rule.info.report + pivot,graph + + + diff --git a/github_connector/security/ir.model.access.csv b/github_connector/security/ir.model.access.csv index 50db0066..03890fb9 100644 --- a/github_connector/security/ir.model.access.csv +++ b/github_connector/security/ir.model.access.csv @@ -1,8 +1,13 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_github_analysis_rule_reader,github_analysis_rule reader,model_github_analysis_rule,,1,0,0,0 +access_github_analysis_rule_manager,github_analysis_rule manager,model_github_analysis_rule,github_connector.group_github_connector_manager,1,1,1,1 +access_github_analysis_rule_group_reader,github_analysis_rule_group reader,model_github_analysis_rule_group,,1,0,0,0 +access_github_analysis_rule_group_manager,github_analysis_rule_group manager,model_github_analysis_rule_group,github_connector.group_github_connector_manager,1,1,1,1 access_github_organization_reader,github_organization reader,model_github_organization,,1,0,0,0 access_github_organization_manager,github_organization manager,model_github_organization,github_connector.group_github_connector_manager,1,1,1,1 access_github_organization_serie_reader,github_organization_serie reader,model_github_organization_serie,,1,0,0,0 access_github_organization_serie_manager,github_organization_serie manager,model_github_organization_serie,github_connector.group_github_connector_manager,1,1,1,1 +access_github_repository_branch_rule_info_report_reader,github_repository_branch_rule_info_report reader,model_github_repository_branch_rule_info_report,,1,0,0,0 access_github_repository_reader,github_repository reader,model_github_repository,,1,0,0,0 access_github_repository_manager,github_repository manager,model_github_repository,github_connector.group_github_connector_manager,1,1,1,1 access_github_repository_branch_reader,github_repository_branch reader,model_github_repository_branch,,1,0,0,0 diff --git a/github_connector/security/res_groups.xml b/github_connector/security/res_groups.xml index f81a92c3..3a0b44c3 100644 --- a/github_connector/security/res_groups.xml +++ b/github_connector/security/res_groups.xml @@ -15,7 +15,10 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). Connector Github Manager - + Hm;fPj2}0|5bbfrbP=VXCq9 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
  • 6jC%=K1FPGV!-?H8?@c7e3TqeFs3?3Dh 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 Connector
  • Fetch into Odoo Code structure information from Github (Repositories, Branches)
  • Download source code from Github
  • +
  • Analyze repository code from rules previously created
  • Table of contents

    +
    +

    Installation

    +

    To install this addon, you need to install some python dependencies

    +
    +``sudo pip install PyGitHub``
    +``sudo pip install pygount``
    +``sudo pip install pathspec``
    +
    +

    Analysis source code is generated by https://github.com/roskakori/pygount

    +
    -

    Configuration

    +

    Configuration

    Once installed, you have to:

    1. Open your odoo.conf file and add extra settings to mention Github @@ -451,7 +464,7 @@

      Configuration

    -

    Technical Information

    +

    Technical Information

    This module provides 4 crons that you can enable:

    • Synchronize All Organizations and Teams (cron_update_organization)
    • @@ -462,9 +475,9 @@

      Technical Information

    -

    Usage

    +

    Usage

    -

    Initial upload from Github

    +

    Initial upload from Github

    To fetch information from Github, you have to:

    1. go to ‘Github’ / ‘Settings’ / ‘Sync Object’

      @@ -484,7 +497,7 @@

      Initial upload from Github

    -

    Select branches to download

    +

    Select branches to download

    This setting will prevent to download undesired branches, downloading only main branches (releases):

      @@ -503,7 +516,7 @@

      Select branches to download

    -

    Team / members synchronization

    +

    Team / members synchronization

    You can synchronize members teams:

    1. Go to ‘Teams’ / tree view / ‘Actions’ / ‘Update from Github’.

      @@ -519,7 +532,7 @@

      Team / members synchronization

    -

    Repositories synchronization

    +

    Repositories synchronization

    You can synchronize the branches of your repositories:

    1. Go to ‘Repositories’ / @@ -533,7 +546,7 @@

      Repositories synchronization

    -

    Fetching the source code

    +

    Fetching the source code

    Finally, you can download locally the source code of all your branches:

    1. Go to ‘Repository Branches’ / tree view / ‘Actions’ / ‘Download and Analyse Source Code’.

      @@ -544,8 +557,33 @@

      Fetching the source code

    +
    +

    Analysis source code

    +

    It’s possible to create custom analysis rules that relate to a GitHub organization, GitHub repository and/or GitHub repository branch to analyze code.

    +
      +
    1. Go to ‘Settings’ / ‘Analysis rule groups’ and create records that allow to organize the rules
    2. +
    3. Go to ‘Settings’ / ‘Analysis rules’ and create rules, for example:
    4. +
    +
    +
      +
    1. Name: All code, Group: General, Paths: *
    2. +
    3. Name: Python code, Group: General, Paths: *.py
    4. +
    5. Name: Xml code, Group: General, Paths: *.xml
    6. +
    7. Name: Repository 1, Group: Custom, Paths: /path/
    8. +
    +
    +

    Note: Paths field in ‘Analysis rule’ allow to put multiple paths for line, path format is according to https://git-scm.com/docs/gitignore#_pattern_format

    +
      +
    1. Go to GitHub > GitHub Community > Organizations and define Analysis rules (optional)
    2. +
    3. Go to GitHub > GitHub Repository > Repositories and define Analysis rules (optional)
    4. +
    5. Go to GitHub > GitHub Repository > Repository Branches and define Analysis rules (optional)
    6. +
    +

    Analysis source code is executed when ‘Update Source Code Analysis’ button in some ‘Repository Branch’, get all the Analysis rules (Repository + Organization) and analyze code and generate info about it +Other option to Analysis source code is in cron called ‘Analyze Source Code for All Github Branches’

    +

    You can see in ‘Repository Branch’ / ‘Code Analysis’ the info obtained from analysis rules.

    +
    -

    Data creation in Github

    +

    Data creation in Github

    You have the possibility to creates two items in Github directly from Odoo

    1. Teams:

      @@ -569,7 +607,7 @@

      Data creation in Github

    -

    Note

    +

    Note

    Analysis in this module is basic: for the time being, it just gives branches size.

    Nevertheless, you can develop an extra Odoo Custom module to extend analysis @@ -578,16 +616,18 @@

    Note

    contain Odoo modules.

    -

    Reporting

    +

    Reporting

    This module provides several reports

    Branches by Serie

    https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/reporting_branches_by_serie.png

    Sizes by Serie

    https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/reporting_sizes_by_serie.png +

    Repository branch analysis rule

    +https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_repository_branch_rule_info_report.png
    -

    Known issues / Roadmap

    +

    Known issues / Roadmap

    • For the time being, Github API doesn’t provide some informations that are available by the classic UI, that includes:

      @@ -614,12 +654,9 @@

      Known issues / Roadmap

      the parent organization (The current module is so faster).

    -
    -``sudo pip install PyGitHub``
    -
    -

    Bug Tracker

    +

    Bug Tracker

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed @@ -627,9 +664,9 @@

    Bug Tracker

    Do not contact contributors directly about support or help with technical issues.

    -

    Credits

    +

    Credits

    -

    Authors

    +

    Authors

    • GRAP
    • Akretion
    • @@ -637,7 +674,7 @@

      Authors

    -

    Maintainers

    +

    Maintainers

    This module is maintained by the OCA.

    Odoo Community Association

    OCA, or the Odoo Community Association, is a nonprofit organization whose diff --git a/github_connector/tests/__init__.py b/github_connector/tests/__init__.py index 8d01db1d..09a1ce31 100644 --- a/github_connector/tests/__init__.py +++ b/github_connector/tests/__init__.py @@ -1,4 +1,5 @@ # Copyright 2021 Tecnativa - Víctor Martínez -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from . import test_github_analysis_rule from . import test_github_connector diff --git a/github_connector/tests/test_github_analysis_rule.py b/github_connector/tests/test_github_analysis_rule.py new file mode 100644 index 00000000..8329bc0a --- /dev/null +++ b/github_connector/tests/test_github_analysis_rule.py @@ -0,0 +1,152 @@ +# Copyright 2020 Tecnativa - Víctor Martínez +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo.tests.common import SavepointCase + + +class TestGithubAnalysisRule(SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.analysis_rule_group_misc = cls.env["github.analysis.rule.group"].create( + {"name": "Misc"} + ) + cls.analysis_rule_python = cls.env["github.analysis.rule"].create( + { + "name": "Python files", + "group_id": cls.analysis_rule_group_misc.id, + "paths": "**/account_analytic_project/**/*.py", + } + ) + cls.analysis_rule_xml = cls.env["github.analysis.rule"].create( + { + "name": "Xml files", + "group_id": cls.analysis_rule_group_misc.id, + "paths": "**/account_analytic_project/**/*.xml", + } + ) + cls.analysis_rule_js = cls.env["github.analysis.rule"].create( + { + "name": "Js files", + "group_id": cls.analysis_rule_group_misc.id, + "paths": "**/account_analytic_project/**/*.js", + } + ) + cls.analysis_rule_test = cls.env["github.analysis.rule"].create( + { + "name": "Test files", + "group_id": cls.analysis_rule_group_misc.id, + "paths": "/tests/*.py", + } + ) + cls.analysis_rule_ocb = cls.env["github.analysis.rule"].create( + { + "name": "OCB files (.py + .xml)", + "group_id": cls.analysis_rule_group_misc.id, + "paths": """ + *.py + *.xml + !/.*/ + """, + } + ) + cls.analysis_rule_custom = cls.env["github.analysis.rule"].create( + { + "name": "Custom", + "group_id": cls.analysis_rule_group_misc.id, + "paths": """/custom/*.py""", + } + ) + cls.organization_oca = cls.env["github.organization"].create( + { + "name": "Odoo Community Association", + "description": "The GitHub repos for all Open Source work around Odoo", + "website_url": "https://odoo-community.org/", + "github_url": "https://github.com/OCA", + "github_login": "OCA", + "analysis_rule_ids": [ + (4, cls.analysis_rule_python.id), + (4, cls.analysis_rule_xml.id), + (4, cls.analysis_rule_js.id), + ], + } + ) + cls.organization_serie_6 = cls.env["github.organization.serie"].create( + {"organization_id": cls.organization_oca.id, "sequence": 6, "name": "6.1"} + ) + cls.organization_serie_13 = cls.env["github.organization.serie"].create( + {"organization_id": cls.organization_oca.id, "sequence": 13, "name": "13.0"} + ) + cls.repository_ocb = cls.env["github.repository"].create( + { + "name": "OCB", + "organization_id": cls.organization_oca.id, + "github_login": "%s/OCB" % cls.organization_oca.github_login, + "analysis_rule_ids": [(4, cls.analysis_rule_ocb.id)], + } + ) + cls.repository_account_analytic = cls.env["github.repository"].create( + { + "name": "account-analytic", + "organization_id": cls.organization_oca.id, + "github_login": "%s/account-analytic" + % cls.organization_oca.github_login, + } + ) + # repository branch + cls.repository_ocb_branch_13 = cls.env["github.repository.branch"].create( + { + "name": cls.organization_serie_13.name, + "organization_id": cls.organization_oca.id, + "repository_id": cls.repository_ocb.id, + "organization_serie_id": cls.organization_serie_13.id, + } + ) + cls.repository_account_analytic_branch_6 = cls.env[ + "github.repository.branch" + ].create( + { + "name": cls.organization_serie_6.name, + "organization_id": cls.organization_oca.id, + "repository_id": cls.repository_account_analytic.id, + "organization_serie_id": cls.organization_serie_6.id, + "analysis_rule_ids": [(4, cls.analysis_rule_custom.id)], + } + ) + + def test_github_analysis_rule(self): + self.assertEqual(len(self.organization_oca.analysis_rule_ids), 3) + self.assertEqual(len(self.repository_ocb.analysis_rule_ids), 1) + # download + analyze_code + self.repository_account_analytic_branch_6._download_code() + self.repository_account_analytic_branch_6.analyze_code_one() + # info ids + info_ids = self.repository_account_analytic_branch_6.analysis_rule_info_ids + self.assertEqual(len(info_ids), 4) + # python info + python_info = info_ids.filtered( + lambda x: x.analysis_rule_id.id == self.analysis_rule_python.id + ) + self.assertEqual(python_info.code_count, 60) + self.assertEqual(python_info.documentation_count, 106) + self.assertEqual(python_info.empty_count, 20) + self.assertEqual(python_info.string_count, 19) + self.assertEqual(python_info.scanned_files, 4) + # xml info + xml_info = info_ids.filtered( + lambda x: x.analysis_rule_id.id == self.analysis_rule_xml.id + ) + self.assertEqual(xml_info.code_count, 35) + self.assertEqual(xml_info.documentation_count, 0) + self.assertEqual(xml_info.empty_count, 0) + self.assertEqual(xml_info.string_count, 10) + self.assertEqual(xml_info.scanned_files, 1) + # js info + js_info = info_ids.filtered( + lambda x: x.analysis_rule_id.id == self.analysis_rule_js.id + ) + self.assertEqual(js_info.code_count, 0) + self.assertEqual(js_info.documentation_count, 0) + self.assertEqual(js_info.empty_count, 0) + self.assertEqual(js_info.string_count, 0) + self.assertEqual(js_info.scanned_files, 0) diff --git a/github_connector/views/action.xml b/github_connector/views/action.xml index f51c78f6..dbe1b125 100644 --- a/github_connector/views/action.xml +++ b/github_connector/views/action.xml @@ -94,6 +94,16 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). form new + + Analysis rule + github.analysis.rule + tree,form + + + Analysis rule group + github.analysis.rule.group + tree,form + Branches by Serie diff --git a/github_connector/views/menu.xml b/github_connector/views/menu.xml index c7aa5ceb..223d8f75 100644 --- a/github_connector/views/menu.xml +++ b/github_connector/views/menu.xml @@ -85,6 +85,20 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). name="Create Repo in Github" action="action_wizard_create_repository" /> + + + + + + github.analysis.rule + + + + + + + + + github.analysis.rule + +

    + +
    +

    + +

    +
    + + + + + + + + + + + +
    +
    + + + diff --git a/github_connector/views/view_github_analysis_rule_group.xml b/github_connector/views/view_github_analysis_rule_group.xml new file mode 100644 index 00000000..cc344f8c --- /dev/null +++ b/github_connector/views/view_github_analysis_rule_group.xml @@ -0,0 +1,29 @@ + + + + + github.analysis.rule.group + + + + + + + + github.analysis.rule.group + +
    + +
    +

    + +

    +
    +
    +
    +
    +
    +
    diff --git a/github_connector/views/view_github_organization.xml b/github_connector/views/view_github_organization.xml index 7bf3dd7e..0ae19463 100644 --- a/github_connector/views/view_github_organization.xml +++ b/github_connector/views/view_github_organization.xml @@ -190,6 +190,10 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). /> + + diff --git a/github_connector/views/view_github_repository.xml b/github_connector/views/view_github_repository.xml index 8f9b19fd..c9eb1ffd 100644 --- a/github_connector/views/view_github_repository.xml +++ b/github_connector/views/view_github_repository.xml @@ -133,6 +133,10 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). /> + + diff --git a/github_connector/views/view_github_repository_branch.xml b/github_connector/views/view_github_repository_branch.xml index 70b3480d..266d0a77 100644 --- a/github_connector/views/view_github_repository_branch.xml +++ b/github_connector/views/view_github_repository_branch.xml @@ -187,6 +187,35 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + From 2c2b74fedaa83b88f6d1b0d4a47a36bd7ce5790b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Marques?= Date: Tue, 8 Jun 2021 08:18:56 +0100 Subject: [PATCH 42/72] [FIX] github_connector: Use correct error messages The error message depends on the GH auth method being used. If the user selected a token, there won't be a login to show the error in the exception thrown. This makes the error message adapt to the type of auth chosen. TT30343 --- github_connector/models/github.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/github_connector/models/github.py b/github_connector/models/github.py index e3f20591..17cc56f5 100644 --- a/github_connector/models/github.py +++ b/github_connector/models/github.py @@ -103,22 +103,26 @@ def get_by_url(self, url, call_type, data=False): else: raise exceptions.Warning(_("Maximum attempts reached.")) + if isinstance(self.auth, HTTPBasicAuth): + auth_err_msg = _("login '%s'") % self.auth.login + elif isinstance(self.auth, HTTPTokenAuth): + auth_err_msg = _("provided token") if response.status_code == _CODE_401: raise exceptions.Warning( _( - "401 - Unable to authenticate to Github with the login '%s'.\n" + "401 - Unable to authenticate to Github with the %s.\n" "You should check your credentials in the Odoo" " configuration file." ) - % self.login + % auth_err_msg ) elif response.status_code == _CODE_403: raise exceptions.Warning( _( - "Unable to realize the current operation. The login '%s'" + "Unable to realize the current operation. The %s" " does not have the correct access rights." ) - % self.login + % auth_err_msg ) elif response.status_code == _CODE_422: raise exceptions.Warning( From 9b3234ffb6117600d35e445bf74a8588ad5b371c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Marques?= Date: Tue, 8 Jun 2021 10:12:48 +0100 Subject: [PATCH 43/72] [IMP] github_connector: black, isort, prettier --- .../models/abstract_github_model.py | 34 +++++++++---------- github_connector/models/github.py | 5 ++- .../models/github_analysis_rule_info.py | 3 +- .../models/github_repository_branch.py | 3 +- ...thub_repository_branch_rule_info_report.py | 17 +++++++--- 5 files changed, 35 insertions(+), 27 deletions(-) diff --git a/github_connector/models/abstract_github_model.py b/github_connector/models/abstract_github_model.py index fd762323..aefaefd2 100644 --- a/github_connector/models/abstract_github_model.py +++ b/github_connector/models/abstract_github_model.py @@ -128,26 +128,24 @@ def full_update(self): """Override this function in models that inherit this abstract to mention which items should be synchronized from github when the user click on 'Full Update' Button""" - pass def _hook_after_github_creation(self): """Hook that will be called, after a creation in github. Override this function to add custom logic for after creation.""" - pass # Custom Public Function @api.model def get_from_id_or_create(self, data, extra_data=None): """Search if the odoo object exists in database. If yes, returns the - object. Otherwise, creates the new object. + object. Otherwise, creates the new object. - :param data: dict with github 'id' and 'url' keys - :return: The searched or created object + :param data: dict with github 'id' and 'url' keys + :return: The searched or created object - :Example: + :Example: - >>> self.env['github_organization'].get_from_id_or_create( - {'id': 7600578, 'url': 'https://api.github.com/orgs/OCA'}) + >>> self.env['github_organization'].get_from_id_or_create( + {'id': 7600578, 'url': 'https://api.github.com/orgs/OCA'}) """ extra_data = extra_data and extra_data or {} @@ -190,15 +188,15 @@ def get_from_id_or_create(self, data, extra_data=None): @api.model def create_from_name(self, name): """Call Github API, using a URL using github name. Load data and - Create Odoo object accordingly, if the odoo object doesn't exist. + Create Odoo object accordingly, if the odoo object doesn't exist. - :param name: the github name to load - :return: The created object + :param name: the github name to load + :return: The created object - :Example: + :Example: - >>> self.env['github_organization'].create_from_name('OCA') - >>> self.env['github_repository'].create_from_name('OCA/web') + >>> self.env['github_organization'].create_from_name('OCA') + >>> self.env['github_repository'].create_from_name('OCA/web') """ github_connector = self.get_github_connector(self.github_type()) res = github_connector.get([name]) @@ -220,11 +218,11 @@ def button_update_from_github_full(self): def update_from_github(self, child_update): """Call Github API, using a URL using github id. Load data and - update Odoo object accordingly, if the odoo object is obsolete. - (Based on last write dates) + update Odoo object accordingly, if the odoo object is obsolete. + (Based on last write dates) - :param child_update: set to True if you want to reload childs - Objects linked to this object. (like members for teams) + :param child_update: set to True if you want to reload childs + Objects linked to this object. (like members for teams) """ github_connector = self.get_github_connector(self.github_type()) for item in self: diff --git a/github_connector/models/github.py b/github_connector/models/github.py index 17cc56f5..da5b241c 100644 --- a/github_connector/models/github.py +++ b/github_connector/models/github.py @@ -98,7 +98,10 @@ def get_by_url(self, url, call_type, data=False): break except Exception as err: _logger.warning( - "URL Call Error. %d/%d. URL: %s", i, self.max_try, err.__str__(), + "URL Call Error. %d/%d. URL: %s", + i, + self.max_try, + err.__str__(), ) else: raise exceptions.Warning(_("Maximum attempts reached.")) diff --git a/github_connector/models/github_analysis_rule_info.py b/github_connector/models/github_analysis_rule_info.py index c0006dcb..3f42af9e 100644 --- a/github_connector/models/github_analysis_rule_info.py +++ b/github_connector/models/github_analysis_rule_info.py @@ -9,7 +9,8 @@ class GithubAnalysisRuleInfoMixin(models.AbstractModel): _description = "Github Analysis Rule Mixin" analysis_rule_id = fields.Many2one( - string="Analysis Rule", comodel_name="github.analysis.rule", + string="Analysis Rule", + comodel_name="github.analysis.rule", ) group_id = fields.Many2one( string="Group", related="analysis_rule_id.group_id", readonly=True diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index 2041ebd9..7188efe2 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -234,8 +234,7 @@ def _get_analyzable_files(self, existing_folder): return res def analyze_code_one(self): - """Overload Me in custom Module that manage Source Code analysis. - """ + """Overload Me in custom Module that manage Source Code analysis.""" self.ensure_one() path = self.local_path # github_analysis_rule diff --git a/github_connector/report/github_repository_branch_rule_info_report.py b/github_connector/report/github_repository_branch_rule_info_report.py index 2bab2157..65cb9a70 100644 --- a/github_connector/report/github_repository_branch_rule_info_report.py +++ b/github_connector/report/github_repository_branch_rule_info_report.py @@ -11,19 +11,23 @@ class GithubRepositoryBranchRuleInfoReport(models.Model): _auto = False analysis_rule_id = fields.Many2one( - string="Analysis Rule", comodel_name="github.analysis.rule", + string="Analysis Rule", + comodel_name="github.analysis.rule", ) group_id = fields.Many2one( string="Group", related="analysis_rule_id.group_id", readonly=True ) repository_branch_id = fields.Many2one( - string="Repository Branch", comodel_name="github.repository.branch", + string="Repository Branch", + comodel_name="github.repository.branch", ) repository_id = fields.Many2one( - string="Repository", comodel_name="github.repository", + string="Repository", + comodel_name="github.repository", ) organization_serie_id = fields.Many2one( - string="Organization serie", comodel_name="github.organization.serie", + string="Organization serie", + comodel_name="github.organization.serie", ) code_count = fields.Integer(string="# Code") documentation_count = fields.Integer(string="# Documentation") @@ -78,7 +82,10 @@ def _query(self, with_clause="", fields=None, groupby="", from_clause=""): ) return "{} (SELECT {} FROM {} WHERE grbri.id > 0 GROUP BY {})".format( - with_, select_, from_, groupby_, + with_, + select_, + from_, + groupby_, ) def init(self): From 1dce4b46f107290b7966cc07bcb620e95907d1a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Marques?= Date: Tue, 8 Jun 2021 12:33:19 +0100 Subject: [PATCH 44/72] [MIG] github_connector: Migration to 14.0 --- github_connector/__manifest__.py | 5 +++-- github_connector/models/github_repository.py | 5 +---- .../models/github_team_partner.py | 22 ++++++++++++++++++- .../models/github_team_repository.py | 22 ++++++++++++++++++- github_connector/readme/CONTRIBUTORS.rst | 1 + github_connector/security/ir.model.access.csv | 8 +++++++ .../views/view_github_team_partner.xml | 6 +++-- .../views/view_github_team_repository.xml | 6 +++-- 8 files changed, 63 insertions(+), 12 deletions(-) diff --git a/github_connector/__manifest__.py b/github_connector/__manifest__.py index e4c0e2f0..941c2c74 100644 --- a/github_connector/__manifest__.py +++ b/github_connector/__manifest__.py @@ -6,10 +6,11 @@ { "name": "Github Connector", "summary": "Synchronize information from Github repositories", - "version": "13.0.3.0.0", + "version": "14.0.1.0.0", "category": "Connector", "license": "AGPL-3", - "author": "Odoo Community Association (OCA), " "GRAP, Akretion, " "Tecnativa", + "author": "Odoo Community Association (OCA), GRAP, Akretion, Tecnativa", + "website": "https://github.com/OCA/interface-github", "depends": ["base", "web"], "data": [ "security/ir_model_category.xml", diff --git a/github_connector/models/github_repository.py b/github_connector/models/github_repository.py index 3491e7a8..cab7ee12 100644 --- a/github_connector/models/github_repository.py +++ b/github_connector/models/github_repository.py @@ -68,16 +68,13 @@ class GithubRepository(models.Model): is_ignored = fields.Boolean( string="Is Ignored", compute="_compute_ignore", - multi="ignore", help="If checked, the branches will not be synchronized, and the" " code source will this way not be downloaded and analyzed. To ignore" " a repository, go to the organization and add the file" " 'Ignored Repositories'.", ) - color = fields.Integer( - string="Color Index", multi="ignore", compute="_compute_ignore" - ) + color = fields.Integer(string="Color Index", compute="_compute_ignore") analysis_rule_ids = fields.Many2many( string="Analysis Rules", comodel_name="github.analysis.rule" ) diff --git a/github_connector/models/github_team_partner.py b/github_connector/models/github_team_partner.py index 3133c260..50f7a104 100644 --- a/github_connector/models/github_team_partner.py +++ b/github_connector/models/github_team_partner.py @@ -2,7 +2,7 @@ # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import fields, models +from odoo import api, fields, models class GithubTeamPartner(models.Model): @@ -34,3 +34,23 @@ class GithubTeamPartner(models.Model): role = fields.Selection( selection=_ROLE_SELECTION, string="Role", required=True, readonly=True ) + + context_search_default_team_id = fields.Integer( + compute="_compute_context_search_default" + ) + context_search_default_partner_id = fields.Integer( + compute="_compute_context_search_default" + ) + + @api.depends_context("search_default_team_id", "search_default_partner_id") + def _compute_context_search_default(self): + """Compute the context value for the search terms + into helper fields for the view + """ + for record in self: + record.context_search_default_team_id = self.env.context.get( + "search_default_team_id", False + ) + record.context_search_default_partner_id = self.env.context.get( + "search_default_partner_id", False + ) diff --git a/github_connector/models/github_team_repository.py b/github_connector/models/github_team_repository.py index 60128a01..c69beb34 100644 --- a/github_connector/models/github_team_repository.py +++ b/github_connector/models/github_team_repository.py @@ -2,7 +2,7 @@ # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import fields, models +from odoo import api, fields, models class GithubTeamRepository(models.Model): @@ -42,3 +42,23 @@ class GithubTeamRepository(models.Model): required=True, readonly=True, ) + + context_search_default_team_id = fields.Integer( + compute="_compute_context_search_default" + ) + context_search_default_repository_id = fields.Integer( + compute="_compute_context_search_default" + ) + + @api.depends_context("search_default_team_id", "search_default_repository_id") + def _compute_context_search_default(self): + """Compute the context value for the search terms + into helper fields for the view + """ + for record in self: + record.context_search_default_team_id = self.env.context.get( + "search_default_team_id", False + ) + record.context_search_default_repository_id = self.env.context.get( + "search_default_repository_id", False + ) diff --git a/github_connector/readme/CONTRIBUTORS.rst b/github_connector/readme/CONTRIBUTORS.rst index 9c69dcaf..fa614fc6 100644 --- a/github_connector/readme/CONTRIBUTORS.rst +++ b/github_connector/readme/CONTRIBUTORS.rst @@ -10,3 +10,4 @@ * Ernesto Tejeda * Carlos Roca * Víctor Martínez + * João Marques diff --git a/github_connector/security/ir.model.access.csv b/github_connector/security/ir.model.access.csv index 03890fb9..d5b09dcd 100644 --- a/github_connector/security/ir.model.access.csv +++ b/github_connector/security/ir.model.access.csv @@ -18,3 +18,11 @@ access_github_team_partner_reader,github_team partner reader,model_github_team_p access_github_team_partner_manager,github_team partner manager,model_github_team_partner,github_connector.group_github_connector_manager,1,1,1,1 access_github_team_repository_reader,github_team repository reader,model_github_team_repository,,1,0,0,0 access_github_team_repository_manager,github_team repository manager,model_github_team_repository,github_connector.group_github_connector_manager,1,1,1,1 +access_github_repository_branch_rule_info_reader,access_github_repository_branch_rule_info_reader,model_github_repository_branch_rule_info,base.group_user,1,0,0,0 +access_github_repository_branch_rule_info_manager,access_github_repository_branch_rule_info_manager,model_github_repository_branch_rule_info,github_connector.group_github_connector_manager,1,1,1,1 +access_wizard_load_github_model_reader,access_wizard_load_github_model,model_wizard_load_github_model,base.group_user,1,0,0,0 +access_wizard_load_github_model_manager,access_wizard_load_github_model_manager,model_wizard_load_github_model,github_connector.group_github_connector_manager,1,1,1,1 +access_wizard_create_repository_reader,access_wizard_create_repository,model_wizard_create_repository,base.group_user,1,0,0,0 +access_wizard_create_repository_manager,access_wizard_create_repository_manager,model_wizard_create_repository,github_connector.group_github_connector_manager,1,1,1,1 +access_wizard_create_team_reader,access_wizard_create_team_reader,model_wizard_create_team,base.group_user,1,0,0,0 +access_wizard_create_team_manager,access_wizard_create_team_manager,model_wizard_create_team,github_connector.group_github_connector_manager,1,1,1,1 diff --git a/github_connector/views/view_github_team_partner.xml b/github_connector/views/view_github_team_partner.xml index b79bb61b..8392c8be 100644 --- a/github_connector/views/view_github_team_partner.xml +++ b/github_connector/views/view_github_team_partner.xml @@ -21,13 +21,15 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + diff --git a/github_connector/views/view_github_team_repository.xml b/github_connector/views/view_github_team_repository.xml index 395efb74..101369f9 100644 --- a/github_connector/views/view_github_team_repository.xml +++ b/github_connector/views/view_github_team_repository.xml @@ -24,13 +24,15 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). > + + From 3591f94b1680f0cf01d842fd33228899ed13668d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Marques?= Date: Tue, 13 Jul 2021 09:35:12 +0100 Subject: [PATCH 45/72] [REF] github_connector: Several improvements and refactor to PyGithub Remove useless (and wrong) `ondelete` attribute from O2M field in `github.organization`. Odoo O2M fields don't support it. Rename and convert relation between `res.partner` and `github.team.partner`. The latest will be unique for each user in each organization, so it makes no sense to make it a M2M, but rather a O2M. Also, the relation is to the "Team Partner" entity, and not to "Team". Remove username/password auth. Deprecated by Github: https://docs.github.com/en/rest/overview/other-authentication-methods#via-username-and-password Allow to set the Github acces token as an IR Configuration Parameter. Whatever is set in the config file still takes priority. Remove useless demo data Move to PyGithub Refactor tests not to depend on real connection to Github TT29979 [UPD] Update github_connector.pot [UPD] README.rst --- github_connector/README.rst | 56 +++-- github_connector/__manifest__.py | 5 +- github_connector/demo/github_organization.xml | 6 +- .../demo/github_repository_branch_demo.xml | 23 -- github_connector/i18n/github_connector.pot | 131 +++++------ .../migrations/14.0.1.0.0/pre-migration.py | 30 +++ github_connector/models/__init__.py | 1 - .../models/abstract_github_model.py | 221 +++++++++--------- github_connector/models/github.py | 167 ------------- .../models/github_organization.py | 59 +++-- github_connector/models/github_repository.py | 67 +++--- .../models/github_repository_branch.py | 39 ++-- github_connector/models/github_team.py | 75 +++--- github_connector/models/res_partner.py | 34 ++- github_connector/readme/CONFIGURE.rst | 9 +- .../static/description/index.html | 54 ++--- .../res/github_repo_20881668_response.json | 123 ++++++++++ .../res/github_search_issues_response.json | 100 ++++++++ .../res/github_user_OCA-git-bot_response.json | 34 +++ .../tests/test_github_analysis_rule.py | 31 ++- .../tests/test_github_connector.py | 48 +++- .../views/view_github_organization.xml | 15 +- .../views/view_github_repository.xml | 4 +- .../views/view_github_repository_branch.xml | 5 +- github_connector/views/view_github_team.xml | 15 +- github_connector/views/view_res_partner.xml | 24 +- .../wizards/wizard_create_repository.py | 2 +- .../wizards/wizard_create_team.py | 8 +- .../wizards/wizard_load_github_model.py | 8 +- 29 files changed, 798 insertions(+), 596 deletions(-) delete mode 100644 github_connector/demo/github_repository_branch_demo.xml create mode 100644 github_connector/migrations/14.0.1.0.0/pre-migration.py delete mode 100644 github_connector/models/github.py create mode 100644 github_connector/tests/res/github_repo_20881668_response.json create mode 100644 github_connector/tests/res/github_search_issues_response.json create mode 100644 github_connector/tests/res/github_user_OCA-git-bot_response.json diff --git a/github_connector/README.rst b/github_connector/README.rst index b763c352..b3b86271 100644 --- a/github_connector/README.rst +++ b/github_connector/README.rst @@ -14,13 +14,13 @@ Github Connector :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Finterface--github-lightgray.png?logo=github - :target: https://github.com/OCA/interface-github/tree/13.0/github_connector + :target: https://github.com/OCA/interface-github/tree/14.0/github_connector :alt: OCA/interface-github .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/interface-github-13-0/interface-github-13-0-github_connector + :target: https://translation.odoo-community.org/projects/interface-github-14-0/interface-github-14-0-github_connector :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/229/13.0 + :target: https://runbot.odoo-community.org/runbot/229/14.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -68,13 +68,8 @@ Note: make sure that Odoo process has read / write access on that folder * ``github_token = your_github_access_token`` -or - - * ``github_login = your_github_login`` - * ``github_password = your_github_password`` - -Note: if token and login/password are provided, the token will be used. -The login/password auth will be deprecated by GitHub in the future. +Note: The login/password auth has been deprecated by GitHub. +https://docs.github.com/en/rest/overview/other-authentication-methods#via-username-and-password #. Go to 'Settings' / 'Technical' / 'Parameters' / 'System Parameters' and define the following values: @@ -88,7 +83,7 @@ The login/password auth will be deprecated by GitHub in the future. download (potentially with a lot of repositories) in order to reduce the size of the transaction - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_settings.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_settings.png #. Go to your(s) user(s) form to add them in the new 'Connector Github Manager' groups. The members of this group will have the possibility to run Github @@ -115,18 +110,18 @@ To fetch information from Github, you have to: #. go to 'Github' / 'Settings' / 'Sync Object' #. Select the object type you want to synchronize and its Gthub name - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/sync_organization.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/sync_organization.png #. Once done for your organization(s), go to 'Github' / 'Github Commnunity' / 'Organizations' - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_organization_kanban.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_organization_kanban.png #. Optionally, once organization is created, you can create series for your projects. Go to 'Github' / 'Organizations' / click on your organization / 'Organization Series' Tabs - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_organization_series.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_organization_series.png Select branches to download ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -141,12 +136,12 @@ main branches (releases): #. In the 'Settings' tab, set the URL of the 'External Services' you use for Continuous Integration and Coverage. - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_organization_external_services.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_organization_external_services.png #. Once done, click on buttons 'Syncs', to synchronize repositories, teams and members. (This process can take a while depending of your size) - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_organization_sync_buttons.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_organization_sync_buttons.png Team / members synchronization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -155,16 +150,16 @@ You can synchronize members teams: #. Go to 'Teams' / tree view / 'Actions' / 'Update from Github'. - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_team_kanban.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_team_kanban.png #. In each team, you can see the members list and the role of the members - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_team_partner_kanban.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_team_partner_kanban.png #. In each team, you can see the repositories list but not the permissions of the team. (See 'Known Issues' Section) - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_team_repository_kanban.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_team_repository_kanban.png Repositories synchronization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -174,12 +169,12 @@ You can synchronize the branches of your repositories: #. Go to 'Repositories' / tree view / 'Actions' / 'Update from Github' - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_repository_kanban.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_repository_kanban.png #. In each repository, you can see the main branches list and the size of code source. - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_repository_branch_kanban.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_repository_branch_kanban.png Fetching the source code ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -188,11 +183,11 @@ Finally, you can download locally the source code of all your branches: #. Go to 'Repository Branches' / tree view / 'Actions' / 'Download and Analyse Source Code'. - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/wizard_download_analyze.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/wizard_download_analyze.png #. In the tree view you can update manually source code or refresh analysis. - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_repository_branch_list.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_repository_branch_list.png Analysis source code ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -233,14 +228,14 @@ You have the possibility to creates two items in Github directly from Odoo #. Later on, a synchronization will be performed, to create the according team in the Odoo instance. - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/wizard_create_team.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/wizard_create_team.png #. Repositories: #. Go to 'Settings' / 'Create Team in Github'. #. Set the information and click on Create in Github. - .. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/wizard_create_repository.png + .. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/wizard_create_repository.png Note ~~~~ @@ -262,15 +257,15 @@ This module provides several reports **Branches by Serie** -.. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/reporting_branches_by_serie.png +.. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/reporting_branches_by_serie.png **Sizes by Serie** -.. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/reporting_sizes_by_serie.png +.. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/reporting_sizes_by_serie.png **Repository branch analysis rule** -.. image:: https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_repository_branch_rule_info_report.png +.. image:: https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_repository_branch_rule_info_report.png Known issues / Roadmap ====================== @@ -306,7 +301,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -335,6 +330,7 @@ Contributors * Ernesto Tejeda * Carlos Roca * Víctor Martínez + * João Marques Maintainers ~~~~~~~~~~~ @@ -349,6 +345,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/interface-github `_ project on GitHub. +This module is part of the `OCA/interface-github `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/github_connector/__manifest__.py b/github_connector/__manifest__.py index 941c2c74..f43f5f75 100644 --- a/github_connector/__manifest__.py +++ b/github_connector/__manifest__.py @@ -40,8 +40,9 @@ "demo/github_analysis_rule_demo.xml", "demo/github_organization.xml", "demo/github_organization_serie.xml", - "demo/github_repository_branch_demo.xml", ], "installable": True, - "external_dependencies": {"python": ["GitPython", "pygount", "pathspec"]}, + "external_dependencies": { + "python": ["GitPython", "pygount", "pathspec", "PyGithub"] + }, } diff --git a/github_connector/demo/github_organization.xml b/github_connector/demo/github_organization.xml index 7019a72e..5ba610e4 100644 --- a/github_connector/demo/github_organization.xml +++ b/github_connector/demo/github_organization.xml @@ -7,7 +7,8 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). Odoo Community Association - OCA + OCA + 7600578 https://codecov.io/gh/{organization_name}/{repository_name}/branch/{branch_name} @@ -16,7 +17,8 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). >https://travis-ci.org/{organization_name}/{repository_name} - - - - - Organization 1 - organization1_login - - - - repository_1 - - - - - branch_1 - - - - diff --git a/github_connector/i18n/github_connector.pot b/github_connector/i18n/github_connector.pot index 44f816b2..621d5e19 100644 --- a/github_connector/i18n/github_connector.pot +++ b/github_connector/i18n/github_connector.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 13.0\n" +"Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -63,17 +63,28 @@ msgid "# Total" msgstr "" #. module: github_connector -#: code:addons/github_connector/models/github.py:0 -#, python-format -msgid "'%s' is not implemented." +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_kanban +msgid "" +"\n" +" \n" +" " msgstr "" #. module: github_connector -#: code:addons/github_connector/models/github.py:0 -#, python-format +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_kanban +msgid "" +"\n" +" \n" +" " +msgstr "" + +#. module: github_connector +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_kanban +#: model_terms:ir.ui.view,arch_db:github_connector.view_github_team_kanban msgid "" -"401 - Unable to authenticate to Github with the login '%s'.\n" -"You should check your credentials in the Odoo configuration file." +"\n" +" \n" +" " msgstr "" #. module: github_connector @@ -269,6 +280,22 @@ msgstr "" msgid "Contact" msgstr "" +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_team_partner__context_search_default_partner_id +msgid "Context Search Default Partner" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_team_repository__context_search_default_repository_id +msgid "Context Search Default Repository" +msgstr "" + +#. module: github_connector +#: model:ir.model.fields,field_description:github_connector.field_github_team_partner__context_search_default_team_id +#: model:ir.model.fields,field_description:github_connector.field_github_team_repository__context_search_default_team_id +msgid "Context Search Default Team" +msgstr "" + #. module: github_connector #: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__coverage_url msgid "Coverage URL" @@ -381,6 +408,7 @@ msgstr "" #: model:ir.model.fields,field_description:github_connector.field_github_team__display_name #: model:ir.model.fields,field_description:github_connector.field_github_team_partner__display_name #: model:ir.model.fields,field_description:github_connector.field_github_team_repository__display_name +#: model:ir.model.fields,field_description:github_connector.field_res_partner__display_name #: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__display_name #: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__display_name #: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model__display_name @@ -446,18 +474,10 @@ msgstr "" #: code:addons/github_connector/models/abstract_github_model.py:0 #, python-format msgid "" -"Feature not Implemented : Please define 'get_github_args_for_creation' " +"Feature not Implemented : Please define 'get_github_base_obj_for_creation' " "function in child model." msgstr "" -#. module: github_connector -#: code:addons/github_connector/models/abstract_github_model.py:0 -#, python-format -msgid "" -"Feature not Implemented : Please define 'get_github_data_from_odoo' function" -" in child model." -msgstr "" - #. module: github_connector #: code:addons/github_connector/models/abstract_github_model.py:0 #, python-format @@ -466,14 +486,6 @@ msgid "" "child model." msgstr "" -#. module: github_connector -#: code:addons/github_connector/models/abstract_github_model.py:0 -#, python-format -msgid "" -"Feature not Implemented : Please define 'github_type' function in child " -"model." -msgstr "" - #. module: github_connector #: model_terms:ir.ui.view,arch_db:github_connector.view_github_organization_form #: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_form @@ -576,15 +588,15 @@ msgid "Github Team Repository" msgstr "" #. module: github_connector -#: model:ir.model.fields,field_description:github_connector.field_abstract_github_model__github_login -#: model:ir.model.fields,field_description:github_connector.field_github_organization__github_login -#: model:ir.model.fields,field_description:github_connector.field_github_repository__github_login -#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__github_login -#: model:ir.model.fields,field_description:github_connector.field_github_team__github_login -#: model:ir.model.fields,field_description:github_connector.field_res_partner__github_login -#: model:ir.model.fields,field_description:github_connector.field_res_users__github_login -#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__github_login -#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__github_login +#: model:ir.model.fields,field_description:github_connector.field_abstract_github_model__github_name +#: model:ir.model.fields,field_description:github_connector.field_github_organization__github_name +#: model:ir.model.fields,field_description:github_connector.field_github_repository__github_name +#: model:ir.model.fields,field_description:github_connector.field_github_repository_branch__github_name +#: model:ir.model.fields,field_description:github_connector.field_github_team__github_name +#: model:ir.model.fields,field_description:github_connector.field_res_partner__github_name +#: model:ir.model.fields,field_description:github_connector.field_res_users__github_name +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__github_name +#: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__github_name msgid "Github Technical Name" msgstr "" @@ -650,6 +662,7 @@ msgstr "" #: model:ir.model.fields,field_description:github_connector.field_github_team__id #: model:ir.model.fields,field_description:github_connector.field_github_team_partner__id #: model:ir.model.fields,field_description:github_connector.field_github_team_repository__id +#: model:ir.model.fields,field_description:github_connector.field_res_partner__id #: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__id #: model:ir.model.fields,field_description:github_connector.field_wizard_create_team__id #: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model__id @@ -676,6 +689,12 @@ msgstr "" msgid "Image" msgstr "" +#. module: github_connector +#: code:addons/github_connector/models/abstract_github_model.py:0 +#, python-format +msgid "Invalid name '%s' provided" +msgstr "" + #. module: github_connector #: model:ir.model.fields,field_description:github_connector.field_res_partner__is_bot_account #: model:ir.model.fields,field_description:github_connector.field_res_users__is_bot_account @@ -712,6 +731,7 @@ msgstr "" #: model:ir.model.fields,field_description:github_connector.field_github_team____last_update #: model:ir.model.fields,field_description:github_connector.field_github_team_partner____last_update #: model:ir.model.fields,field_description:github_connector.field_github_team_repository____last_update +#: model:ir.model.fields,field_description:github_connector.field_res_partner____last_update #: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository____last_update #: model:ir.model.fields,field_description:github_connector.field_wizard_create_team____last_update #: model:ir.model.fields,field_description:github_connector.field_wizard_load_github_model____last_update @@ -813,7 +833,6 @@ msgstr "" #. module: github_connector #: code:addons/github_connector/models/abstract_github_model.py:0 -#: code:addons/github_connector/models/github.py:0 #, python-format msgid "Maximum attempts reached." msgstr "" @@ -974,8 +993,8 @@ msgstr "" #: code:addons/github_connector/models/abstract_github_model.py:0 #, python-format msgid "" -"Please add the couple 'github_login' and 'github_password' or 'github_token'" -" in Odoo configuration file." +"Please add the 'github_token' in Odoo configuration file or as the " +"'github.access_token' configuration parameter." msgstr "" #. module: github_connector @@ -1165,8 +1184,8 @@ msgstr "" #: model:ir.actions.act_window,name:github_connector.action_github_team_partner_from_partner #: model:ir.model.fields,field_description:github_connector.field_github_organization__team_ids #: model:ir.model.fields,field_description:github_connector.field_github_repository__team_ids -#: model:ir.model.fields,field_description:github_connector.field_res_partner__github_team_ids -#: model:ir.model.fields,field_description:github_connector.field_res_users__github_team_ids +#: model:ir.model.fields,field_description:github_connector.field_res_partner__github_team_partner_ids +#: model:ir.model.fields,field_description:github_connector.field_res_users__github_team_partner_ids #: model:ir.model.fields,field_description:github_connector.field_wizard_create_repository__team_ids #: model:ir.ui.menu,name:github_connector.menu_github_team #: model_terms:ir.ui.view,arch_db:github_connector.view_res_partner_form @@ -1184,15 +1203,6 @@ msgstr "" msgid "Technical Settings" msgstr "" -#. module: github_connector -#: code:addons/github_connector/models/github.py:0 -#, python-format -msgid "" -"The call to '%s' failed:\n" -"- Status Code: %d\n" -"- Reason: %s" -msgstr "" - #. module: github_connector #: model:ir.model.fields,help:github_connector.field_github_team__privacy #: model:ir.model.fields,help:github_connector.field_wizard_create_team__privacy @@ -1202,6 +1212,14 @@ msgid "" "* closed - visible to all members of this organization." msgstr "" +#. module: github_connector +#: code:addons/github_connector/models/github_organization.py:0 +#, python-format +msgid "" +"The provided Github Token must have admin read:org permissions to the " +"organization '%s'" +msgstr "" + #. module: github_connector #: model:ir.model.fields.selection,name:github_connector.selection__github_repository_branch__state__to_analyze #: model_terms:ir.ui.view,arch_db:github_connector.view_github_repository_branch_search @@ -1254,23 +1272,6 @@ msgstr "" msgid "Two different partners cannot have the same Github Login" msgstr "" -#. module: github_connector -#: code:addons/github_connector/models/github.py:0 -#, python-format -msgid "" -"Unable to realize the current operation. Possible reasons:\n" -" * You try to create a duplicated item\n" -" * Some of the arguments are incorrect" -msgstr "" - -#. module: github_connector -#: code:addons/github_connector/models/github.py:0 -#, python-format -msgid "" -"Unable to realize the current operation. The login '%s' does not have the " -"correct access rights." -msgstr "" - #. module: github_connector #: model:ir.model.fields.selection,name:github_connector.selection__github_team_repository__permission__undefined msgid "Undefined" diff --git a/github_connector/migrations/14.0.1.0.0/pre-migration.py b/github_connector/migrations/14.0.1.0.0/pre-migration.py new file mode 100644 index 00000000..ac88a167 --- /dev/null +++ b/github_connector/migrations/14.0.1.0.0/pre-migration.py @@ -0,0 +1,30 @@ +# Copyright 2021 Tecnativa - João Marques +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from openupgradelib import openupgrade + +column_renames = { + "res_partner": [ + ("github_team_ids", "github_team_partner_ids"), + ("github_login", "github_name"), + ], + "github_organization": [ + ("github_login", "github_name"), + ], + "github_repository_branch": [ + ("github_login", "github_name"), + ], + "github_repository": [ + ("github_login", "github_name"), + ], + "github_team_partner": [ + ("github_login", "github_name"), + ], + "github_team": [ + ("github_login", "github_name"), + ], +} + + +@openupgrade.migrate() +def migrate(env, version): + openupgrade.rename_columns(env.cr, column_renames) diff --git a/github_connector/models/__init__.py b/github_connector/models/__init__.py index cecd2499..db322cdb 100644 --- a/github_connector/models/__init__.py +++ b/github_connector/models/__init__.py @@ -1,4 +1,3 @@ -from . import github from . import abstract_github_model from . import res_partner diff --git a/github_connector/models/abstract_github_model.py b/github_connector/models/abstract_github_model.py index aefaefd2..132e18bd 100644 --- a/github_connector/models/abstract_github_model.py +++ b/github_connector/models/abstract_github_model.py @@ -1,4 +1,5 @@ # Copyright (C) 2016-Today: Odoo Community Association (OCA) +# Copyright 2021 Tecnativa - João Marques # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -7,33 +8,33 @@ from datetime import datetime from urllib.request import urlopen +from github import Github +from github.GithubException import UnknownObjectException + from odoo import _, api, exceptions, fields, models, tools from odoo.exceptions import UserError -from .github import Github - _logger = logging.getLogger(__name__) +_GITHUB_URL = "https://github.com/" + class AbstractGithubModel(models.AbstractModel): """ This abstract model is used to share all features related to github model. Note that some fields and function have to be defined in the inherited - model. (github_type for instance) + model. """ _name = "abstract.github.model" _description = "Github abstract model" - _github_type = None _github_login_field = None _need_individual_call = False _field_list_prevent_overwrite = [] github_id_external = fields.Char(string="Github Id", readonly=True, index=True) - github_login = fields.Char( - string="Github Technical Name", readonly=True, index=True - ) + github_name = fields.Char(string="Github Technical Name", readonly=True, index=True) github_url = fields.Char(string="Github URL", readonly=True) @@ -48,17 +49,6 @@ class AbstractGithubModel(models.AbstractModel): ) # Overloadable Section - def github_type(self): - if self._github_type is None: - raise exceptions.Warning( - _( - "Feature not Implemented : Please define 'github_type'" - " function in child model." - ) - ) - else: - return self._github_type - def github_login_field(self): if self._github_login_field is None: raise exceptions.Warning( @@ -73,13 +63,14 @@ def github_login_field(self): @api.model def get_conversion_dict(self): """ - Prepare function that map Github fields to Odoo fields + Prepare function that builds a map from Github fields to Odoo fields + :return: Dictionary {odoo_field: github_field} """ return { "github_id_external": "id", "github_url": "html_url", - "github_login": self.github_login_field(), + "github_name": self.github_login_field(), "github_create_date": "created_at", "github_write_date": "updated_at", } @@ -91,87 +82,89 @@ def process_timezone_fields(self, res): @api.model def get_odoo_data_from_github(self, data): - """Prepare function that map Github data to create in Odoo""" + """Prepare function that maps data from a Github object to a dictionary of + values ready to create an Odoo record + """ map_dict = self.get_conversion_dict() res = {} for k, v in map_dict.items(): - if hasattr(self, k) and data.get(v, False): - res.update({k: data[v]}) + if hasattr(self, k) and hasattr(data, v): + res.update({k: getattr(data, v)}) res.update({"github_last_sync_date": fields.Datetime.now()}) + # res.update({"github_type": type(data).__name__}) self.process_timezone_fields(res) return res - def get_github_data_from_odoo(self): - """Prepare function that map Odoo data to create in Github. - Usefull only if your model implement creation in github""" - self.ensure_one() - raise exceptions.Warning( - _( - "Feature not Implemented : Please define" - " 'get_github_data_from_odoo' function in child model." - ) - ) - - def get_github_args_for_creation(self): - """Should Return list of arguments required to create the given item + def get_github_base_obj_for_creation(self): + """Should return the base object required to create the given item in Github. - Usefull only if your model implement creation in github""" + Usefull only if your model implements creation in github + """ self.ensure_one() raise exceptions.Warning( _( "Feature not Implemented : Please define" - " 'get_github_args_for_creation' function in child model." + " 'get_github_base_obj_for_creation' function in child model." ) ) def full_update(self): """Override this function in models that inherit this abstract to mention which items should be synchronized from github when the - user click on 'Full Update' Button""" + user clicks the 'Full Update' Button""" def _hook_after_github_creation(self): - """Hook that will be called, after a creation in github. + """Hook that will be called after a creation in github. Override this function to add custom logic for after creation.""" # Custom Public Function @api.model - def get_from_id_or_create(self, data, extra_data=None): - """Search if the odoo object exists in database. If yes, returns the - object. Otherwise, creates the new object. + def get_from_id_or_create(self, gh_data=None, data=None, extra_data=None): + """Search if an Odoo object related to the Github data exists in database. + If it does, it returns the object. Otherwise, it creates the new object. - :param data: dict with github 'id' and 'url' keys + :param gh_data: Github object the will be used to get/create Odoo record + :param data: dict with github 'id' and 'url' keys (deprecated) + :param extra_data: dict with extra data to be put into the Odoo record :return: The searched or created object :Example: >>> self.env['github_organization'].get_from_id_or_create( - {'id': 7600578, 'url': 'https://api.github.com/orgs/OCA'}) + data={'id': 7600578, 'url': 'https://api.github.com/orgs/OCA'}) """ - extra_data = extra_data and extra_data or {} - + extra_data = extra_data or {} + if gh_data and not data: + # Get a dictionary of data corresponding to the Github object + data = self.get_odoo_data_from_github(gh_data) # We try to search object by id - existing_object = self.with_context(active_test=False).search( - [("github_id_external", "=", data["id"])] - ) + existing_object = None + if "github_id_external" in data: + existing_object = self.with_context(active_test=False).search( + [("github_id_external", "=", data["github_id_external"])] + ) if existing_object: return existing_object - - # We try to see if object exist by name (instead of id) + # We try to search the object by name (instead of id) if self._github_login_field and self._github_login_field in data: existing_object = self.with_context(active_test=False).search( - [("github_login", "=", data[self._github_login_field])] + [("github_name", "=", data[self._github_login_field])] ) if len(existing_object) == 1: - # Update the existing object with the id - existing_object.github_id_external = data["id"] + # Update the existing object + existing_object.github_id_external = ( + data["github_id_external"] + if "github_id_external" in data + else existing_object.find_related_github_object().id + ) _logger.info( "Existing object %s#%d with Github name '%s' has been" - " updated with unique Github id %s#%s", + " updated from a '%s' object with unique Github id %s", self._name, existing_object.id, data[self._github_login_field], - data["id"], - self.github_type(), + type(data).__name__, + existing_object.github_id_external, ) return existing_object elif len(existing_object) > 1: @@ -179,10 +172,12 @@ def get_from_id_or_create(self, data, extra_data=None): _("Duplicate object with Github login %s") % (data[self._github_login_field],) ) - - if self._need_individual_call: - github_connector = self.get_github_connector(self.github_type()) - data = github_connector.get_by_url(data["url"], "get") + # if self._need_individual_call: + # github_connector = self.get_github_connector(self.github_type()) + # data = github_connector.get_by_url(data["url"], "get") + # Create a new object otherwise + # The _create function already parses the Github object to obtain the full + # Odoo dictionary, so we need to pass the full gh_data object. return self._create_from_github_data(data, extra_data) @api.model @@ -198,23 +193,46 @@ def create_from_name(self, name): >>> self.env['github_organization'].create_from_name('OCA') >>> self.env['github_repository'].create_from_name('OCA/web') """ - github_connector = self.get_github_connector(self.github_type()) - res = github_connector.get([name]) + gh_api = self.get_github_connector() + p_name = name.rstrip("/").lstrip( + "/" + ) # strip any / in the beggining of end just in case + try: + if "/" in p_name: + # It's a repo + gh_obj = gh_api.get_repo(p_name) + else: + try: + # Try to get an organization 1st. + # An organization is always an user, but a user is not necessarily an org. + gh_obj = gh_api.get_organization(p_name) + except UnknownObjectException: + # Try to get an user. + gh_obj = gh_api.get_user(p_name) + except UnknownObjectException: + raise UserError(_("Invalid name '%s' provided" % name)) + res = self.get_odoo_data_from_github(gh_obj) # search if ID doesn't exist in database current_object = self.with_context(active_test=False).search( - [("github_id_external", "=", res["id"])] + [("github_id_external", "=", res["github_id_external"])] ) - if not current_object: - # Create the object - return self._create_from_github_data(res) - else: + if current_object: return current_object + # Create the object + return self._create_from_github_data(res) def button_update_from_github_light(self): - return self.update_from_github(False) + return self.update_from_github(child_update=False) def button_update_from_github_full(self): - return self.update_from_github(True) + return self.update_from_github(child_update=True) + + @api.model + def find_related_github_object(self, id=None): + """Query Github API to find the related object + + This function should be overwritten in the child classes. + """ def update_from_github(self, child_update): """Call Github API, using a URL using github id. Load data and @@ -224,14 +242,10 @@ def update_from_github(self, child_update): :param child_update: set to True if you want to reload childs Objects linked to this object. (like members for teams) """ - github_connector = self.get_github_connector(self.github_type()) for item in self: - if item._name == "github.organization": - # Github doesn't provides api to load an organization by id - res = github_connector.get([item.github_login]) - else: - res = github_connector.get([item.github_id_external], by_id=True) - item._update_from_github_data(res) + gh_obj = item.find_related_github_object() + data = self.get_odoo_data_from_github(gh_obj) + item._update_from_github_data(data) if child_update: self.full_update() @@ -241,7 +255,7 @@ def get_base64_image_from_github(self, url): ) for _i in range(max_try): try: - stream = urlopen(url).read() + stream = urlopen(url, timeout=10).read() break except Exception as err: _logger.warning("URL Call Error. %s" % (err.__str__())) @@ -253,18 +267,16 @@ def get_base64_image_from_github(self, url): @api.model def _create_from_github_data(self, data, extra_data=None): extra_data = extra_data and extra_data or {} - vals = self.get_odoo_data_from_github(data) - vals.update(extra_data) - return self.create(vals) + data.update(extra_data) + return self.create(data) def _update_from_github_data(self, data): for item in self: - vals = self.get_odoo_data_from_github(data) # Optimization. Due to the fact that github datas rarely change, # and that there a lot of related / computed fields invalidation # process, we realize a write only if data changed to_write = {} - for k, v in vals.items(): + for k, v in data.items(): if hasattr(item[k], "id"): to_compare = item[k].id else: @@ -277,39 +289,26 @@ def _update_from_github_data(self, data): if to_write: item.write(to_write) - def get_github_connector(self, github_type): - no_login = not tools.config.get("github_login") or not tools.config.get( - "github_password" + def get_github_connector(self): + ICP = self.env["ir.config_parameter"] + token = tools.config.get("github_token") or ICP.get_param( + "github.access_token", default="" ) - no_token = not tools.config.get("github_token") - if no_login and no_token: + if not token: raise exceptions.Warning( _( - "Please add the couple 'github_login' and 'github_password'" - " or 'github_token'" - " in Odoo configuration file." + "Please add the 'github_token' in Odoo configuration file" + " or as the 'github.access_token' configuration parameter." ) ) - return Github( - github_type, - tools.config.get("github_login", ""), - tools.config.get("github_password", ""), - int(self.sudo().env["ir.config_parameter"].get_param("github.max_try")), - tools.config.get("github_token", ""), - ) + return Github(token) - def create_in_github(self, model_obj): - self.ensure_one() - github_connector = self.get_github_connector(self.github_type()) - # Create in Github - response = github_connector.create( - self.get_github_args_for_creation(), self.get_github_data_from_odoo() - ) - # Create in Odoo with the returned data and update object - new_item = model_obj._create_from_github_data(response) - new_item.full_update() - new_item._hook_after_github_creation() - return new_item + def create_in_github(self): + """Create an object in Github through the API + + As this depends on each object, it should be overwritten in each + implementation class + """ def get_action(self): self.ensure_one() diff --git a/github_connector/models/github.py b/github_connector/models/github.py deleted file mode 100644 index da5b241c..00000000 --- a/github_connector/models/github.py +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright (C) 2016-Today: Odoo Community Association (OCA) -# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) -# @author: Sébastien BEAU -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - - -import json -import logging - -import requests -from requests.auth import AuthBase, HTTPBasicAuth - -from odoo import _, exceptions - -_logger = logging.getLogger(__name__) - -_MAX_NUMBER_REQUEST = 30 - -_BASE_URL = "https://api.github.com/" - -_GITHUB_URL = "https://github.com/" - -_GITHUB_TYPE = [ - ("organization", "Organization"), - ("repository", "Repository"), - ("user", "User"), -] - -_GITHUB_TYPE_URL = { - "organization": {"url_get_by_name": "orgs/%s"}, - "user": {"url_get_by_id": "user/%s", "url_get_by_name": "users/%s"}, - "repository": { - "url_get_by_id": "repositories/%s", - "url_get_by_name": "repos/%s", - "url_create": "orgs/%s/repos", - }, - "team": {"url_get_by_id": "teams/%s", "url_create": "orgs/%s/teams"}, - "organization_members": {"url_get_by_name": "orgs/%s/members"}, - "organization_repositories": {"url_get_by_name": "orgs/%s/repos"}, - "organization_teams": {"url_get_by_name": "orgs/%s/teams"}, - "team_members_member": {"url_get_by_name": "teams/%s/members?role=member"}, - "team_members_maintainer": {"url_get_by_name": "teams/%s/members?role=maintainer"}, - "team_repositories": {"url_get_by_name": "teams/%s/repos"}, - "repository_branches": {"url_get_by_name": "repos/%s/branches"}, -} - -_CODE_401 = 401 -_CODE_403 = 403 -_CODE_422 = 422 -_CODE_200 = 200 -_CODE_201 = 201 - - -class Github(object): - def __init__(self, github_type, login, password, max_try, token=None): - super().__init__() - self.github_type = github_type - self.max_try = max_try - if token: - self.auth = HTTPTokenAuth(token) - else: - self.auth = HTTPBasicAuth(login, password) - - def _build_url(self, arguments, url_type, page): - arguments = arguments and arguments or {} - url = _GITHUB_TYPE_URL[self.github_type][url_type] - if self.github_type not in _GITHUB_TYPE_URL.keys(): - raise exceptions.Warning(_("'%s' is not implemented.") % self.github_type) - complete_url = _BASE_URL + url % tuple(arguments) - - if page: - complete_url += ( - "?" in complete_url and "&" or "?" - ) + "per_page=%d&page=%d" % (_MAX_NUMBER_REQUEST, page) - return complete_url - - def list(self, arguments): - page = 1 - datas = [] - while True: - pending_datas = self.get(arguments, False, page) - datas += pending_datas - if pending_datas == [] or len(pending_datas) < _MAX_NUMBER_REQUEST: - break - page += 1 - return datas - - def get_by_url(self, url, call_type, data=False): - _logger.info("Calling %s" % url) - for i in range(self.max_try): - try: - if call_type == "get": - response = requests.get(url, auth=self.auth) - break - elif call_type == "post": - json_data = json.dumps(data) - response = requests.post(url, auth=self.auth, data=json_data) - break - except Exception as err: - _logger.warning( - "URL Call Error. %d/%d. URL: %s", - i, - self.max_try, - err.__str__(), - ) - else: - raise exceptions.Warning(_("Maximum attempts reached.")) - - if isinstance(self.auth, HTTPBasicAuth): - auth_err_msg = _("login '%s'") % self.auth.login - elif isinstance(self.auth, HTTPTokenAuth): - auth_err_msg = _("provided token") - if response.status_code == _CODE_401: - raise exceptions.Warning( - _( - "401 - Unable to authenticate to Github with the %s.\n" - "You should check your credentials in the Odoo" - " configuration file." - ) - % auth_err_msg - ) - elif response.status_code == _CODE_403: - raise exceptions.Warning( - _( - "Unable to realize the current operation. The %s" - " does not have the correct access rights." - ) - % auth_err_msg - ) - elif response.status_code == _CODE_422: - raise exceptions.Warning( - _( - "Unable to realize the current operation. Possible reasons:\n" - " * You try to create a duplicated item\n" - " * Some of the arguments are incorrect" - ) - ) - elif response.status_code not in [_CODE_200, _CODE_201]: - raise exceptions.Warning( - _("The call to '%s' failed:\n" "- Status Code: %d\n" "- Reason: %s") - % (response.url, response.status_code, response.reason) - ) - return response.json() - - def get(self, arguments, by_id=False, page=None): - url = self._build_url( - arguments, by_id and "url_get_by_id" or "url_get_by_name", page - ) - return self.get_by_url(url, "get") - - def create(self, arguments, data): - # pylint: disable=method-required-super - url = self._build_url(arguments, "url_create", None) - res = self.get_by_url(url, "post", data) - return res - - -class HTTPTokenAuth(AuthBase): - - header_format_str = "token {}" - - def __init__(self, token): - self.token = token - - def __call__(self, request): - request.headers["Authorization"] = self.header_format_str.format(self.token) - return request diff --git a/github_connector/models/github_organization.py b/github_connector/models/github_organization.py index 82aba864..c2569cd7 100644 --- a/github_connector/models/github_organization.py +++ b/github_connector/models/github_organization.py @@ -1,9 +1,12 @@ # Copyright (C) 2016-Today: Odoo Community Association (OCA) # Copyright 2020 Tecnativa - Víctor Martínez +# Copyright 2021 Tecnativa - João Marques # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import api, fields, models +from github.GithubException import GithubException + +from odoo import _, api, exceptions, fields, models class GithubOrganization(models.Model): @@ -12,7 +15,6 @@ class GithubOrganization(models.Model): _order = "name" _description = "Github organization" - _github_type = "organization" _github_login_field = "login" # Columns Section @@ -54,7 +56,6 @@ class GithubOrganization(models.Model): repository_ids = fields.One2many( string="Repositories", comodel_name="github.repository", - ondelete="cascade", inverse_name="organization_id", readonly=True, ) @@ -108,10 +109,10 @@ def get_conversion_dict(self): return res @api.model - def get_odoo_data_from_github(self, data): - res = super().get_odoo_data_from_github(data) - if "avatar_url" in data: - res.update({"image": self.get_base64_image_from_github(data["avatar_url"])}) + def get_odoo_data_from_github(self, gh_data): + res = super().get_odoo_data_from_github(gh_data) + if hasattr(gh_data, "avatar_url"): + res.update({"image": self.get_base64_image_from_github(gh_data.avatar_url)}) return res def full_update(self): @@ -149,38 +150,54 @@ def _compute_organization_serie_qty(self): organization.organization_serie_ids ) + def find_related_github_object(self, obj_id=None): + """Query Github API to find the related object""" + gh_api = self.get_github_connector() + return gh_api.get_organization(obj_id or self.github_name) + # Action section def button_sync_member(self): - github_member = self.get_github_connector("organization_members") + gh_org = self.find_related_github_object() partner_obj = self.env["res.partner"] for organization in self: member_ids = [] - for data in github_member.list([organization.github_login]): - partner = partner_obj.get_from_id_or_create(data) + for gh_member in gh_org.get_members(): + partner = partner_obj.get_from_id_or_create(gh_data=gh_member) member_ids.append(partner.id) organization.member_ids = member_ids def button_sync_repository(self): + gh_org = self.find_related_github_object() repository_obj = self.env["github.repository"] - github_repo = self.get_github_connector("organization_repositories") for organization in self: repository_ids = [] - for data in github_repo.list([organization.github_login]): - repository = repository_obj.get_from_id_or_create(data) + for gh_repo in gh_org.get_repos(): + repository = repository_obj.with_context( + github_organization_id=organization.id + ).get_from_id_or_create(gh_data=gh_repo) repository_ids.append(repository.id) organization.repository_ids = repository_ids def button_sync_team(self): + gh_org = self.find_related_github_object() team_obj = self.env["github.team"] - github_team = self.get_github_connector("organization_teams") for organization in self: - team_ids = [] - for data in github_team.list([organization.github_login]): - team = team_obj.get_from_id_or_create( - data, {"organization_id": organization.id} - ) - team_ids.append(team.id) - organization.team_ids = team_ids + try: + team_ids = [] + for gh_team in gh_org.get_teams(): + team = team_obj.get_from_id_or_create( + gh_data=gh_team, extra_data={"organization_id": organization.id} + ) + team_ids.append(team.id) + organization.team_ids = team_ids + except GithubException as e: + if e.status == 403: + raise exceptions.AccessError( + _( + "The provided Github Token must have admin read:org" + " permissions to the organization '%s'" % self.name + ) + ) def action_github_repository(self): self.ensure_one() diff --git a/github_connector/models/github_repository.py b/github_connector/models/github_repository.py index cab7ee12..f321a11d 100644 --- a/github_connector/models/github_repository.py +++ b/github_connector/models/github_repository.py @@ -1,4 +1,5 @@ # Copyright (C) 2016-Today: Odoo Community Association (OCA) +# Copyright 2021 Tecnativa - João Marques # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -15,7 +16,6 @@ class GithubRepository(models.Model): _order = "organization_id, name" _description = "Github Repository" - _github_type = "repository" _github_login_field = "full_name" # Column Section @@ -94,12 +94,12 @@ def _compute_team_qty(self): for repository in self: repository.team_qty = len(repository.team_ids) - @api.depends("name", "organization_id.github_login") + @api.depends("name", "organization_id.github_name") def _compute_complete_name(self): for repository in self: repository.complete_name = "%(login)s/%(rep_name)s" % ( { - "login": repository.organization_id.github_login, + "login": repository.organization_id.github_name, "rep_name": repository.name or "", } ) @@ -116,7 +116,6 @@ def get_conversion_dict(self): res.update( { "name": "name", - "github_url": "url", "description": "description", "website": "homepage", } @@ -124,24 +123,41 @@ def get_conversion_dict(self): return res @api.model - def get_odoo_data_from_github(self, data): - organization_obj = self.env["github.organization"] - res = super().get_odoo_data_from_github(data) - organization = organization_obj.get_from_id_or_create(data["owner"]) - res.update({"organization_id": organization.id}) + def get_odoo_data_from_github(self, gh_data): + res = super().get_odoo_data_from_github(gh_data) + org_id = self.env.context.get("github_organization_id", None) + if not org_id: + # Fetch current organization object + organization_obj = self.env["github.organization"] + organization = organization_obj.get_from_id_or_create(gh_data=gh_data.owner) + org_id = organization.id + res.update({"organization_id": org_id}) return res - def get_github_data_from_odoo(self): + def find_related_github_object(self, obj_id=None): + """Query Github API to find the related object""" + gh_api = self.get_github_connector() + return gh_api.get_repo(int(obj_id or self.github_id_external)) + + def get_github_base_obj_for_creation(self): self.ensure_one() - return { - "name": self.name, - "description": self.description or "", - "homepage": self.website, - } + gh_api = self.get_github_connector() + return gh_api.get_organization(self.organization_id.github_name) - def get_github_args_for_creation(self): + def create_in_github(self): + """Create an object in Github through the API""" self.ensure_one() - return [self.organization_id.github_login] + # Create in Github + gh_base_obj = self.get_github_base_obj_for_creation() + gh_repo = gh_base_obj.create_repo( + name=self.name, description=self.description or "", homepage=self.website + ) + # Create in Odoo with the returned data and update object + data = self.get_odoo_data_from_github(gh_repo) + new_item = self._create_from_github_data(data) + new_item.full_update() + new_item._hook_after_github_creation() + return new_item def full_update(self): self.button_sync_branch() @@ -153,32 +169,29 @@ def cron_update_branch_list(self): return True def button_sync_branch(self): - github_branch = self.get_github_connector("repository_branches") + gh_repo = self.find_related_github_object() branch_obj = self.env["github.repository.branch"] - for repository in self: + for repository in self.filtered(lambda r: not r.is_ignored): branch_ids = [] correct_series = repository.organization_id.organization_serie_ids.mapped( "name" ) - - for data in github_branch.list([repository.github_login]): - if repository.is_ignored: - pass - elif data["name"] in correct_series: + for gh_branch in gh_repo.get_branches(): + if gh_branch.name in correct_series: # We don't use get_from_id_or_create because repository # branches does not have any ids. (very basic object in the # Github API) branch = branch_obj.create_or_update_from_name( - repository.id, data["name"] + repository.id, gh_branch.name ) branch_ids.append(branch.id) else: _logger.warning( "the branch '%s'/'%s' has been ignored.", repository.name, - data["name"], + gh_branch.name, ) - repository.branch_ids = branch_ids + repository.repository_branch_ids = [(6, 0, branch_ids)] def action_github_team_repository_from_repository(self): self.ensure_one() diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index 7188efe2..1b80130f 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -1,5 +1,6 @@ # Copyright (C) 2016-Today: Odoo Community Association (OCA) # Copyright 2020 Tecnativa - Víctor Martínez +# Copyright 2021 Tecnativa - João Marques # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -12,8 +13,6 @@ from odoo import _, addons, api, exceptions, fields, models, tools from odoo.tools.safe_eval import safe_eval -from .github import _GITHUB_URL - _logger = logging.getLogger(__name__) try: @@ -28,7 +27,6 @@ class GithubRepository(models.Model): _order = "repository_id, sequence_serie" _description = "Github Repository Branch" - _github_type = "repository_branches" _github_login_field = False _SELECTION_STATE = [ @@ -89,10 +87,10 @@ class GithubRepository(models.Model): last_analyze_date = fields.Datetime(string="Last Analyze Date") coverage_url = fields.Char( - string="Coverage URL", store=True, compute="_compute_coverage" + string="Coverage URL", store=True, compute="_compute_coverage_url" ) - ci_url = fields.Char(string="CI URL", store=True, compute="_compute_ci") + ci_url = fields.Char(string="CI URL", store=True, compute="_compute_ci_url") github_url = fields.Char( string="Github URL", store=True, compute="_compute_github_url" @@ -160,6 +158,8 @@ def create_or_update_from_name(self, repository_id, name): def _download_code(self): for branch in self: + repository = branch.repository_id + gh_repo = repository.find_related_github_object() if not os.path.exists(branch.local_path): _logger.info("Cloning new repository into %s ..." % branch.local_path) # Cloning the repository @@ -173,11 +173,8 @@ def _download_code(self): ) % (branch.local_path) ) - - command = ("git clone %s%s/%s.git -b %s %s") % ( - _GITHUB_URL, - branch.repository_id.organization_id.github_login, - branch.repository_id.name, + command = ("git clone %s -b %s %s") % ( + gh_repo.clone_url, branch.name, branch.local_path, ) @@ -254,7 +251,6 @@ def analyze_code_one(self): size += os.path.getsize(file_path) except Exception: _logger.warning("Warning : unable to eval the size of '%s'.", file_path) - try: Repo(path) except Exception: @@ -262,7 +258,6 @@ def analyze_code_one(self): # to be downloaded again self.state = "to_download" return {"size": 0} - return {"size": size} def _analyze_code(self): @@ -286,7 +281,6 @@ def _analyze_code(self): branch.write(vals) if partial_commit: self._cr.commit() # pylint: disable=invalid-commit - except Exception as e: _logger.warning( "Cannot analyze branch %s so skipping it, error " "is: %s", @@ -374,16 +368,16 @@ def _compute_local_path(self): ) for branch in self: branch.local_path = os.path.join( - source_path, branch.organization_id.github_login, branch.complete_name + source_path, branch.organization_id.github_name, branch.complete_name ) @api.depends( "name", "repository_id.name", - "organization_id.github_login", + "organization_id.github_name", "organization_id.coverage_url_pattern", ) - def _compute_coverage(self): + def _compute_coverage_url(self): for branch in self: if not branch.organization_id.coverage_url_pattern: branch.coverage_url = "" @@ -392,7 +386,7 @@ def _compute_coverage(self): # way org_id = branch.organization_id branch.coverage_url = org_id.coverage_url_pattern.format( - organization_name=org_id.github_login, + organization_name=org_id.github_name, repository_name=branch.repository_id.name, branch_name=branch.name, ) @@ -400,16 +394,16 @@ def _compute_coverage(self): @api.depends( "name", "repository_id.name", - "organization_id.github_login", + "organization_id.github_name", "organization_id.ci_url_pattern", ) - def _compute_ci(self): + def _compute_ci_url(self): for branch in self: if not branch.organization_id.ci_url_pattern: branch.ci_url = "" continue branch.ci_url = branch.organization_id.ci_url_pattern.format( - organization_name=branch.organization_id.github_login, + organization_name=branch.organization_id.github_name, repository_name=branch.repository_id.name, branch_name=branch.name, ) @@ -417,9 +411,8 @@ def _compute_ci(self): @api.depends("name", "repository_id.complete_name") def _compute_github_url(self): for branch in self: - branch.github_url = "https://github.com/{}/{}/tree/{}".format( - branch.organization_id.github_login, - branch.repository_id.name, + branch.github_url = "{}/tree/{}".format( + branch.repository_id.github_url, branch.name, ) diff --git a/github_connector/models/github_team.py b/github_connector/models/github_team.py index 850aa932..d7f0bb42 100644 --- a/github_connector/models/github_team.py +++ b/github_connector/models/github_team.py @@ -1,4 +1,5 @@ # Copyright (C) 2016-Today: Odoo Community Association (OCA) +# Copyright 2021 Tecnativa - João Marques # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -11,7 +12,6 @@ class GithubTeam(models.Model): _order = "name" _description = "Github Team" - _github_type = "team" _github_login_field = "slug" _PRIVACY_SELECTION = [("secret", "Secret"), ("closed", "Closed")] @@ -79,22 +79,22 @@ class GithubTeam(models.Model): ) # Compute Section - @api.depends("github_login", "organization_id.github_login") + @api.depends("github_name", "organization_id.github_name") def _compute_github_url(self): for team in self: team.github_url = ( "https://github.com/orgs/{organization_name}/" "teams/{team_name}".format( - organization_name=team.organization_id.github_login, - team_name=team.github_login, + organization_name=team.organization_id.github_name, + team_name=team.github_name, ) ) - @api.depends("name", "organization_id.github_login") + @api.depends("name", "organization_id.github_name") def _compute_complete_name(self): for team in self: team.complete_name = "{}/{}".format( - team.organization_id.github_login, team.github_login + team.organization_id.github_name, team.github_name ) @api.depends("partner_ids") @@ -115,67 +115,82 @@ def get_conversion_dict(self): return res @api.model - def get_odoo_data_from_github(self, data): + def get_odoo_data_from_github(self, gh_data): organization_obj = self.env["github.organization"] - res = super().get_odoo_data_from_github(data) - if data.get("organization", False): + res = super().get_odoo_data_from_github(gh_data) + if gh_data.organization: organization_id = organization_obj.get_from_id_or_create( - data["organization"] + gh_data=gh_data.organization ).id else: organization_id = False res.update({"organization_id": organization_id}) return res - def get_github_data_from_odoo(self): + def get_github_base_obj_for_creation(self): self.ensure_one() - return { - "name": self.name, - "description": self.description and self.description or "", - "privacy": self.privacy, - } + gh_api = self.get_github_connector() + return gh_api.get_organization(self.organization_id.github_name) - def get_github_args_for_creation(self): + def create_in_github(self): + """Create an object in Github through the API""" self.ensure_one() - return [self.organization_id.github_login] + # Create in Github + gh_base_obj = self.get_github_base_obj_for_creation() + gh_team = gh_base_obj.create_team( + name=self.name, description=self.description or "", privacy=self.privacy + ) + # Create in Odoo with the returned data and update object + data = self.get_odoo_data_from_github(gh_team) + new_item = self._create_from_github_data(data) + new_item.full_update() + new_item._hook_after_github_creation() + return new_item def full_update(self): self.button_sync_member() self.button_sync_repository() + def find_related_github_object(self, obj_id=None): + """Query Github API to find the related object""" + self.get_github_connector() + return self.organization_id.find_related_github_object().get_team( + int(obj_id or self.github_id_external) + ) + # Action Section def button_sync_member(self): partner_obj = self.env["res.partner"] - connector_member = self.get_github_connector("team_members_member") - connector_maintainer = self.get_github_connector("team_members_maintainer") + gh_team = self.find_related_github_object() for team in self: partner_data = [] - for data in connector_member.list([team.github_id_external]): - partner = partner_obj.get_from_id_or_create(data) + # Fetching the role after getting each user requires more API calls for + # each user, so we fetch the users in 2 steps, one for each role + for gh_user in gh_team.get_members(role="member"): + partner = partner_obj.get_from_id_or_create(gh_data=gh_user) partner_data.append({"partner_id": partner.id, "role": "member"}) - for data in connector_maintainer.list([team.github_id_external]): - partner = partner_obj.get_from_id_or_create(data) + for gh_user in gh_team.get_members(role="maintainer"): + partner = partner_obj.get_from_id_or_create(gh_data=gh_user) partner_data.append({"partner_id": partner.id, "role": "maintainer"}) team.partner_ids = [(2, x.id, False) for x in team.partner_ids] team.partner_ids = [(0, False, x) for x in partner_data] def button_sync_repository(self): repository_obj = self.env["github.repository"] - connector = self.get_github_connector("team_repositories") + gh_team = self.find_related_github_object() for team in self: repository_data = [] - for data in connector.list([team.github_id_external]): - repository = repository_obj.get_from_id_or_create(data) - if data["permissions"]["admin"] is True: + for gh_repo in gh_team.get_repos(): + repository = repository_obj.get_from_id_or_create(gh_data=gh_repo) + if gh_repo.permissions.admin: permission = "admin" - elif data["permissions"]["push"] is True: + elif gh_repo.permissions.push: permission = "write" else: permission = "read" repository_data.append( {"repository_id": repository.id, "permission": permission} ) - team.repository_ids = [(2, x.id, False) for x in team.repository_ids] team.repository_ids = [(0, False, x) for x in repository_data] diff --git a/github_connector/models/res_partner.py b/github_connector/models/res_partner.py index 235a6948..96ed19f3 100644 --- a/github_connector/models/res_partner.py +++ b/github_connector/models/res_partner.py @@ -1,7 +1,10 @@ # Copyright (C) 2016-Today: Odoo Community Association (OCA) +# Copyright 2021 Tecnativa - João Marques # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from github.GithubException import UnknownObjectException + from odoo import _, api, fields, models @@ -9,7 +12,6 @@ class ResPartner(models.Model): _name = "res.partner" _inherit = ["res.partner", "abstract.github.model"] - _github_type = "user" _github_login_field = "login" _need_individual_call = True _field_list_prevent_overwrite = ["name", "website", "email", "image_1920"] @@ -20,7 +22,7 @@ class ResPartner(models.Model): help="Check this box if this " "account is a bot or similar.", ) - github_team_ids = fields.Many2many( + github_team_partner_ids = fields.One2many( string="Teams", comodel_name="github.team.partner", inverse_name="partner_id", @@ -50,15 +52,15 @@ class ResPartner(models.Model): _sql_constraints = [ ( "github_login_uniq", - "unique(github_login)", + "unique(github_name)", "Two different partners cannot have the same Github Login", ) ] - @api.constrains("github_login", "is_company") + @api.constrains("github_name", "is_company") def _check_login_company(self): for partner in self: - if partner.is_company and partner.github_login: + if partner.is_company and partner.github_name: raise Warning( _("A company ('%s') can not have a Github login" " associated.") % partner.name @@ -70,10 +72,10 @@ def _compute_organization_qty(self): for partner in self: partner.organization_qty = len(partner.organization_ids) - @api.depends("github_team_ids") + @api.depends("github_team_partner_ids") def _compute_github_team_qty(self): for partner in self: - partner.github_team_qty = len(partner.github_team_ids) + partner.github_team_qty = len(partner.github_team_partner_ids) # Custom Section @api.model @@ -83,15 +85,23 @@ def get_conversion_dict(self): return res @api.model - def get_odoo_data_from_github(self, data): - res = super().get_odoo_data_from_github(data) - res.update({"name": data["name"] or "%s (Github)" % data["login"]}) - if "avatar_url" in data: + def get_odoo_data_from_github(self, gh_data): + res = super().get_odoo_data_from_github(gh_data) + res.update({"name": gh_data.name or "%s (Github)" % gh_data.login}) + if hasattr(gh_data, "avatar_url"): res.update( - {"image_1920": self.get_base64_image_from_github(data["avatar_url"])} + {"image_1920": self.get_base64_image_from_github(gh_data.avatar_url)} ) return res + def find_related_github_object(self, obj_id=None): + """Query Github API to find the related object""" + gh_api = self.get_github_connector() + try: + return gh_api.get_user_by_id(int(obj_id or self.github_id_external)) + except UnknownObjectException: + return gh_api.get_user(self.github_name) + def action_github_organization(self): self.ensure_one() action = self.env.ref("github_connector.action_github_organization").read()[0] diff --git a/github_connector/readme/CONFIGURE.rst b/github_connector/readme/CONFIGURE.rst index 925cd31f..b23fb6f7 100644 --- a/github_connector/readme/CONFIGURE.rst +++ b/github_connector/readme/CONFIGURE.rst @@ -12,13 +12,8 @@ Note: make sure that Odoo process has read / write access on that folder * ``github_token = your_github_access_token`` -or - - * ``github_login = your_github_login`` - * ``github_password = your_github_password`` - -Note: if token and login/password are provided, the token will be used. -The login/password auth will be deprecated by GitHub in the future. +Note: The login/password auth has been deprecated by GitHub. +https://docs.github.com/en/rest/overview/other-authentication-methods#via-username-and-password #. Go to 'Settings' / 'Technical' / 'Parameters' / 'System Parameters' and define the following values: diff --git a/github_connector/static/description/index.html b/github_connector/static/description/index.html index 42950acf..e9507d3d 100644 --- a/github_connector/static/description/index.html +++ b/github_connector/static/description/index.html @@ -367,7 +367,7 @@

    Github Connector

    !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

    Beta License: AGPL-3 OCA/interface-github Translate me on Weblate Try me on Runbot

    +

    Beta License: AGPL-3 OCA/interface-github Translate me on Weblate Try me on Runbot

    This module allows you to:

    • Fetch into Odoo social information from Github (Organizations, Teams, Users)
    • @@ -434,15 +434,8 @@

      Configuration

    • github_token = your_github_access_token
    -

    or

    -
    -
      -
    • github_login = your_github_login
    • -
    • github_password = your_github_password
    • -
    -
    -

    Note: if token and login/password are provided, the token will be used. -The login/password auth will be deprecated by GitHub in the future.

    +

    Note: The login/password auth has been deprecated by GitHub. +https://docs.github.com/en/rest/overview/other-authentication-methods#via-username-and-password

    1. Go to ‘Settings’ / ‘Technical’ / ‘Parameters’ / ‘System Parameters’ and define the following values:

      @@ -456,7 +449,7 @@

      Configuration

      download (potentially with a lot of repositories) in order to reduce the size of the transaction
    -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_settings.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_settings.png
  • Go to your(s) user(s) form to add them in the new ‘Connector Github Manager’ groups. The members of this group will have the possibility to run Github @@ -483,16 +476,16 @@

    Initial upload from Github

  • go to ‘Github’ / ‘Settings’ / ‘Sync Object’

  • Select the object type you want to synchronize and its Gthub name

    -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/sync_organization.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/sync_organization.png
  • Once done for your organization(s), go to ‘Github’ / ‘Github Commnunity’ / ‘Organizations’

    -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_organization_kanban.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_organization_kanban.png
  • Optionally, once organization is created, you can create series for your projects. Go to ‘Github’ / ‘Organizations’ / click on your organization / ‘Organization Series’ Tabs

    -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_organization_series.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_organization_series.png
  • @@ -507,11 +500,11 @@

    Select branches to download

  • In the ‘Settings’ tab, set the URL of the ‘External Services’ you use for Continuous Integration and Coverage.

    -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_organization_external_services.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_organization_external_services.png
  • Once done, click on buttons ‘Syncs’, to synchronize repositories, teams and members. (This process can take a while depending of your size)

    -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_organization_sync_buttons.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_organization_sync_buttons.png
  • @@ -520,14 +513,14 @@

    Team / members synchronization

    You can synchronize members teams:

    1. Go to ‘Teams’ / tree view / ‘Actions’ / ‘Update from Github’.

      -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_team_kanban.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_team_kanban.png
    2. In each team, you can see the members list and the role of the members

      -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_team_partner_kanban.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_team_partner_kanban.png
    3. In each team, you can see the repositories list but not the permissions of the team. (See ‘Known Issues’ Section)

      -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_team_repository_kanban.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_team_repository_kanban.png
    @@ -537,11 +530,11 @@

    Repositories synchronization

    1. Go to ‘Repositories’ / tree view / ‘Actions’ / ‘Update from Github’

      -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_repository_kanban.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_repository_kanban.png
    2. In each repository, you can see the main branches list and the size of code source.

      -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_repository_branch_kanban.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_repository_branch_kanban.png
    @@ -550,10 +543,10 @@

    Fetching the source code

    Finally, you can download locally the source code of all your branches:

    1. Go to ‘Repository Branches’ / tree view / ‘Actions’ / ‘Download and Analyse Source Code’.

      -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/wizard_download_analyze.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/wizard_download_analyze.png
    2. In the tree view you can update manually source code or refresh analysis.

      -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_repository_branch_list.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_repository_branch_list.png
    @@ -595,14 +588,14 @@

    Data creation in Github

  • Later on, a synchronization will be performed, to create the according team in the Odoo instance.
  • -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/wizard_create_team.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/wizard_create_team.png
  • Repositories:

    1. Go to ‘Settings’ / ‘Create Team in Github’.
    2. Set the information and click on Create in Github.
    -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/wizard_create_repository.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/wizard_create_repository.png
  • @@ -619,11 +612,11 @@

    Note

    Reporting

    This module provides several reports

    Branches by Serie

    -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/reporting_branches_by_serie.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/reporting_branches_by_serie.png

    Sizes by Serie

    -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/reporting_sizes_by_serie.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/reporting_sizes_by_serie.png

    Repository branch analysis rule

    -https://raw.githubusercontent.com/OCA/interface-github/13.0/github_connector/static/description/github_repository_branch_rule_info_report.png +https://raw.githubusercontent.com/OCA/interface-github/14.0/github_connector/static/description/github_repository_branch_rule_info_report.png
    @@ -660,7 +653,7 @@

    Bug Tracker

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -feedback.

    +feedback.

    Do not contact contributors directly about support or help with technical issues.

    @@ -687,6 +680,7 @@

    Contributors

  • Ernesto Tejeda
  • Carlos Roca
  • Víctor Martínez
  • +
  • João Marques
  • @@ -698,7 +692,7 @@

    Maintainers

    OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

    -

    This module is part of the OCA/interface-github project on GitHub.

    +

    This module is part of the OCA/interface-github project on GitHub.

    You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

    diff --git a/github_connector/tests/res/github_repo_20881668_response.json b/github_connector/tests/res/github_repo_20881668_response.json new file mode 100644 index 00000000..ea76151c --- /dev/null +++ b/github_connector/tests/res/github_repo_20881668_response.json @@ -0,0 +1,123 @@ +{ + "id": 20881668, + "node_id": "MDEwOlJlcG9zaXRvcnkyMDg4MTY2OA==", + "name": "account-analytic", + "full_name": "OCA/account-analytic", + "private": false, + "owner": { + "login": "OCA", + "id": 7600578, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc2MDA1Nzg=", + "avatar_url": "https://avatars.githubusercontent.com/u/7600578?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/OCA", + "html_url": "https://github.com/OCA", + "followers_url": "https://api.github.com/users/OCA/followers", + "following_url": "https://api.github.com/users/OCA/following{/other_user}", + "gists_url": "https://api.github.com/users/OCA/gists{/gist_id}", + "starred_url": "https://api.github.com/users/OCA/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/OCA/subscriptions", + "organizations_url": "https://api.github.com/users/OCA/orgs", + "repos_url": "https://api.github.com/users/OCA/repos", + "events_url": "https://api.github.com/users/OCA/events{/privacy}", + "received_events_url": "https://api.github.com/users/OCA/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/OCA/account-analytic", + "description": "Odoo Account Analytic Related Addons", + "fork": false, + "url": "https://api.github.com/repos/OCA/account-analytic", + "forks_url": "https://api.github.com/repos/OCA/account-analytic/forks", + "keys_url": "https://api.github.com/repos/OCA/account-analytic/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/OCA/account-analytic/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/OCA/account-analytic/teams", + "hooks_url": "https://api.github.com/repos/OCA/account-analytic/hooks", + "issue_events_url": "https://api.github.com/repos/OCA/account-analytic/issues/events{/number}", + "events_url": "https://api.github.com/repos/OCA/account-analytic/events", + "assignees_url": "https://api.github.com/repos/OCA/account-analytic/assignees{/user}", + "branches_url": "https://api.github.com/repos/OCA/account-analytic/branches{/branch}", + "tags_url": "https://api.github.com/repos/OCA/account-analytic/tags", + "blobs_url": "https://api.github.com/repos/OCA/account-analytic/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/OCA/account-analytic/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/OCA/account-analytic/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/OCA/account-analytic/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/OCA/account-analytic/statuses/{sha}", + "languages_url": "https://api.github.com/repos/OCA/account-analytic/languages", + "stargazers_url": "https://api.github.com/repos/OCA/account-analytic/stargazers", + "contributors_url": "https://api.github.com/repos/OCA/account-analytic/contributors", + "subscribers_url": "https://api.github.com/repos/OCA/account-analytic/subscribers", + "subscription_url": "https://api.github.com/repos/OCA/account-analytic/subscription", + "commits_url": "https://api.github.com/repos/OCA/account-analytic/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/OCA/account-analytic/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/OCA/account-analytic/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/OCA/account-analytic/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/OCA/account-analytic/contents/{+path}", + "compare_url": "https://api.github.com/repos/OCA/account-analytic/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/OCA/account-analytic/merges", + "archive_url": "https://api.github.com/repos/OCA/account-analytic/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/OCA/account-analytic/downloads", + "issues_url": "https://api.github.com/repos/OCA/account-analytic/issues{/number}", + "pulls_url": "https://api.github.com/repos/OCA/account-analytic/pulls{/number}", + "milestones_url": "https://api.github.com/repos/OCA/account-analytic/milestones{/number}", + "notifications_url": "https://api.github.com/repos/OCA/account-analytic/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/OCA/account-analytic/labels{/name}", + "releases_url": "https://api.github.com/repos/OCA/account-analytic/releases{/id}", + "deployments_url": "https://api.github.com/repos/OCA/account-analytic/deployments", + "created_at": "2014-06-16T10:55:18Z", + "updated_at": "2021-07-05T16:49:21Z", + "pushed_at": "2021-07-07T09:59:23Z", + "git_url": "git://github.com/OCA/account-analytic.git", + "ssh_url": "git@github.com:OCA/account-analytic.git", + "clone_url": "https://github.com/OCA/account-analytic.git", + "svn_url": "https://github.com/OCA/account-analytic", + "homepage": "", + "size": 2960, + "stargazers_count": 55, + "watchers_count": 55, + "language": "HTML", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 249, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 88, + "license": { + "key": "agpl-3.0", + "name": "GNU Affero General Public License v3.0", + "spdx_id": "AGPL-3.0", + "url": "https://api.github.com/licenses/agpl-3.0", + "node_id": "MDc6TGljZW5zZTE=" + }, + "forks": 249, + "open_issues": 88, + "watchers": 55, + "default_branch": "12.0", + "temp_clone_token": null, + "organization": { + "login": "OCA", + "id": 7600578, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc2MDA1Nzg=", + "avatar_url": "https://avatars.githubusercontent.com/u/7600578?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/OCA", + "html_url": "https://github.com/OCA", + "followers_url": "https://api.github.com/users/OCA/followers", + "following_url": "https://api.github.com/users/OCA/following{/other_user}", + "gists_url": "https://api.github.com/users/OCA/gists{/gist_id}", + "starred_url": "https://api.github.com/users/OCA/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/OCA/subscriptions", + "organizations_url": "https://api.github.com/users/OCA/orgs", + "repos_url": "https://api.github.com/users/OCA/repos", + "events_url": "https://api.github.com/users/OCA/events{/privacy}", + "received_events_url": "https://api.github.com/users/OCA/received_events", + "type": "Organization", + "site_admin": false + }, + "network_count": 249, + "subscribers_count": 63 +} diff --git a/github_connector/tests/res/github_search_issues_response.json b/github_connector/tests/res/github_search_issues_response.json new file mode 100644 index 00000000..508b4e6f --- /dev/null +++ b/github_connector/tests/res/github_search_issues_response.json @@ -0,0 +1,100 @@ +{ + "total_count": 280, + "incomplete_results": false, + "items": [ + { + "url": "https://api.github.com/repos/batterseapower/pinyin-toolkit/issues/132", + "repository_url": "https://api.github.com/repos/batterseapower/pinyin-toolkit", + "labels_url": "https://api.github.com/repos/batterseapower/pinyin-toolkit/issues/132/labels{/name}", + "comments_url": "https://api.github.com/repos/batterseapower/pinyin-toolkit/issues/132/comments", + "events_url": "https://api.github.com/repos/batterseapower/pinyin-toolkit/issues/132/events", + "html_url": "https://github.com/batterseapower/pinyin-toolkit/issues/132", + "id": 35802, + "node_id": "MDU6SXNzdWUzNTgwMg==", + "number": 132, + "title": "Line Number Indexes Beyond 20 Not Displayed", + "user": { + "login": "Nick3C", + "id": 90254, + "node_id": "MDQ6VXNlcjkwMjU0", + "avatar_url": "https://secure.gravatar.com/avatar/934442aadfe3b2f4630510de416c5718?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png", + "gravatar_id": "", + "url": "https://api.github.com/users/Nick3C", + "html_url": "https://github.com/Nick3C", + "followers_url": "https://api.github.com/users/Nick3C/followers", + "following_url": "https://api.github.com/users/Nick3C/following{/other_user}", + "gists_url": "https://api.github.com/users/Nick3C/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Nick3C/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Nick3C/subscriptions", + "organizations_url": "https://api.github.com/users/Nick3C/orgs", + "repos_url": "https://api.github.com/users/Nick3C/repos", + "events_url": "https://api.github.com/users/Nick3C/events{/privacy}", + "received_events_url": "https://api.github.com/users/Nick3C/received_events", + "type": "User", + "site_admin": true + }, + "labels": [ + { + "id": 4, + "node_id": "MDU6TGFiZWw0", + "url": "https://api.github.com/repos/batterseapower/pinyin-toolkit/labels/bug", + "name": "bug", + "color": "ff0000" + } + ], + "state": "open", + "assignee": null, + "milestone": { + "url": "https://api.github.com/repos/octocat/Hello-World/milestones/1", + "html_url": "https://github.com/octocat/Hello-World/milestones/v1.0", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/milestones/1/labels", + "id": 1002604, + "node_id": "MDk6TWlsZXN0b25lMTAwMjYwNA==", + "number": 1, + "state": "open", + "title": "v1.0", + "description": "Tracking milestone for version 1.0", + "creator": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "open_issues": 4, + "closed_issues": 8, + "created_at": "2011-04-10T20:09:31Z", + "updated_at": "2014-03-03T18:58:10Z", + "closed_at": "2013-02-12T13:22:01Z", + "due_on": "2012-10-09T23:39:01Z" + }, + "comments": 15, + "created_at": "2009-07-12T20:10:41Z", + "updated_at": "2009-07-19T09:23:43Z", + "closed_at": null, + "pull_request": { + "url": "https://api/github.com/repos/octocat/Hello-World/pull/1347", + "html_url": "https://github.com/octocat/Hello-World/pull/1347", + "diff_url": "https://github.com/octocat/Hello-World/pull/1347.diff", + "patch_url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347" + }, + "body": "...", + "score": 1, + "locked": true, + "author_association": "COLLABORATOR" + } + ] +} diff --git a/github_connector/tests/res/github_user_OCA-git-bot_response.json b/github_connector/tests/res/github_user_OCA-git-bot_response.json new file mode 100644 index 00000000..0eb0bf23 --- /dev/null +++ b/github_connector/tests/res/github_user_OCA-git-bot_response.json @@ -0,0 +1,34 @@ +{ + "login": "OCA-git-bot", + "id": 8723280, + "node_id": "MDQ6VXNlcjg3MjMyODA=", + "avatar_url": "https://avatars.githubusercontent.com/u/8723280?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/OCA-git-bot", + "html_url": "https://github.com/OCA-git-bot", + "followers_url": "https://api.github.com/users/OCA-git-bot/followers", + "following_url": "https://api.github.com/users/OCA-git-bot/following{/other_user}", + "gists_url": "https://api.github.com/users/OCA-git-bot/gists{/gist_id}", + "starred_url": "https://api.github.com/users/OCA-git-bot/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/OCA-git-bot/subscriptions", + "organizations_url": "https://api.github.com/users/OCA-git-bot/orgs", + "repos_url": "https://api.github.com/users/OCA-git-bot/repos", + "events_url": "https://api.github.com/users/OCA-git-bot/events{/privacy}", + "received_events_url": "https://api.github.com/users/OCA-git-bot/received_events", + "type": "User", + "site_admin": false, + "name": "OCA Bot", + "company": "OCA", + "blog": "", + "location": null, + "email": null, + "hireable": null, + "bio": null, + "twitter_username": null, + "public_repos": 1, + "public_gists": 0, + "followers": 24, + "following": 0, + "created_at": "2014-09-10T13:03:33Z", + "updated_at": "2021-05-15T09:42:06Z" +} diff --git a/github_connector/tests/test_github_analysis_rule.py b/github_connector/tests/test_github_analysis_rule.py index 8329bc0a..0f449e14 100644 --- a/github_connector/tests/test_github_analysis_rule.py +++ b/github_connector/tests/test_github_analysis_rule.py @@ -1,6 +1,12 @@ # Copyright 2020 Tecnativa - Víctor Martínez +# Copyright 2021 Tecnativa - João Marques # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +import json + +import responses + +from odoo.modules.module import get_resource_path from odoo.tests.common import SavepointCase @@ -63,7 +69,8 @@ def setUpClass(cls): "description": "The GitHub repos for all Open Source work around Odoo", "website_url": "https://odoo-community.org/", "github_url": "https://github.com/OCA", - "github_login": "OCA", + "github_name": "OCA", + "github_id_external": 7600578, "analysis_rule_ids": [ (4, cls.analysis_rule_python.id), (4, cls.analysis_rule_xml.id), @@ -81,7 +88,8 @@ def setUpClass(cls): { "name": "OCB", "organization_id": cls.organization_oca.id, - "github_login": "%s/OCB" % cls.organization_oca.github_login, + "github_name": "%s/OCB" % cls.organization_oca.github_name, + "github_id_external": 20558462, "analysis_rule_ids": [(4, cls.analysis_rule_ocb.id)], } ) @@ -89,8 +97,8 @@ def setUpClass(cls): { "name": "account-analytic", "organization_id": cls.organization_oca.id, - "github_login": "%s/account-analytic" - % cls.organization_oca.github_login, + "github_id_external": 20881668, + "github_name": "%s/account-analytic" % cls.organization_oca.github_name, } ) # repository branch @@ -113,7 +121,22 @@ def setUpClass(cls): "analysis_rule_ids": [(4, cls.analysis_rule_custom.id)], } ) + cls.env["ir.config_parameter"].set_param("github.access_token", "test") + # Create appropriate responses for the API calls + with open( + get_resource_path( + "github_connector", "tests", "res", "github_repo_20881668_response.json" + ) + ) as jsonfile: + cls.repo_data = json.loads(jsonfile.read()) + responses.add( + responses.GET, + "https://api.github.com:443/repositories/20881668", + json=cls.repo_data, + status=200, + ) + @responses.activate def test_github_analysis_rule(self): self.assertEqual(len(self.organization_oca.analysis_rule_ids), 3) self.assertEqual(len(self.repository_ocb.analysis_rule_ids), 1) diff --git a/github_connector/tests/test_github_connector.py b/github_connector/tests/test_github_connector.py index 41f2a971..de309692 100644 --- a/github_connector/tests/test_github_connector.py +++ b/github_connector/tests/test_github_connector.py @@ -1,6 +1,12 @@ # Copyright 2021 Tecnativa - Víctor Martínez +# Copyright 2021 Tecnativa - João Marques # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import json + +import responses + +from odoo.modules.module import get_resource_path from odoo.tests import common @@ -9,16 +15,46 @@ class TestGithubConnector(common.SavepointCase): def setUpClass(cls): super().setUpClass() cls.model = cls.env["res.partner"] - cls.model._need_individual_call = False + cls.env["ir.config_parameter"].set_param("github.access_token", "test") + # Create appropriate responses for the API calls + with open( + get_resource_path( + "github_connector", + "tests", + "res", + "github_user_OCA-git-bot_response.json", + ) + ) as jsonfile: + cls.user_data = json.loads(jsonfile.read()) + responses.add( + responses.GET, + "https://api.github.com:443/users/OCA-git-bot", + json=cls.user_data, + status=200, + ) + responses.add( + responses.GET, + "https://api.github.com:443/user/8723280", + json=cls.user_data, + status=200, + ) + responses.add( + responses.GET, + "https://api.github.com:443/orgs/OCA-git-bot", + json={ + "message": "Not Found", + }, + status=404, + ) + @responses.activate def test_partner_get_from_id_or_create(self): - data = {"id": "10", "name": "Mr Odoo", "url": "https://github.com"} - partner = self.model.get_from_id_or_create(data) - self.assertEqual(partner.name, data["name"]) + partner = self.model.create_from_name("OCA-git-bot") + self.assertEqual(partner.github_name, "OCA-git-bot") # Check create process not really create new record - res = self.model.get_from_id_or_create(data) + res = self.model.get_from_id_or_create(data={"login": "OCA-git-bot"}) self.assertEqual(partner.id, res.id) # Try to archive record and try to create again partner.active = False - res = self.model.get_from_id_or_create(data) + res = self.model.get_from_id_or_create(data={"login": "OCA-git-bot"}) self.assertEqual(partner.id, res.id) diff --git a/github_connector/views/view_github_organization.xml b/github_connector/views/view_github_organization.xml index 0ae19463..8c60b645 100644 --- a/github_connector/views/view_github_organization.xml +++ b/github_connector/views/view_github_organization.xml @@ -12,7 +12,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -21,7 +21,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). github.organization - + @@ -168,7 +168,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - + @@ -205,7 +205,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - + @@ -227,7 +227,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

    - +

    @@ -250,7 +250,10 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

    - + diff --git a/github_connector/views/view_github_repository.xml b/github_connector/views/view_github_repository.xml index c9eb1ffd..2f7757bd 100644 --- a/github_connector/views/view_github_repository.xml +++ b/github_connector/views/view_github_repository.xml @@ -111,7 +111,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - + @@ -181,7 +181,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - + diff --git a/github_connector/views/view_github_repository_branch.xml b/github_connector/views/view_github_repository_branch.xml index 266d0a77..f00ac486 100644 --- a/github_connector/views/view_github_repository_branch.xml +++ b/github_connector/views/view_github_repository_branch.xml @@ -243,7 +243,10 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). t-att-href="record.github_url.value" > - + - + @@ -107,7 +107,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - + @@ -85,14 +85,14 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - + diff --git a/github_connector/wizards/wizard_create_repository.py b/github_connector/wizards/wizard_create_repository.py index 5dacf0ec..90773451 100644 --- a/github_connector/wizards/wizard_create_repository.py +++ b/github_connector/wizards/wizard_create_repository.py @@ -23,5 +23,5 @@ def get_github_data_from_odoo(self): def button_create_in_github(self): self.ensure_one() - new_item = self.create_in_github(self.env["github.repository"]) + new_item = self.create_in_github() return new_item.get_action() diff --git a/github_connector/wizards/wizard_create_team.py b/github_connector/wizards/wizard_create_team.py index cb85f135..50dcf6d8 100644 --- a/github_connector/wizards/wizard_create_team.py +++ b/github_connector/wizards/wizard_create_team.py @@ -20,7 +20,7 @@ class WizardCreateTeam(models.TransientModel): wizard_partner_ids = fields.Many2many( string="Team Members", comodel_name="res.partner", - domain="[('github_login', '!=', False)]", + domain="[('github_name', '!=', False)]", ) wizard_repository_ids = fields.Many2many( @@ -33,10 +33,10 @@ def get_github_data_from_odoo(self): res.update( { "maintainers": [ - x.github_login for x in self.wizard_partner_ids if x.github_login + x.github_name for x in self.wizard_partner_ids if x.github_name ], "repo_names": [ - x.github_login for x in self.wizard_repository_ids if x.github_login + x.github_name for x in self.wizard_repository_ids if x.github_name ], } ) @@ -44,5 +44,5 @@ def get_github_data_from_odoo(self): def button_create_in_github(self): self.ensure_one() - new_item = self.create_in_github(self.env["github.team"]) + new_item = self.env["github.team"].create_in_github() return new_item.get_action() diff --git a/github_connector/wizards/wizard_load_github_model.py b/github_connector/wizards/wizard_load_github_model.py index aa3a1e71..9bc73e65 100644 --- a/github_connector/wizards/wizard_load_github_model.py +++ b/github_connector/wizards/wizard_load_github_model.py @@ -4,8 +4,6 @@ from odoo import fields, models -from ..models.github import _GITHUB_TYPE - class WizardLoadGithubModel(models.TransientModel): _name = "wizard.load.github.model" @@ -13,7 +11,11 @@ class WizardLoadGithubModel(models.TransientModel): # Columns Section github_type = fields.Selection( - selection=_GITHUB_TYPE, + selection=[ + ("organization", "Organization"), + ("repository", "Repository"), + ("user", "User"), + ], string="Github Type Name", default="organization", required=True, From be3d82fe879f9cf7db0812c2eed1007072f491d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Ra=C3=AFch?= Date: Thu, 28 Oct 2021 10:29:40 +0200 Subject: [PATCH 46/72] [FIX] github_connector: migration scripts --- .../migrations/14.0.1.0.0/pre-migration.py | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/github_connector/migrations/14.0.1.0.0/pre-migration.py b/github_connector/migrations/14.0.1.0.0/pre-migration.py index ac88a167..8de93051 100644 --- a/github_connector/migrations/14.0.1.0.0/pre-migration.py +++ b/github_connector/migrations/14.0.1.0.0/pre-migration.py @@ -2,29 +2,22 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from openupgradelib import openupgrade -column_renames = { - "res_partner": [ - ("github_team_ids", "github_team_partner_ids"), - ("github_login", "github_name"), - ], - "github_organization": [ - ("github_login", "github_name"), - ], - "github_repository_branch": [ - ("github_login", "github_name"), - ], - "github_repository": [ - ("github_login", "github_name"), - ], - "github_team_partner": [ - ("github_login", "github_name"), - ], - "github_team": [ - ("github_login", "github_name"), - ], -} +field_renames = [ + ("res.partner", "res_partner", "github_team_ids", "github_team_partner_ids"), + ("res.partner", "res_partner", "github_login", "github_name"), + ("github.organization", "github_organization", "github_login", "github_name"), + ( + "github.repository.branch", + "github_repository_branch", + "github_login", + "github_name", + ), + ("github.repository", "github_repository", "github_login", "github_name"), + ("github.team.partner", "github_team_partner", "github_login", "github_name"), + ("github.team", "github_team", "github_login", "github_name"), +] @openupgrade.migrate() def migrate(env, version): - openupgrade.rename_columns(env.cr, column_renames) + openupgrade.rename_fields(env, field_renames) From e355f304f14773ae66324f4f1e76d489c60f0659 Mon Sep 17 00:00:00 2001 From: Eduardo de Miguel Date: Fri, 18 Feb 2022 15:40:36 +0100 Subject: [PATCH 47/72] [ADD] Add dependency on README Missed dependency [UPD] README.rst github_connector 14.0.1.0.1 [IMP] update dotfiles [ci skip] --- github_connector/README.rst | 7 ++++--- github_connector/__manifest__.py | 2 +- github_connector/models/github_repository_branch.py | 2 +- github_connector/readme/INSTALL.rst | 7 ++++--- github_connector/static/description/index.html | 7 ++++--- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/github_connector/README.rst b/github_connector/README.rst index b3b86271..4d1efc9b 100644 --- a/github_connector/README.rst +++ b/github_connector/README.rst @@ -45,9 +45,10 @@ To install this addon, you need to install some python dependencies .. code-block:: bash - ``sudo pip install PyGitHub`` - ``sudo pip install pygount`` - ``sudo pip install pathspec`` + sudo pip install PyGitHub + sudo pip install pygount + sudo pip install pathspec + sudo pip install GitPython Analysis source code is generated by https://github.com/roskakori/pygount diff --git a/github_connector/__manifest__.py b/github_connector/__manifest__.py index f43f5f75..32555da6 100644 --- a/github_connector/__manifest__.py +++ b/github_connector/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Github Connector", "summary": "Synchronize information from Github repositories", - "version": "14.0.1.0.0", + "version": "14.0.1.0.1", "category": "Connector", "license": "AGPL-3", "author": "Odoo Community Association (OCA), GRAP, Akretion, Tecnativa", diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index 1b80130f..ecb8cc17 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -347,7 +347,7 @@ def _compute_complete_name(self): @api.depends("size") def _compute_mb_size(self): for branch in self: - branch.mb_size = float(branch.size) / (1024 ** 2) + branch.mb_size = float(branch.size) / (1024**2) @api.depends("organization_id", "name") def _compute_organization_serie_id(self): diff --git a/github_connector/readme/INSTALL.rst b/github_connector/readme/INSTALL.rst index d291d83c..181fc869 100644 --- a/github_connector/readme/INSTALL.rst +++ b/github_connector/readme/INSTALL.rst @@ -2,8 +2,9 @@ To install this addon, you need to install some python dependencies .. code-block:: bash - ``sudo pip install PyGitHub`` - ``sudo pip install pygount`` - ``sudo pip install pathspec`` + sudo pip install PyGitHub + sudo pip install pygount + sudo pip install pathspec + sudo pip install GitPython Analysis source code is generated by https://github.com/roskakori/pygount diff --git a/github_connector/static/description/index.html b/github_connector/static/description/index.html index e9507d3d..e8512c51 100644 --- a/github_connector/static/description/index.html +++ b/github_connector/static/description/index.html @@ -410,9 +410,10 @@

    Github Connector

    Installation

    To install this addon, you need to install some python dependencies

    -``sudo pip install PyGitHub``
    -``sudo pip install pygount``
    -``sudo pip install pathspec``
    +sudo pip install PyGitHub
    +sudo pip install pygount
    +sudo pip install pathspec
    +sudo pip install GitPython
     

    Analysis source code is generated by https://github.com/roskakori/pygount

    From 03e6288a22c9bb80ddb21558aff078661d3fdc3f Mon Sep 17 00:00:00 2001 From: diga Date: Fri, 20 May 2022 21:39:09 +0500 Subject: [PATCH 48/72] [FIX] github_connector_odoo: Expected singleton: github.repository github_connector 14.0.1.0.2 --- github_connector/__manifest__.py | 2 +- github_connector/models/github_repository.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/github_connector/__manifest__.py b/github_connector/__manifest__.py index 32555da6..4ad4df0b 100644 --- a/github_connector/__manifest__.py +++ b/github_connector/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Github Connector", "summary": "Synchronize information from Github repositories", - "version": "14.0.1.0.1", + "version": "14.0.1.0.2", "category": "Connector", "license": "AGPL-3", "author": "Odoo Community Association (OCA), GRAP, Akretion, Tecnativa", diff --git a/github_connector/models/github_repository.py b/github_connector/models/github_repository.py index f321a11d..9659211a 100644 --- a/github_connector/models/github_repository.py +++ b/github_connector/models/github_repository.py @@ -169,9 +169,9 @@ def cron_update_branch_list(self): return True def button_sync_branch(self): - gh_repo = self.find_related_github_object() branch_obj = self.env["github.repository.branch"] for repository in self.filtered(lambda r: not r.is_ignored): + gh_repo = repository.find_related_github_object() branch_ids = [] correct_series = repository.organization_id.organization_serie_ids.mapped( "name" From 46b95b980eaaacecf00c18f6b2236fdacc51367a Mon Sep 17 00:00:00 2001 From: Giovanni Date: Tue, 28 Jun 2022 17:45:18 +0200 Subject: [PATCH 49/72] [14.0][FIX] github_connector_*, fix smart button open actions github_connector 14.0.1.0.3 --- github_connector/__manifest__.py | 2 +- github_connector/models/github_organization.py | 8 +++++--- github_connector/models/github_repository.py | 16 ++++++++++------ github_connector/models/github_team.py | 16 ++++++++++------ github_connector/models/res_partner.py | 12 ++++++++---- 5 files changed, 34 insertions(+), 20 deletions(-) diff --git a/github_connector/__manifest__.py b/github_connector/__manifest__.py index 4ad4df0b..263619e9 100644 --- a/github_connector/__manifest__.py +++ b/github_connector/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Github Connector", "summary": "Synchronize information from Github repositories", - "version": "14.0.1.0.2", + "version": "14.0.1.0.3", "category": "Connector", "license": "AGPL-3", "author": "Odoo Community Association (OCA), GRAP, Akretion, Tecnativa", diff --git a/github_connector/models/github_organization.py b/github_connector/models/github_organization.py index c2569cd7..b4f1fc34 100644 --- a/github_connector/models/github_organization.py +++ b/github_connector/models/github_organization.py @@ -201,7 +201,9 @@ def button_sync_team(self): def action_github_repository(self): self.ensure_one() - action = self.env.ref("github_connector.action_github_repository").read()[0] + action = ( + self.sudo().env.ref("github_connector.action_github_repository").read()[0] + ) action["context"] = dict(self.env.context) action["context"].pop("group_by", None) action["context"]["search_default_organization_id"] = self.id @@ -209,7 +211,7 @@ def action_github_repository(self): def action_github_team(self): self.ensure_one() - action = self.env.ref("github_connector.action_github_team").read()[0] + action = self.sudo().env.ref("github_connector.action_github_team").read()[0] action["context"] = dict(self.env.context) action["context"].pop("group_by", None) action["context"]["search_default_organization_id"] = self.id @@ -217,7 +219,7 @@ def action_github_team(self): def action_res_partner(self): self.ensure_one() - action = self.env.ref("github_connector.action_res_partner").read()[0] + action = self.sudo().env.ref("github_connector.action_res_partner").read()[0] action["context"] = dict(self.env.context) action["context"].pop("group_by", None) action["context"]["search_default_organization_ids"] = self.id diff --git a/github_connector/models/github_repository.py b/github_connector/models/github_repository.py index 9659211a..f6fbdb5a 100644 --- a/github_connector/models/github_repository.py +++ b/github_connector/models/github_repository.py @@ -195,9 +195,11 @@ def button_sync_branch(self): def action_github_team_repository_from_repository(self): self.ensure_one() - action = self.env.ref( - "github_connector.action_github_team_repository_from_repository" - ).read()[0] + action = ( + self.sudo() + .env.ref("github_connector.action_github_team_repository_from_repository") + .read()[0] + ) action["context"] = dict(self.env.context) action["context"].pop("group_by", None) action["context"]["search_default_repository_id"] = self.id @@ -205,9 +207,11 @@ def action_github_team_repository_from_repository(self): def action_github_repository_branch(self): self.ensure_one() - action = self.env.ref( - "github_connector.action_github_repository_branch" - ).read()[0] + action = ( + self.sudo() + .env.ref("github_connector.action_github_repository_branch") + .read()[0] + ) action["context"] = dict(self.env.context) action["context"].pop("group_by", None) action["context"]["search_default_repository_id"] = self.id diff --git a/github_connector/models/github_team.py b/github_connector/models/github_team.py index d7f0bb42..f30679d4 100644 --- a/github_connector/models/github_team.py +++ b/github_connector/models/github_team.py @@ -196,9 +196,11 @@ def button_sync_repository(self): def action_github_team_partner_from_team(self): self.ensure_one() - action = self.env.ref( - "github_connector.action_github_team_partner_from_team" - ).read()[0] + action = ( + self.sudo() + .env.ref("github_connector.action_github_team_partner_from_team") + .read()[0] + ) action["context"] = dict(self.env.context) action["context"].pop("group_by", None) action["context"]["search_default_team_id"] = self.id @@ -206,9 +208,11 @@ def action_github_team_partner_from_team(self): def action_github_team_repository_from_team(self): self.ensure_one() - action = self.env.ref( - "github_connector.action_github_team_repository_from_team" - ).read()[0] + action = ( + self.sudo() + .env.ref("github_connector.action_github_team_repository_from_team") + .read()[0] + ) action["context"] = dict(self.env.context) action["context"].pop("group_by", None) action["context"]["search_default_team_id"] = self.id diff --git a/github_connector/models/res_partner.py b/github_connector/models/res_partner.py index 96ed19f3..da5bc66e 100644 --- a/github_connector/models/res_partner.py +++ b/github_connector/models/res_partner.py @@ -104,7 +104,9 @@ def find_related_github_object(self, obj_id=None): def action_github_organization(self): self.ensure_one() - action = self.env.ref("github_connector.action_github_organization").read()[0] + action = ( + self.sudo().env.ref("github_connector.action_github_organization").read()[0] + ) action["context"] = dict(self.env.context) action["context"].pop("group_by", None) action["context"]["search_default_member_ids"] = self.id @@ -112,9 +114,11 @@ def action_github_organization(self): def action_github_team_partner_from_partner(self): self.ensure_one() - action = self.env.ref( - "github_connector.action_github_team_partner_from_partner" - ).read()[0] + action = ( + self.sudo() + .env.ref("github_connector.action_github_team_partner_from_partner") + .read()[0] + ) action["context"] = dict(self.env.context) action["context"].pop("group_by", None) action["context"]["search_default_partner_id"] = self.id From 2731faa282a0b90f4b9924de6791c064b885ad12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Thu, 17 Sep 2020 13:46:44 +0200 Subject: [PATCH 50/72] [IMP] github_connector_odoo: Code analysis TT25583 [UPD] README.rst github_connector 14.0.2.0.0 --- github_connector/__manifest__.py | 2 +- .../demo/github_analysis_rule_demo.xml | 8 +- .../models/abstract_github_model.py | 10 +- .../models/github_analysis_rule.py | 6 +- .../models/github_repository_branch.py | 35 +- github_connector/models/res_partner.py | 3 +- github_connector/tests/__init__.py | 5 +- github_connector/tests/common.py | 61 ++++ .../res/github_repo_20558462_response.json | 338 ++++++++++++++++++ .../res/github_repo_20881668_response.json | 123 ------- .../res/github_repo_70173147_response.json | 128 +++++++ .../tests/test_github_analysis_rule.py | 212 ++++------- .../tests/test_github_connector.py | 16 +- .../views/view_github_repository_branch.xml | 6 +- 14 files changed, 650 insertions(+), 303 deletions(-) create mode 100644 github_connector/tests/common.py create mode 100644 github_connector/tests/res/github_repo_20558462_response.json delete mode 100644 github_connector/tests/res/github_repo_20881668_response.json create mode 100644 github_connector/tests/res/github_repo_70173147_response.json diff --git a/github_connector/__manifest__.py b/github_connector/__manifest__.py index 263619e9..084de994 100644 --- a/github_connector/__manifest__.py +++ b/github_connector/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Github Connector", "summary": "Synchronize information from Github repositories", - "version": "14.0.1.0.3", + "version": "14.0.2.0.0", "category": "Connector", "license": "AGPL-3", "author": "Odoo Community Association (OCA), GRAP, Akretion, Tecnativa", diff --git a/github_connector/demo/github_analysis_rule_demo.xml b/github_connector/demo/github_analysis_rule_demo.xml index 5decd0bd..ae5d6fee 100644 --- a/github_connector/demo/github_analysis_rule_demo.xml +++ b/github_connector/demo/github_analysis_rule_demo.xml @@ -4,22 +4,22 @@ Copyright 2020 Tecnativa - Víctor Martínez License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> - + Python files *.py - + XML files *.xml - + JS files *.js - + Test files /tests/*.py diff --git a/github_connector/models/abstract_github_model.py b/github_connector/models/abstract_github_model.py index 132e18bd..a9d2f22f 100644 --- a/github_connector/models/abstract_github_model.py +++ b/github_connector/models/abstract_github_model.py @@ -11,7 +11,7 @@ from github import Github from github.GithubException import UnknownObjectException -from odoo import _, api, exceptions, fields, models, tools +from odoo import _, api, fields, models, tools from odoo.exceptions import UserError _logger = logging.getLogger(__name__) @@ -51,7 +51,7 @@ class AbstractGithubModel(models.AbstractModel): # Overloadable Section def github_login_field(self): if self._github_login_field is None: - raise exceptions.Warning( + raise UserError( _( "Feature not Implemented : Please define 'github_login_field'" " function in child model." @@ -101,7 +101,7 @@ def get_github_base_obj_for_creation(self): Usefull only if your model implements creation in github """ self.ensure_one() - raise exceptions.Warning( + raise UserError( _( "Feature not Implemented : Please define" " 'get_github_base_obj_for_creation' function in child model." @@ -260,7 +260,7 @@ def get_base64_image_from_github(self, url): except Exception as err: _logger.warning("URL Call Error. %s" % (err.__str__())) else: - raise exceptions.Warning(_("Maximum attempts reached.")) + raise UserError(_("Maximum attempts reached.")) return base64.standard_b64encode(stream) # Custom Private Function @@ -295,7 +295,7 @@ def get_github_connector(self): "github.access_token", default="" ) if not token: - raise exceptions.Warning( + raise UserError( _( "Please add the 'github_token' in Odoo configuration file" " or as the 'github.access_token' configuration parameter." diff --git a/github_connector/models/github_analysis_rule.py b/github_connector/models/github_analysis_rule.py index ff5162e5..a8de47ba 100644 --- a/github_connector/models/github_analysis_rule.py +++ b/github_connector/models/github_analysis_rule.py @@ -25,13 +25,15 @@ class GithubAnalysisRule(models.Model): required=True, ) + def _set_spec(self, lines): + return pathspec.PathSpec.from_lines("gitwildmatch", lines) + def _get_matches(self, path): """ Get all matches from rule paths (multiple per line allow in rule) in a local path """ - spec = pathspec.PathSpec.from_lines("gitwildmatch", self.paths.splitlines()) - return spec.match_tree(path) + return self._set_spec(self.paths.splitlines()).match_tree(path) def _analysis_file(self, path): file_res = SourceAnalysis.from_file(path, "") diff --git a/github_connector/models/github_repository_branch.py b/github_connector/models/github_repository_branch.py index ecb8cc17..32857e73 100644 --- a/github_connector/models/github_repository_branch.py +++ b/github_connector/models/github_repository_branch.py @@ -166,7 +166,7 @@ def _download_code(self): try: os.makedirs(branch.local_path) except Exception: - raise exceptions.Warning( + raise exceptions.UserError( _( "Error when trying to create the folder %s\n" " Please check Odoo Access Rights." @@ -230,11 +230,7 @@ def _get_analyzable_files(self, existing_folder): res.append(os.path.join(root, fic)) return res - def analyze_code_one(self): - """Overload Me in custom Module that manage Source Code analysis.""" - self.ensure_one() - path = self.local_path - # github_analysis_rule + def set_analysis_rule_info(self): rule_ids = ( self.repository_id.organization_id.analysis_rule_ids + self.repository_id.analysis_rule_ids @@ -244,6 +240,12 @@ def analyze_code_one(self): self._delete_analysis_rule_model_info(rule_id) for vals in self._prepare_analysis_rule_info_vals(rule_id): self.env[self._prepare_analysis_rule_model_info(rule_id)].create(vals) + + def analyze_code_one(self): + """Overload Me in custom Module that manage Source Code analysis.""" + self.ensure_one() + path = self.local_path + self.set_analysis_rule_info() # Compute Files Sizes size = 0 for file_path in self._get_analyzable_files(path): @@ -295,12 +297,17 @@ def _prepare_analysis_rule_model_info(self, analysis_rule_id): def _delete_analysis_rule_model_info(self, analysis_rule_id): """Remove existing info data to create new records""" - self.env[self._prepare_analysis_rule_model_info(analysis_rule_id)].search( - [ - ("analysis_rule_id", "=", analysis_rule_id.id), - ("repository_branch_id", "=", self.id), - ] - ).sudo().unlink() + return ( + self.env[self._prepare_analysis_rule_model_info(analysis_rule_id)] + .search( + [ + ("analysis_rule_id", "=", analysis_rule_id.id), + ("repository_branch_id", "=", self.id), + ] + ) + .sudo() + .unlink() + ) def _prepare_analysis_rule_info_vals(self, analysis_rule_id): """Prepare info vals""" @@ -329,13 +336,11 @@ def _operation_analysis_rule_id(self, analysis_rule_id): "string": 0, } for match in analysis_rule_id._get_matches(self.local_path): - # _logger.info("analyse file %s "% match) res_file = analysis_rule_id._analysis_file(self.local_path + "/" + match) res["paths"].append(res_file["path"]) # define values for key in ("code", "documentation", "empty", "string"): res[key] += res_file[key] - return res # Compute Section @@ -360,7 +365,7 @@ def _compute_organization_serie_id(self): def _compute_local_path(self): source_path = self._get_source_path() if not source_path and not tools.config["test_enable"]: - raise exceptions.Warning( + raise exceptions.UserError( _( "source_code_local_path should be defined in your " " configuration file" diff --git a/github_connector/models/res_partner.py b/github_connector/models/res_partner.py index da5bc66e..ae1c3ef4 100644 --- a/github_connector/models/res_partner.py +++ b/github_connector/models/res_partner.py @@ -6,6 +6,7 @@ from github.GithubException import UnknownObjectException from odoo import _, api, fields, models +from odoo.exceptions import UserError class ResPartner(models.Model): @@ -61,7 +62,7 @@ class ResPartner(models.Model): def _check_login_company(self): for partner in self: if partner.is_company and partner.github_name: - raise Warning( + raise UserError( _("A company ('%s') can not have a Github login" " associated.") % partner.name ) diff --git a/github_connector/tests/__init__.py b/github_connector/tests/__init__.py index 09a1ce31..d62e4b0b 100644 --- a/github_connector/tests/__init__.py +++ b/github_connector/tests/__init__.py @@ -1,5 +1,4 @@ -# Copyright 2021 Tecnativa - Víctor Martínez +# Copyright 2021-2022 Tecnativa - Víctor Martínez # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html - -from . import test_github_analysis_rule from . import test_github_connector +from . import test_github_analysis_rule diff --git a/github_connector/tests/common.py b/github_connector/tests/common.py new file mode 100644 index 00000000..1739fc5c --- /dev/null +++ b/github_connector/tests/common.py @@ -0,0 +1,61 @@ +# Copyright 2020-2022 Tecnativa - Víctor Martínez +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +import responses + +from odoo.tests.common import SavepointCase + + +class TestGithubConnectorCommon(SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.info_keys = [ + "code_count", + "documentation_count", + "empty_count", + "string_count", + "scanned_files", + ] + cls.model_gos = cls.env["github.organization.serie"] + cls.model_gr = cls.env["github.repository"] + cls.model_grb = cls.env["github.repository.branch"] + cls.oca = cls.env.ref("github_connector.oca_organization") + cls.serie_13 = cls.env.ref("github_connector.oca_organization_serie_13") + cls.repository_ocb = cls.model_gr.create( + { + "name": "OCB", + "organization_id": cls.oca.id, + "github_id_external": 20558462, + } + ) + cls.repository_interface_github = cls.model_gr.create( + { + "name": "interface-github", + "organization_id": cls.oca.id, + "github_id_external": 70173147, + } + ) + # repository branch + cls.repository_ocb_13 = cls.model_grb.create( + { + "name": cls.serie_13.name, + "organization_id": cls.oca.id, + "repository_id": cls.repository_ocb.id, + "organization_serie_id": cls.serie_13.id, + } + ) + cls.repository_interface_github_13 = cls.model_grb.create( + { + "name": cls.serie_13.name, + "organization_id": cls.oca.id, + "repository_id": cls.repository_interface_github.id, + "organization_serie_id": cls.serie_13.id, + } + ) + cls.env["ir.config_parameter"].set_param("github.access_token", "test") + + @responses.activate + def _download_and_analyze(self, repo_branch): + if repo_branch.state == "to_download": + repo_branch._download_code() + repo_branch.analyze_code_one() diff --git a/github_connector/tests/res/github_repo_20558462_response.json b/github_connector/tests/res/github_repo_20558462_response.json new file mode 100644 index 00000000..5c9f20a3 --- /dev/null +++ b/github_connector/tests/res/github_repo_20558462_response.json @@ -0,0 +1,338 @@ +{ + "id": 20558462, + "node_id": "MDEwOlJlcG9zaXRvcnkyMDU1ODQ2Mg==", + "name": "OCB", + "full_name": "OCA/OCB", + "private": false, + "owner": { + "login": "OCA", + "id": 7600578, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc2MDA1Nzg=", + "avatar_url": "https://avatars.githubusercontent.com/u/7600578?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/OCA", + "html_url": "https://github.com/OCA", + "followers_url": "https://api.github.com/users/OCA/followers", + "following_url": "https://api.github.com/users/OCA/following{/other_user}", + "gists_url": "https://api.github.com/users/OCA/gists{/gist_id}", + "starred_url": "https://api.github.com/users/OCA/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/OCA/subscriptions", + "organizations_url": "https://api.github.com/users/OCA/orgs", + "repos_url": "https://api.github.com/users/OCA/repos", + "events_url": "https://api.github.com/users/OCA/events{/privacy}", + "received_events_url": "https://api.github.com/users/OCA/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/OCA/OCB", + "description": "Odoo Community Backports", + "fork": true, + "url": "https://api.github.com/repos/OCA/OCB", + "forks_url": "https://api.github.com/repos/OCA/OCB/forks", + "keys_url": "https://api.github.com/repos/OCA/OCB/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/OCA/OCB/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/OCA/OCB/teams", + "hooks_url": "https://api.github.com/repos/OCA/OCB/hooks", + "issue_events_url": "https://api.github.com/repos/OCA/OCB/issues/events{/number}", + "events_url": "https://api.github.com/repos/OCA/OCB/events", + "assignees_url": "https://api.github.com/repos/OCA/OCB/assignees{/user}", + "branches_url": "https://api.github.com/repos/OCA/OCB/branches{/branch}", + "tags_url": "https://api.github.com/repos/OCA/OCB/tags", + "blobs_url": "https://api.github.com/repos/OCA/OCB/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/OCA/OCB/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/OCA/OCB/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/OCA/OCB/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/OCA/OCB/statuses/{sha}", + "languages_url": "https://api.github.com/repos/OCA/OCB/languages", + "stargazers_url": "https://api.github.com/repos/OCA/OCB/stargazers", + "contributors_url": "https://api.github.com/repos/OCA/OCB/contributors", + "subscribers_url": "https://api.github.com/repos/OCA/OCB/subscribers", + "subscription_url": "https://api.github.com/repos/OCA/OCB/subscription", + "commits_url": "https://api.github.com/repos/OCA/OCB/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/OCA/OCB/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/OCA/OCB/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/OCA/OCB/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/OCA/OCB/contents/{+path}", + "compare_url": "https://api.github.com/repos/OCA/OCB/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/OCA/OCB/merges", + "archive_url": "https://api.github.com/repos/OCA/OCB/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/OCA/OCB/downloads", + "issues_url": "https://api.github.com/repos/OCA/OCB/issues{/number}", + "pulls_url": "https://api.github.com/repos/OCA/OCB/pulls{/number}", + "milestones_url": "https://api.github.com/repos/OCA/OCB/milestones{/number}", + "notifications_url": "https://api.github.com/repos/OCA/OCB/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/OCA/OCB/labels{/name}", + "releases_url": "https://api.github.com/repos/OCA/OCB/releases{/id}", + "deployments_url": "https://api.github.com/repos/OCA/OCB/deployments", + "created_at": "2014-06-06T09:33:16Z", + "updated_at": "2022-07-11T17:24:33Z", + "pushed_at": "2022-07-19T22:38:25Z", + "git_url": "git://github.com/OCA/OCB.git", + "ssh_url": "git@github.com:OCA/OCB.git", + "clone_url": "https://github.com/OCA/OCB.git", + "svn_url": "https://github.com/OCA/OCB", + "homepage": "http://odoo-community.org", + "size": 4097132, + "stargazers_count": 261, + "watchers_count": 261, + "language": "JavaScript", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 334, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 173, + "license": { + "key": "other", + "name": "Other", + "spdx_id": "NOASSERTION", + "url": null, + "node_id": "MDc6TGljZW5zZTA=" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 334, + "open_issues": 173, + "watchers": 261, + "default_branch": "14.0", + "temp_clone_token": null, + "organization": { + "login": "OCA", + "id": 7600578, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc2MDA1Nzg=", + "avatar_url": "https://avatars.githubusercontent.com/u/7600578?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/OCA", + "html_url": "https://github.com/OCA", + "followers_url": "https://api.github.com/users/OCA/followers", + "following_url": "https://api.github.com/users/OCA/following{/other_user}", + "gists_url": "https://api.github.com/users/OCA/gists{/gist_id}", + "starred_url": "https://api.github.com/users/OCA/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/OCA/subscriptions", + "organizations_url": "https://api.github.com/users/OCA/orgs", + "repos_url": "https://api.github.com/users/OCA/repos", + "events_url": "https://api.github.com/users/OCA/events{/privacy}", + "received_events_url": "https://api.github.com/users/OCA/received_events", + "type": "Organization", + "site_admin": false + }, + "parent": { + "id": 19745004, + "node_id": "MDEwOlJlcG9zaXRvcnkxOTc0NTAwNA==", + "name": "odoo", + "full_name": "odoo/odoo", + "private": false, + "owner": { + "login": "odoo", + "id": 6368483, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjYzNjg0ODM=", + "avatar_url": "https://avatars.githubusercontent.com/u/6368483?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/odoo", + "html_url": "https://github.com/odoo", + "followers_url": "https://api.github.com/users/odoo/followers", + "following_url": "https://api.github.com/users/odoo/following{/other_user}", + "gists_url": "https://api.github.com/users/odoo/gists{/gist_id}", + "starred_url": "https://api.github.com/users/odoo/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/odoo/subscriptions", + "organizations_url": "https://api.github.com/users/odoo/orgs", + "repos_url": "https://api.github.com/users/odoo/repos", + "events_url": "https://api.github.com/users/odoo/events{/privacy}", + "received_events_url": "https://api.github.com/users/odoo/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/odoo/odoo", + "description": "Odoo. Open Source Apps To Grow Your Business.", + "fork": false, + "url": "https://api.github.com/repos/odoo/odoo", + "forks_url": "https://api.github.com/repos/odoo/odoo/forks", + "keys_url": "https://api.github.com/repos/odoo/odoo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/odoo/odoo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/odoo/odoo/teams", + "hooks_url": "https://api.github.com/repos/odoo/odoo/hooks", + "issue_events_url": "https://api.github.com/repos/odoo/odoo/issues/events{/number}", + "events_url": "https://api.github.com/repos/odoo/odoo/events", + "assignees_url": "https://api.github.com/repos/odoo/odoo/assignees{/user}", + "branches_url": "https://api.github.com/repos/odoo/odoo/branches{/branch}", + "tags_url": "https://api.github.com/repos/odoo/odoo/tags", + "blobs_url": "https://api.github.com/repos/odoo/odoo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/odoo/odoo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/odoo/odoo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/odoo/odoo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/odoo/odoo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/odoo/odoo/languages", + "stargazers_url": "https://api.github.com/repos/odoo/odoo/stargazers", + "contributors_url": "https://api.github.com/repos/odoo/odoo/contributors", + "subscribers_url": "https://api.github.com/repos/odoo/odoo/subscribers", + "subscription_url": "https://api.github.com/repos/odoo/odoo/subscription", + "commits_url": "https://api.github.com/repos/odoo/odoo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/odoo/odoo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/odoo/odoo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/odoo/odoo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/odoo/odoo/contents/{+path}", + "compare_url": "https://api.github.com/repos/odoo/odoo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/odoo/odoo/merges", + "archive_url": "https://api.github.com/repos/odoo/odoo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/odoo/odoo/downloads", + "issues_url": "https://api.github.com/repos/odoo/odoo/issues{/number}", + "pulls_url": "https://api.github.com/repos/odoo/odoo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/odoo/odoo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/odoo/odoo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/odoo/odoo/labels{/name}", + "releases_url": "https://api.github.com/repos/odoo/odoo/releases{/id}", + "deployments_url": "https://api.github.com/repos/odoo/odoo/deployments", + "created_at": "2014-05-13T15:38:58Z", + "updated_at": "2022-07-20T08:12:51Z", + "pushed_at": "2022-07-20T10:32:52Z", + "git_url": "git://github.com/odoo/odoo.git", + "ssh_url": "git@github.com:odoo/odoo.git", + "clone_url": "https://github.com/odoo/odoo.git", + "svn_url": "https://github.com/odoo/odoo", + "homepage": "https://www.odoo.com", + "size": 4637751, + "stargazers_count": 25671, + "watchers_count": 25671, + "language": "JavaScript", + "has_issues": true, + "has_projects": false, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 16544, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 5463, + "license": { + "key": "other", + "name": "Other", + "spdx_id": "NOASSERTION", + "url": null, + "node_id": "MDc6TGljZW5zZTA=" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": ["apps", "business", "erp", "management", "odoo", "odoo-apps", "python"], + "visibility": "public", + "forks": 16544, + "open_issues": 5463, + "watchers": 25671, + "default_branch": "15.0" + }, + "source": { + "id": 19745004, + "node_id": "MDEwOlJlcG9zaXRvcnkxOTc0NTAwNA==", + "name": "odoo", + "full_name": "odoo/odoo", + "private": false, + "owner": { + "login": "odoo", + "id": 6368483, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjYzNjg0ODM=", + "avatar_url": "https://avatars.githubusercontent.com/u/6368483?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/odoo", + "html_url": "https://github.com/odoo", + "followers_url": "https://api.github.com/users/odoo/followers", + "following_url": "https://api.github.com/users/odoo/following{/other_user}", + "gists_url": "https://api.github.com/users/odoo/gists{/gist_id}", + "starred_url": "https://api.github.com/users/odoo/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/odoo/subscriptions", + "organizations_url": "https://api.github.com/users/odoo/orgs", + "repos_url": "https://api.github.com/users/odoo/repos", + "events_url": "https://api.github.com/users/odoo/events{/privacy}", + "received_events_url": "https://api.github.com/users/odoo/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/odoo/odoo", + "description": "Odoo. Open Source Apps To Grow Your Business.", + "fork": false, + "url": "https://api.github.com/repos/odoo/odoo", + "forks_url": "https://api.github.com/repos/odoo/odoo/forks", + "keys_url": "https://api.github.com/repos/odoo/odoo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/odoo/odoo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/odoo/odoo/teams", + "hooks_url": "https://api.github.com/repos/odoo/odoo/hooks", + "issue_events_url": "https://api.github.com/repos/odoo/odoo/issues/events{/number}", + "events_url": "https://api.github.com/repos/odoo/odoo/events", + "assignees_url": "https://api.github.com/repos/odoo/odoo/assignees{/user}", + "branches_url": "https://api.github.com/repos/odoo/odoo/branches{/branch}", + "tags_url": "https://api.github.com/repos/odoo/odoo/tags", + "blobs_url": "https://api.github.com/repos/odoo/odoo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/odoo/odoo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/odoo/odoo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/odoo/odoo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/odoo/odoo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/odoo/odoo/languages", + "stargazers_url": "https://api.github.com/repos/odoo/odoo/stargazers", + "contributors_url": "https://api.github.com/repos/odoo/odoo/contributors", + "subscribers_url": "https://api.github.com/repos/odoo/odoo/subscribers", + "subscription_url": "https://api.github.com/repos/odoo/odoo/subscription", + "commits_url": "https://api.github.com/repos/odoo/odoo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/odoo/odoo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/odoo/odoo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/odoo/odoo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/odoo/odoo/contents/{+path}", + "compare_url": "https://api.github.com/repos/odoo/odoo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/odoo/odoo/merges", + "archive_url": "https://api.github.com/repos/odoo/odoo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/odoo/odoo/downloads", + "issues_url": "https://api.github.com/repos/odoo/odoo/issues{/number}", + "pulls_url": "https://api.github.com/repos/odoo/odoo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/odoo/odoo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/odoo/odoo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/odoo/odoo/labels{/name}", + "releases_url": "https://api.github.com/repos/odoo/odoo/releases{/id}", + "deployments_url": "https://api.github.com/repos/odoo/odoo/deployments", + "created_at": "2014-05-13T15:38:58Z", + "updated_at": "2022-07-20T08:12:51Z", + "pushed_at": "2022-07-20T10:32:52Z", + "git_url": "git://github.com/odoo/odoo.git", + "ssh_url": "git@github.com:odoo/odoo.git", + "clone_url": "https://github.com/odoo/odoo.git", + "svn_url": "https://github.com/odoo/odoo", + "homepage": "https://www.odoo.com", + "size": 4637751, + "stargazers_count": 25671, + "watchers_count": 25671, + "language": "JavaScript", + "has_issues": true, + "has_projects": false, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 16544, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 5463, + "license": { + "key": "other", + "name": "Other", + "spdx_id": "NOASSERTION", + "url": null, + "node_id": "MDc6TGljZW5zZTA=" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": ["apps", "business", "erp", "management", "odoo", "odoo-apps", "python"], + "visibility": "public", + "forks": 16544, + "open_issues": 5463, + "watchers": 25671, + "default_branch": "15.0" + }, + "network_count": 16544, + "subscribers_count": 127 +} diff --git a/github_connector/tests/res/github_repo_20881668_response.json b/github_connector/tests/res/github_repo_20881668_response.json deleted file mode 100644 index ea76151c..00000000 --- a/github_connector/tests/res/github_repo_20881668_response.json +++ /dev/null @@ -1,123 +0,0 @@ -{ - "id": 20881668, - "node_id": "MDEwOlJlcG9zaXRvcnkyMDg4MTY2OA==", - "name": "account-analytic", - "full_name": "OCA/account-analytic", - "private": false, - "owner": { - "login": "OCA", - "id": 7600578, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc2MDA1Nzg=", - "avatar_url": "https://avatars.githubusercontent.com/u/7600578?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/OCA", - "html_url": "https://github.com/OCA", - "followers_url": "https://api.github.com/users/OCA/followers", - "following_url": "https://api.github.com/users/OCA/following{/other_user}", - "gists_url": "https://api.github.com/users/OCA/gists{/gist_id}", - "starred_url": "https://api.github.com/users/OCA/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/OCA/subscriptions", - "organizations_url": "https://api.github.com/users/OCA/orgs", - "repos_url": "https://api.github.com/users/OCA/repos", - "events_url": "https://api.github.com/users/OCA/events{/privacy}", - "received_events_url": "https://api.github.com/users/OCA/received_events", - "type": "Organization", - "site_admin": false - }, - "html_url": "https://github.com/OCA/account-analytic", - "description": "Odoo Account Analytic Related Addons", - "fork": false, - "url": "https://api.github.com/repos/OCA/account-analytic", - "forks_url": "https://api.github.com/repos/OCA/account-analytic/forks", - "keys_url": "https://api.github.com/repos/OCA/account-analytic/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/OCA/account-analytic/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/OCA/account-analytic/teams", - "hooks_url": "https://api.github.com/repos/OCA/account-analytic/hooks", - "issue_events_url": "https://api.github.com/repos/OCA/account-analytic/issues/events{/number}", - "events_url": "https://api.github.com/repos/OCA/account-analytic/events", - "assignees_url": "https://api.github.com/repos/OCA/account-analytic/assignees{/user}", - "branches_url": "https://api.github.com/repos/OCA/account-analytic/branches{/branch}", - "tags_url": "https://api.github.com/repos/OCA/account-analytic/tags", - "blobs_url": "https://api.github.com/repos/OCA/account-analytic/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/OCA/account-analytic/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/OCA/account-analytic/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/OCA/account-analytic/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/OCA/account-analytic/statuses/{sha}", - "languages_url": "https://api.github.com/repos/OCA/account-analytic/languages", - "stargazers_url": "https://api.github.com/repos/OCA/account-analytic/stargazers", - "contributors_url": "https://api.github.com/repos/OCA/account-analytic/contributors", - "subscribers_url": "https://api.github.com/repos/OCA/account-analytic/subscribers", - "subscription_url": "https://api.github.com/repos/OCA/account-analytic/subscription", - "commits_url": "https://api.github.com/repos/OCA/account-analytic/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/OCA/account-analytic/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/OCA/account-analytic/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/OCA/account-analytic/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/OCA/account-analytic/contents/{+path}", - "compare_url": "https://api.github.com/repos/OCA/account-analytic/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/OCA/account-analytic/merges", - "archive_url": "https://api.github.com/repos/OCA/account-analytic/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/OCA/account-analytic/downloads", - "issues_url": "https://api.github.com/repos/OCA/account-analytic/issues{/number}", - "pulls_url": "https://api.github.com/repos/OCA/account-analytic/pulls{/number}", - "milestones_url": "https://api.github.com/repos/OCA/account-analytic/milestones{/number}", - "notifications_url": "https://api.github.com/repos/OCA/account-analytic/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/OCA/account-analytic/labels{/name}", - "releases_url": "https://api.github.com/repos/OCA/account-analytic/releases{/id}", - "deployments_url": "https://api.github.com/repos/OCA/account-analytic/deployments", - "created_at": "2014-06-16T10:55:18Z", - "updated_at": "2021-07-05T16:49:21Z", - "pushed_at": "2021-07-07T09:59:23Z", - "git_url": "git://github.com/OCA/account-analytic.git", - "ssh_url": "git@github.com:OCA/account-analytic.git", - "clone_url": "https://github.com/OCA/account-analytic.git", - "svn_url": "https://github.com/OCA/account-analytic", - "homepage": "", - "size": 2960, - "stargazers_count": 55, - "watchers_count": 55, - "language": "HTML", - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "forks_count": 249, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 88, - "license": { - "key": "agpl-3.0", - "name": "GNU Affero General Public License v3.0", - "spdx_id": "AGPL-3.0", - "url": "https://api.github.com/licenses/agpl-3.0", - "node_id": "MDc6TGljZW5zZTE=" - }, - "forks": 249, - "open_issues": 88, - "watchers": 55, - "default_branch": "12.0", - "temp_clone_token": null, - "organization": { - "login": "OCA", - "id": 7600578, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc2MDA1Nzg=", - "avatar_url": "https://avatars.githubusercontent.com/u/7600578?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/OCA", - "html_url": "https://github.com/OCA", - "followers_url": "https://api.github.com/users/OCA/followers", - "following_url": "https://api.github.com/users/OCA/following{/other_user}", - "gists_url": "https://api.github.com/users/OCA/gists{/gist_id}", - "starred_url": "https://api.github.com/users/OCA/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/OCA/subscriptions", - "organizations_url": "https://api.github.com/users/OCA/orgs", - "repos_url": "https://api.github.com/users/OCA/repos", - "events_url": "https://api.github.com/users/OCA/events{/privacy}", - "received_events_url": "https://api.github.com/users/OCA/received_events", - "type": "Organization", - "site_admin": false - }, - "network_count": 249, - "subscribers_count": 63 -} diff --git a/github_connector/tests/res/github_repo_70173147_response.json b/github_connector/tests/res/github_repo_70173147_response.json new file mode 100644 index 00000000..933e79e8 --- /dev/null +++ b/github_connector/tests/res/github_repo_70173147_response.json @@ -0,0 +1,128 @@ +{ + "id": 70173147, + "node_id": "MDEwOlJlcG9zaXRvcnk3MDE3MzE0Nw==", + "name": "interface-github", + "full_name": "OCA/interface-github", + "private": false, + "owner": { + "login": "OCA", + "id": 7600578, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc2MDA1Nzg=", + "avatar_url": "https://avatars.githubusercontent.com/u/7600578?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/OCA", + "html_url": "https://github.com/OCA", + "followers_url": "https://api.github.com/users/OCA/followers", + "following_url": "https://api.github.com/users/OCA/following{/other_user}", + "gists_url": "https://api.github.com/users/OCA/gists{/gist_id}", + "starred_url": "https://api.github.com/users/OCA/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/OCA/subscriptions", + "organizations_url": "https://api.github.com/users/OCA/orgs", + "repos_url": "https://api.github.com/users/OCA/repos", + "events_url": "https://api.github.com/users/OCA/events{/privacy}", + "received_events_url": "https://api.github.com/users/OCA/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/OCA/interface-github", + "description": "Tools to interact with github from Odoo", + "fork": false, + "url": "https://api.github.com/repos/OCA/interface-github", + "forks_url": "https://api.github.com/repos/OCA/interface-github/forks", + "keys_url": "https://api.github.com/repos/OCA/interface-github/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/OCA/interface-github/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/OCA/interface-github/teams", + "hooks_url": "https://api.github.com/repos/OCA/interface-github/hooks", + "issue_events_url": "https://api.github.com/repos/OCA/interface-github/issues/events{/number}", + "events_url": "https://api.github.com/repos/OCA/interface-github/events", + "assignees_url": "https://api.github.com/repos/OCA/interface-github/assignees{/user}", + "branches_url": "https://api.github.com/repos/OCA/interface-github/branches{/branch}", + "tags_url": "https://api.github.com/repos/OCA/interface-github/tags", + "blobs_url": "https://api.github.com/repos/OCA/interface-github/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/OCA/interface-github/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/OCA/interface-github/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/OCA/interface-github/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/OCA/interface-github/statuses/{sha}", + "languages_url": "https://api.github.com/repos/OCA/interface-github/languages", + "stargazers_url": "https://api.github.com/repos/OCA/interface-github/stargazers", + "contributors_url": "https://api.github.com/repos/OCA/interface-github/contributors", + "subscribers_url": "https://api.github.com/repos/OCA/interface-github/subscribers", + "subscription_url": "https://api.github.com/repos/OCA/interface-github/subscription", + "commits_url": "https://api.github.com/repos/OCA/interface-github/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/OCA/interface-github/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/OCA/interface-github/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/OCA/interface-github/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/OCA/interface-github/contents/{+path}", + "compare_url": "https://api.github.com/repos/OCA/interface-github/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/OCA/interface-github/merges", + "archive_url": "https://api.github.com/repos/OCA/interface-github/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/OCA/interface-github/downloads", + "issues_url": "https://api.github.com/repos/OCA/interface-github/issues{/number}", + "pulls_url": "https://api.github.com/repos/OCA/interface-github/pulls{/number}", + "milestones_url": "https://api.github.com/repos/OCA/interface-github/milestones{/number}", + "notifications_url": "https://api.github.com/repos/OCA/interface-github/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/OCA/interface-github/labels{/name}", + "releases_url": "https://api.github.com/repos/OCA/interface-github/releases{/id}", + "deployments_url": "https://api.github.com/repos/OCA/interface-github/deployments", + "created_at": "2016-10-06T16:42:24Z", + "updated_at": "2022-06-22T12:50:39Z", + "pushed_at": "2022-07-20T10:34:42Z", + "git_url": "git://github.com/OCA/interface-github.git", + "ssh_url": "git@github.com:OCA/interface-github.git", + "clone_url": "https://github.com/OCA/interface-github.git", + "svn_url": "https://github.com/OCA/interface-github", + "homepage": null, + "size": 1573, + "stargazers_count": 39, + "watchers_count": 39, + "language": "Python", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 64, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 11, + "license": { + "key": "agpl-3.0", + "name": "GNU Affero General Public License v3.0", + "spdx_id": "AGPL-3.0", + "url": "https://api.github.com/licenses/agpl-3.0", + "node_id": "MDc6TGljZW5zZTE=" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 64, + "open_issues": 11, + "watchers": 39, + "default_branch": "13.0", + "temp_clone_token": null, + "organization": { + "login": "OCA", + "id": 7600578, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc2MDA1Nzg=", + "avatar_url": "https://avatars.githubusercontent.com/u/7600578?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/OCA", + "html_url": "https://github.com/OCA", + "followers_url": "https://api.github.com/users/OCA/followers", + "following_url": "https://api.github.com/users/OCA/following{/other_user}", + "gists_url": "https://api.github.com/users/OCA/gists{/gist_id}", + "starred_url": "https://api.github.com/users/OCA/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/OCA/subscriptions", + "organizations_url": "https://api.github.com/users/OCA/orgs", + "repos_url": "https://api.github.com/users/OCA/repos", + "events_url": "https://api.github.com/users/OCA/events{/privacy}", + "received_events_url": "https://api.github.com/users/OCA/received_events", + "type": "Organization", + "site_admin": false + }, + "network_count": 64, + "subscribers_count": 31 +} diff --git a/github_connector/tests/test_github_analysis_rule.py b/github_connector/tests/test_github_analysis_rule.py index 0f449e14..a1e2d70e 100644 --- a/github_connector/tests/test_github_analysis_rule.py +++ b/github_connector/tests/test_github_analysis_rule.py @@ -1,54 +1,29 @@ -# Copyright 2020 Tecnativa - Víctor Martínez -# Copyright 2021 Tecnativa - João Marques +# Copyright 2020-2022 Tecnativa - Víctor Martínez # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html - import json import responses from odoo.modules.module import get_resource_path -from odoo.tests.common import SavepointCase + +from .common import TestGithubConnectorCommon -class TestGithubAnalysisRule(SavepointCase): +class TestGithubConnectorAnalysisRuleBase(TestGithubConnectorCommon): @classmethod def setUpClass(cls): super().setUpClass() - cls.analysis_rule_group_misc = cls.env["github.analysis.rule.group"].create( - {"name": "Misc"} - ) - cls.analysis_rule_python = cls.env["github.analysis.rule"].create( - { - "name": "Python files", - "group_id": cls.analysis_rule_group_misc.id, - "paths": "**/account_analytic_project/**/*.py", - } - ) - cls.analysis_rule_xml = cls.env["github.analysis.rule"].create( - { - "name": "Xml files", - "group_id": cls.analysis_rule_group_misc.id, - "paths": "**/account_analytic_project/**/*.xml", - } - ) - cls.analysis_rule_js = cls.env["github.analysis.rule"].create( - { - "name": "Js files", - "group_id": cls.analysis_rule_group_misc.id, - "paths": "**/account_analytic_project/**/*.js", - } - ) - cls.analysis_rule_test = cls.env["github.analysis.rule"].create( - { - "name": "Test files", - "group_id": cls.analysis_rule_group_misc.id, - "paths": "/tests/*.py", - } - ) - cls.analysis_rule_ocb = cls.env["github.analysis.rule"].create( + cls.rule_group = cls.env.ref( + "github_connector.github_analysis_rule_group_1_demo" + ) + cls.rule_python = cls.env.ref("github_connector.github_analysis_rule_python") + cls.rule_xml = cls.env.ref("github_connector.github_analysis_rule_xml") + cls.rule_js = cls.env.ref("github_connector.github_analysis_rule_js") + cls.rule_test = cls.env.ref("github_connector.github_analysis_rule_test") + cls.rule_ocb = cls.env["github.analysis.rule"].create( { "name": "OCB files (.py + .xml)", - "group_id": cls.analysis_rule_group_misc.id, + "group_id": cls.rule_group.id, "paths": """ *.py *.xml @@ -56,120 +31,77 @@ def setUpClass(cls): """, } ) - cls.analysis_rule_custom = cls.env["github.analysis.rule"].create( + cls.rule_custom = cls.env["github.analysis.rule"].create( { "name": "Custom", - "group_id": cls.analysis_rule_group_misc.id, + "group_id": cls.rule_group.id, "paths": """/custom/*.py""", } ) - cls.organization_oca = cls.env["github.organization"].create( + cls.oca.write( { - "name": "Odoo Community Association", - "description": "The GitHub repos for all Open Source work around Odoo", - "website_url": "https://odoo-community.org/", - "github_url": "https://github.com/OCA", - "github_name": "OCA", - "github_id_external": 7600578, "analysis_rule_ids": [ - (4, cls.analysis_rule_python.id), - (4, cls.analysis_rule_xml.id), - (4, cls.analysis_rule_js.id), - ], + (6, 0, [cls.rule_python.id, cls.rule_xml.id, cls.rule_js.id]) + ] } ) - cls.organization_serie_6 = cls.env["github.organization.serie"].create( - {"organization_id": cls.organization_oca.id, "sequence": 6, "name": "6.1"} + cls.repository_ocb.write({"analysis_rule_ids": [(6, 0, cls.rule_ocb.ids)]}) + cls.repository_interface_github_13.write( + {"analysis_rule_ids": [(6, 0, cls.rule_custom.ids)]} ) - cls.organization_serie_13 = cls.env["github.organization.serie"].create( - {"organization_id": cls.organization_oca.id, "sequence": 13, "name": "13.0"} - ) - cls.repository_ocb = cls.env["github.repository"].create( - { - "name": "OCB", - "organization_id": cls.organization_oca.id, - "github_name": "%s/OCB" % cls.organization_oca.github_name, - "github_id_external": 20558462, - "analysis_rule_ids": [(4, cls.analysis_rule_ocb.id)], - } - ) - cls.repository_account_analytic = cls.env["github.repository"].create( - { - "name": "account-analytic", - "organization_id": cls.organization_oca.id, - "github_id_external": 20881668, - "github_name": "%s/account-analytic" % cls.organization_oca.github_name, - } - ) - # repository branch - cls.repository_ocb_branch_13 = cls.env["github.repository.branch"].create( - { - "name": cls.organization_serie_13.name, - "organization_id": cls.organization_oca.id, - "repository_id": cls.repository_ocb.id, - "organization_serie_id": cls.organization_serie_13.id, - } - ) - cls.repository_account_analytic_branch_6 = cls.env[ - "github.repository.branch" - ].create( - { - "name": cls.organization_serie_6.name, - "organization_id": cls.organization_oca.id, - "repository_id": cls.repository_account_analytic.id, - "organization_serie_id": cls.organization_serie_6.id, - "analysis_rule_ids": [(4, cls.analysis_rule_custom.id)], - } - ) - cls.env["ir.config_parameter"].set_param("github.access_token", "test") + cls.repo_branch_item = cls.repository_interface_github_13 # Create appropriate responses for the API calls - with open( - get_resource_path( - "github_connector", "tests", "res", "github_repo_20881668_response.json" - ) - ) as jsonfile: - cls.repo_data = json.loads(jsonfile.read()) - responses.add( - responses.GET, - "https://api.github.com:443/repositories/20881668", - json=cls.repo_data, - status=200, - ) + cls._set_github_responses(cls) + + def _set_github_responses(self): + for github_id in self.oca.mapped("repository_ids.github_id_external"): + with open( + get_resource_path( + "github_connector", + "tests", + "res", + "github_repo_%s_response.json" % github_id, + ) + ) as jsonfile: + responses.add( + responses.GET, + "https://api.github.com:443/repositories/%s" % github_id, + json=json.loads(jsonfile.read()), + status=200, + ) - @responses.activate - def test_github_analysis_rule(self): - self.assertEqual(len(self.organization_oca.analysis_rule_ids), 3) + +class TestGithubConnectorAnalysisRule(TestGithubConnectorAnalysisRuleBase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls._download_and_analyze(cls, cls.repo_branch_item) + + def test_analysis_rule_info(self): + self.assertEqual(len(self.oca.analysis_rule_ids), 3) self.assertEqual(len(self.repository_ocb.analysis_rule_ids), 1) - # download + analyze_code - self.repository_account_analytic_branch_6._download_code() - self.repository_account_analytic_branch_6.analyze_code_one() - # info ids - info_ids = self.repository_account_analytic_branch_6.analysis_rule_info_ids - self.assertEqual(len(info_ids), 4) - # python info - python_info = info_ids.filtered( - lambda x: x.analysis_rule_id.id == self.analysis_rule_python.id - ) - self.assertEqual(python_info.code_count, 60) - self.assertEqual(python_info.documentation_count, 106) - self.assertEqual(python_info.empty_count, 20) - self.assertEqual(python_info.string_count, 19) - self.assertEqual(python_info.scanned_files, 4) - # xml info - xml_info = info_ids.filtered( - lambda x: x.analysis_rule_id.id == self.analysis_rule_xml.id + self.assertEqual(len(self.repo_branch_item.analysis_rule_info_ids), 4) + + def test_analysis_rule_info_python(self): + rule_info = self.repo_branch_item.analysis_rule_info_ids.filtered( + lambda x: x.analysis_rule_id.id == self.rule_python.id ) - self.assertEqual(xml_info.code_count, 35) - self.assertEqual(xml_info.documentation_count, 0) - self.assertEqual(xml_info.empty_count, 0) - self.assertEqual(xml_info.string_count, 10) - self.assertEqual(xml_info.scanned_files, 1) - # js info - js_info = info_ids.filtered( - lambda x: x.analysis_rule_id.id == self.analysis_rule_js.id + for info_key in self.info_keys: + self.assertGreater(rule_info[info_key], 0) + + def test_analysis_rule_info_xml(self): + rule_info = self.repo_branch_item.analysis_rule_info_ids.filtered( + lambda x: x.analysis_rule_id.id == self.rule_xml.id + ) + for info_key in self.info_keys: + if info_key in ("empty_count", "string_count"): + self.assertEqual(rule_info[info_key], 0) + else: + self.assertGreater(rule_info[info_key], 0) + + def test_analysis_rule_info_js(self): + rule_info = self.repo_branch_item.analysis_rule_info_ids.filtered( + lambda x: x.analysis_rule_id.id == self.rule_js.id ) - self.assertEqual(js_info.code_count, 0) - self.assertEqual(js_info.documentation_count, 0) - self.assertEqual(js_info.empty_count, 0) - self.assertEqual(js_info.string_count, 0) - self.assertEqual(js_info.scanned_files, 0) + for info_key in self.info_keys: + self.assertEqual(rule_info[info_key], 0) diff --git a/github_connector/tests/test_github_connector.py b/github_connector/tests/test_github_connector.py index de309692..32517bb2 100644 --- a/github_connector/tests/test_github_connector.py +++ b/github_connector/tests/test_github_connector.py @@ -1,4 +1,4 @@ -# Copyright 2021 Tecnativa - Víctor Martínez +# Copyright 2021-2022 Tecnativa - Víctor Martínez # Copyright 2021 Tecnativa - João Marques # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). @@ -7,15 +7,14 @@ import responses from odoo.modules.module import get_resource_path -from odoo.tests import common +from .common import TestGithubConnectorCommon -class TestGithubConnector(common.SavepointCase): + +class TestGithubConnector(TestGithubConnectorCommon): @classmethod def setUpClass(cls): super().setUpClass() - cls.model = cls.env["res.partner"] - cls.env["ir.config_parameter"].set_param("github.access_token", "test") # Create appropriate responses for the API calls with open( get_resource_path( @@ -49,12 +48,13 @@ def setUpClass(cls): @responses.activate def test_partner_get_from_id_or_create(self): - partner = self.model.create_from_name("OCA-git-bot") + partner_model = self.env["res.partner"] + partner = partner_model.create_from_name("OCA-git-bot") self.assertEqual(partner.github_name, "OCA-git-bot") # Check create process not really create new record - res = self.model.get_from_id_or_create(data={"login": "OCA-git-bot"}) + res = partner_model.get_from_id_or_create(data={"login": "OCA-git-bot"}) self.assertEqual(partner.id, res.id) # Try to archive record and try to create again partner.active = False - res = self.model.get_from_id_or_create(data={"login": "OCA-git-bot"}) + res = partner_model.get_from_id_or_create(data={"login": "OCA-git-bot"}) self.assertEqual(partner.id, res.id) diff --git a/github_connector/views/view_github_repository_branch.xml b/github_connector/views/view_github_repository_branch.xml index f00ac486..9e47dc1e 100644 --- a/github_connector/views/view_github_repository_branch.xml +++ b/github_connector/views/view_github_repository_branch.xml @@ -190,11 +190,15 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).