Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# generated from manifests external_dependencies
github3.py
1 change: 1 addition & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
odoo_test_helper
91 changes: 91 additions & 0 deletions vcp/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
===
Vcp
===

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:e5814614bba4bc7f628d116d3529a253bb2ae9bff8e8a16c3cfc7eefa5def3cf
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fversion--control--platform-lightgray.png?logo=github
:target: https://github.com/OCA/version-control-platform/tree/18.0/vcp
:alt: OCA/version-control-platform
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/version-control-platform-18-0/version-control-platform-18-0-vcp
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/version-control-platform&target_branch=18.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

Creates a set of modules used for handling a version control patform.

**Table of contents**

.. contents::
:local:

Use Cases / Context
===================

The aim of this module is to allow any community to import data from a
version control system.

The system should be done in a way that is agnostic to the system and
the connections are handled directly by specific modules.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/version-control-platform/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/version-control-platform/issues/new?body=module:%20vcp%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

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

Credits
=======

Authors
-------

* Dixmit

Contributors
------------

- `Dixmit <https://dixmit.com>`__

- Enric Tobella

- `Akretion <https://akretion.com>`__

- Sebastien Beau

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

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/version-control-platform <https://github.com/OCA/version-control-platform/tree/18.0/vcp>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions vcp/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
28 changes: 28 additions & 0 deletions vcp/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2025 Dixmit
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Vcp",
"summary": """Virtual Control Platform core module""",
"version": "18.0.1.0.0",
"license": "AGPL-3",
"author": "Dixmit,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/version-control-platform",
"depends": ["base"],
"data": [
"security/ir.model.access.csv",
"data/ir_cron.xml",
"templates/templates.xml",
"views/menu.xml",
"views/vcp_comment.xml",
"views/vcp_review.xml",
"views/vcp_request.xml",
"views/vcp_repository.xml",
"views/vcp_branch.xml",
"views/vcp_platform.xml",
"views/vcp_organization.xml",
"views/vcp_user.xml",
"views/vcp_platform_type.xml",
],
"demo": [],
}
23 changes: 23 additions & 0 deletions vcp/data/ir_cron.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2026 Dixmit
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo noupdate="1">
<record model="ir.cron" id="cron_repository_update">
<field name="name">VCP: Repository Update</field>
<field name="model_id" ref="model_vcp_repository" />
<field name="state">code</field>
<field name="code">model._cron_update_repositories()</field>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="active">False</field>
</record>
<record model="ir.cron" id="cron_platform_update">
<field name="name">VCP: Platform Update</field>
<field name="model_id" ref="model_vcp_platform" />
<field name="state">code</field>
<field name="code">model._cron_update_platforms()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="active">False</field>
</record>
</odoo>
10 changes: 10 additions & 0 deletions vcp/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from . import vcp_platform
from . import vcp_branch
from . import vcp_repository
from . import vcp_request
from . import vcp_review
from . import vcp_comment
from . import res_partner
from . import vcp_platform_type
from . import vcp_user
from . import vcp_organization
60 changes: 60 additions & 0 deletions vcp/models/res_partner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Copyright 2026 Dixmit
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).


from odoo import api, fields, models


class ResPartner(models.Model):
_inherit = "res.partner"

vcp_merged_requests = fields.Integer(
compute="_compute_vcp_contributions",
string="Merged Requests",
prefetch=False,
)
vcp_created_requests = fields.Integer(
compute="_compute_vcp_contributions",
string="Created Requests",
prefetch=False,
)
vcp_comments = fields.Integer(
compute="_compute_vcp_contributions", string="Comments", prefetch=False
)
vcp_reviews = fields.Integer(
compute="_compute_vcp_contributions", string="Reviews", prefetch=False
)

@api.depends()
def _compute_vcp_contributions(self):
self.filtered(lambda p: p.github_user)._compute_vcp_contributions_field(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hum. I think there is a little mistake in the design here. You call github_user field, but this one is defined in vcp_github module.

(same in line 33)

"partner_id"
)
self.filtered(lambda p: not p.github_user)._compute_vcp_contributions_field(
"organization_id"
)

@api.model
def _get_contributors_field_map(self):
return {
"vcp_merged_requests": "merged_requests",
"vcp_created_requests": "created_requests",
"vcp_comments": "comments",
"vcp_reviews": "reviews",
}

def _compute_vcp_contributions_field(self, field):
today = fields.Date.today()
start, end = self.env["vcp.platform"]._get_dates(today.year, today.month, "MAT")
data = (
self.env["vcp.platform"]
.search([])
._generate_data(
start=start, end=end, field=field, kind="user", extra_domain=[]
)
)
field_map = self._get_contributors_field_map()
for partner in self:
partner.update(
{key: data[partner.id].get(field_map[key], 0) for key in field_map}
)
19 changes: 19 additions & 0 deletions vcp/models/vcp_branch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2026 Dixmit
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import fields, models


class VcpBranch(models.Model):
_name = "vcp.branch"
_description = "Branch"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a branch exactly? Are we talking about a real git branch name, or an Odoo release/serie/version?

Asking as I faced this name issue in https://github.com/OCA/module-composition-analysis/blob/16.0/odoo_repository/models/odoo_branch.py which deserves a renaming to odoo.serie or odoo.version, but now the goal is to re-use your modules. In that project a serie/version is 17.0/18.0/19.0, while a branch can be main/18.0-mig which is linked to a serie/version.

@sebastienbeau you were proposing the term Odoo "serie" IIRC

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a Branch is a Branch in git. We should need to keep it, because there are repositories that are not using odoo versions (master/main for example on libraries like openupgradelib)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sebalix I think we should split the concept of "odoo.serie" and "vcp.branch".

An "odoo.serie" is the major version of odoo (17.0, 18.0, 19.0...)
A "vcp.branch" is a branch in term of git.

For sure in OCA case the branch (for repo that are odoo modules) are linked to one "odoo.version" that have the same name (but maybe one days if odoo start to be stable, we may have branch like 20+ that work with several version)

So my idea is that in odoo-repository we name this "odoo.version" and "odoo.serie" and then a branch is link to a serie (18.0-mig have the odoo.serie 18.0)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All clear, wanted to know what it was about 👍


name = fields.Char(required=True)
platform_id = fields.Many2one(
comodel_name="vcp.platform",
string="Platform",
required=True,
)
_sql_constraints = [
("name_uniq", "unique(name, platform_id)", "Branch name must be unique.")
]
40 changes: 40 additions & 0 deletions vcp/models/vcp_comment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright 2026 Dixmit
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import fields, models


class VcpComment(models.Model):
_name = "vcp.comment"
_description = "Comment"

external_id = fields.Char(readonly=True, required=True, index=True)
body = fields.Html(readonly=True)
user_id = fields.Many2one(
comodel_name="vcp.user",
readonly=True,
)
partner_id = fields.Many2one(
related="user_id.partner_id",
readonly=True,
)
organization_id = fields.Many2one(
related="request_id.organization_id",
readonly=True,
store=True,
)
repository_id = fields.Many2one(
related="request_id.repository_id",
readonly=True,
store=True,
)
created_at = fields.Datetime(readonly=True)
updated_at = fields.Datetime(readonly=True)
request_id = fields.Many2one(
comodel_name="vcp.request",
string="Request",
readonly=True,
)
_sql_constraints = [
("external_id_uniq", "unique(external_id)", "External ID must be unique.")
]
34 changes: 34 additions & 0 deletions vcp/models/vcp_organization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2026 Dixmit
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import fields, models


class VcpOrganization(models.Model):
_name = "vcp.organization"
_description = "Organization" # TODO

name = fields.Char(required=True, readonly=True)
external_id = fields.Char(required=True, readonly=True, index=True)
platform_type_id = fields.Many2one(
comodel_name="vcp.platform.type",
required=True,
readonly=True,
)
partner_id = fields.Many2one(
"res.partner",
)

_sql_constraints = [
(
"external_id_uniq",
"unique(external_id, platform_type_id)",
"External ID must be unique.",
)
]

def _get_contributor_url(self):
return False

def _get_contributors_name(self, kind, **kwargs):
return self.partner_id.name or self.name
Loading