Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
31fa9d0
[ADD] contributors_github
etobella Jan 5, 2026
beccfa4
[ADD] contributors_github_psc
etobella Jan 7, 2026
0e5c31c
[FIX] contributors_github: Set the right github_name
etobella Jan 9, 2026
944ba67
[FIX] contributors_github
etobella Jan 10, 2026
a4369ca
[FIX] contributors_github_psc
etobella Jan 10, 2026
092b241
[ADD] contributors_weblate
etobella Jan 10, 2026
4858ea6
[IMP] contributors_weblate: make message as debug
etobella Jan 10, 2026
c6eb4df
[FIX] contributors_github_psc: add sudo
etobella Jan 10, 2026
e561e93
[FIX] contributors_weblate: Fix unsettling language
etobella Jan 10, 2026
f40458a
[FIX] contributors_github_psc: Allow unsetting PSC
etobella Jan 10, 2026
22b23b5
[FIX] contributors_weblate: add other options
etobella Jan 10, 2026
2c34b56
[FIX] contributors_github: Fill comments on creation too...
etobella Jan 12, 2026
80e5118
[IMP] contributors_github: Add an option to handle the search for imp…
etobella Jan 12, 2026
e28d52c
[IMP] contributors_github: Add some cache and indexes
etobella Jan 13, 2026
85df898
[IMP] contributors_github: Add some cache and indexes
etobella Jan 13, 2026
a687826
[FIX] contributors_weblate: Add index
etobella Jan 13, 2026
9c920a4
[FIX] contributors_github: add index
etobella Jan 13, 2026
26287d7
[FIX] contributors_github: Pass logic to organization
etobella Jan 13, 2026
ed217d5
[FIX] contributors_weblate: Use a different name for function
etobella Jan 13, 2026
1d9b6cc
[FIX] contributors_github: use ormcache...
etobella Jan 13, 2026
aba2381
[FIX] contributors_github: Use cache properly and remove it if necessary
etobella Jan 14, 2026
0ce2a43
[IMP] contributors_github: Add number of developers
etobella Jan 14, 2026
7115554
[FIX] contributors_weblate: add actions for better filtering...
etobella Jan 14, 2026
6803b6f
[IMP] contributors_weblate: add status verification
etobella Jan 14, 2026
7d78311
[IMP] contributors_github: Add tooltips
etobella Jan 14, 2026
073781e
[FIX] contributors_weblate: Fix typo error
etobella Jan 14, 2026
406b793
[FIX] contributors_github_psc: Fix typo error
etobella Jan 14, 2026
43d285f
[IMP] contibutors_github: improve readme
etobella Jan 15, 2026
8907290
[IMP] contributors_weblate
etobella Jan 15, 2026
951d27a
[FIX] contributors_github: README
etobella Jan 15, 2026
e2ca335
[FIX] contributors_github: Fix readme
etobella Jan 16, 2026
33de4da
[FIX] contributors_weblate: Fix readme
etobella Jan 16, 2026
853f067
[IMP] contributors_github: add some portal tests
etobella Jan 16, 2026
4d3eb97
[IMP] contributors_github: Add portal tests
etobella Jan 16, 2026
4b0b26f
[IMP] contributors_github: Define portal view
etobella Jan 22, 2026
811561d
[IMP] contributors_weblate: Add portal view
etobella Jan 22, 2026
2306e19
[FIX] contributors_github_psc: adapt to new logic
etobella Jan 22, 2026
be590b1
[FIX] contributors_github: Improve css
etobella Jan 22, 2026
0ba9293
[IMP] weblate: Improve css
etobella Jan 22, 2026
ce80485
[IMP] PSC: Add PSC teams on your main view
etobella Jan 22, 2026
24bfb7f
[IMP] github: Pass logic to models, simplify setting names and so on …
etobella Jan 23, 2026
824814f
[FIX] psc: pass logic to models
etobella Jan 23, 2026
c413862
[IMP] weblate: Use defined functions to simplify code
etobella Jan 23, 2026
8de8bae
[FIX] weblate: Avoid raising a warning
etobella Jan 23, 2026
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
123 changes: 123 additions & 0 deletions contributors_github/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
===================
Contributors Github
===================

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

.. |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--contributors%2Fcontributors--module-lightgray.png?logo=github
:target: https://github.com/OCA-contributors/contributors-module/tree/18.0/contributors_github
:alt: OCA-contributors/contributors-module

|badge1| |badge2| |badge3|

This module allows to get data from github and show it in your odoo
instance.

**Table of contents**

.. contents::
:local:

Usage
=====

Access the Contributors / Organization module.

Add your organization and one ore more API Keys (it might be faster if
you add several ones).

Update the repositories.

The system will start fetching the data automatically.

First Load
----------

Usually, the first load can take a lot of time and you could find time
constrains on your Odoo database. For this reason we recommend to stop
the cron in this first load and execute the following code in your shell
once you have all the repositories created:

.. code:: python

from datetime import date, datetime, timedelta
import time
self = self.env["contributors.organization"].search([], limit=1) # Use the organization you prefer
clients = self._get_clients()
FIXED_DATE = "2026-01-01"
repositories = self.env["contributors.repository"].search([("from_date", "<", FIXED_DATE), ("organization_id", "=", self.id)], order="from_date asc")
i = 0
while repositories:
try:
for repository in repositories:
i = (i+1) % len(clients)
repository.update_information(client_for_search=i)
self.env.cr.commit()
except Exception:
date = False
for client in clients:
rate = client.rate_limit()
print(rate)
for code in rate["resources"]:
if rate["resources"][code]["remaining"] == 0:
date = max(date or 0, rate["resources"][code]["reset"])
if not date:
raise
print("%s - Sleeping for %s seconds" % (datetime.now().isoformat(), date - time.mktime(datetime.now().timetuple())))
time.sleep(date - time.mktime(datetime.now().timetuple()))
time.sleep(10)
repositories = self.env["contributors.repository"].search([("from_date", "<", FIXED_DATE), ("organization_id", "=", self.id)], order="from_date asc")

Once it has finished, restart the cron.

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

Bugs are tracked on `GitHub Issues <https://github.com/OCA-contributors/contributors-module/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-contributors/contributors-module/issues/new?body=module:%20contributors_github%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://www.dixmit.com>`__

- Enric Tobella

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

.. |maintainer-etobella| image:: https://github.com/etobella.png?size=40px
:target: https://github.com/etobella
:alt: etobella

Current maintainer:

|maintainer-etobella|

This module is part of the `OCA-contributors/contributors-module <https://github.com/OCA-contributors/contributors-module/tree/18.0/contributors_github>`_ project on GitHub.

You are welcome to contribute.
2 changes: 2 additions & 0 deletions contributors_github/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import controllers
from . import models
38 changes: 38 additions & 0 deletions contributors_github/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright 2026 Dixmit
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Contributors Github",
"summary": """Get Contributors and Contributions from Github""",
"version": "18.0.1.0.0",
"license": "AGPL-3",
"author": "Dixmit, Odoo Community Association (OCA)",
"website": "https://github.com/OCA-contributors/contributors-module",
"maintainers": ["etobella"],
"depends": ["portal", "website_partner"],
"data": [
"security/ir.model.access.csv",
"views/menu.xml",
"views/contributors_comment.xml",
"views/contributors_review.xml",
"views/contributors_branch.xml",
"views/contributors_pull_request.xml",
"views/contributors_repository.xml",
"views/contributors_organization.xml",
"views/res_partner.xml",
"data/ir_cron.xml",
"templates/templates.xml",
],
"external_dependencies": {"python": ["github3.py", "PyYAML"]},
"demo": [],
"assets": {
"web.assets_frontend": [
"contributors_github/static/src/components/**/*.esm.js",
"contributors_github/static/src/components/**/*.xml",
"contributors_github/static/src/components/**/*.scss",
],
"web.assets_tests": [
"contributors_github/static/tests/**/*",
],
},
}
1 change: 1 addition & 0 deletions contributors_github/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import main
216 changes: 216 additions & 0 deletions contributors_github/controllers/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
# Copyright 2026 Dixmit
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from math import sqrt

from markupsafe import Markup

from odoo import _, http
from odoo.http import request

from odoo.addons.portal.controllers.portal import CustomerPortal


class ContributorsController(CustomerPortal):
@http.route(
[
"/contributors",
"/contributors/<string:organization>",
],
type="http",
auth="user",
website=True,
)
def contributors_organization(self, organization=None):
values = self._prepare_portal_layout_values()
values.update(self._prepare_home_portal_values([]))
if organization is None:
organizations = request.env["contributors.organization"].search([])
return request.render(
"contributors_github.contributors_template",
{"organizations": organizations, **values},
)
organization_id = (
request.env["contributors.organization"]
.sudo()
.search([("name", "=ilike", organization)], limit=1)
.id
)
return request.render(
"contributors_github.contributors_organization_template",
{"organization": organization_id, **values},
)

def _get_index(self, data):
return round(
sqrt(data["created_pull_requests"])
+ data["merged_pull_requests"]
+ sqrt(data["comments"])
+ data["reviews"],
2,
)

def _get_field(self, kind):
if kind == "contributors":
return "partner_id"
elif kind == "organizations":
return "organization_id"
elif kind == "repositories":
return "repository_id"
return False

@http.route(["/contributors/fetch"], type="json", auth="user", readonly=True)
def fetch_data(self, organization_id, year, month, kind, period, **values):
organization = (
request.env["contributors.organization"].browse(organization_id).exists()
)
if not organization:
return []
start, end = organization._get_dates(year, month, period, **values)
data = organization._generate_data(
start, end, self._get_field(kind), kind, **values
)
return {
"columns": self._get_columns(kind),
"data": self._improve_data(data, kind, **values),
}

def _get_columns(self, kind):
if kind == "contributors":
return [
{"field": "name", "title": _("Name"), "kind": "name"},
{
"field": "index",
"title": _("Contributor Index"),
"kind": "float",
"decimals": 2,
"tooltip": Markup(
request.env["ir.qweb"]._render(
"contributors_github.contributor_index_tooltip", {}
)
),
},
{
"field": "created_pull_requests",
"title": _("Created Pull Requests"),
"kind": "float",
"decimals": 0,
},
{
"field": "merged_pull_requests",
"title": _("Merged Pull Requests"),
"kind": "float",
"decimals": 0,
},
{
"field": "comments",
"title": _("Comments"),
"kind": "float",
"decimals": 0,
},
{
"field": "reviews",
"title": _("Reviews"),
"kind": "float",
"decimals": 0,
},
]
elif kind == "organizations":
return [
{"field": "name", "title": _("Organization Name"), "kind": "name"},
{
"field": "created_pull_requests",
"title": _("Created Pull Requests"),
"kind": "float",
"decimals": 0,
},
{
"field": "merged_pull_requests",
"title": _("Merged Pull Requests"),
"kind": "float",
"decimals": 0,
},
{
"field": "comments",
"title": _("Comments"),
"kind": "float",
"decimals": 0,
},
{
"field": "reviews",
"title": _("Reviews"),
"kind": "float",
"decimals": 0,
},
{
"field": "developers",
"title": _("Developers"),
"kind": "float",
"decimals": 0,
},
]
elif kind == "repositories":
return [
{"field": "name", "title": _("Repository Name"), "kind": "name"},
{
"field": "index",
"title": _("Repository Index"),
"kind": "float",
"decimals": 2,
"tooltip": Markup(
request.env["ir.qweb"]._render(
"contributors_github.contributor_index_tooltip", {}
)
),
},
{
"field": "created_pull_requests",
"title": _("Created Pull Requests"),
"kind": "float",
"decimals": 0,
},
{
"field": "merged_pull_requests",
"title": _("Merged Pull Requests"),
"kind": "float",
"decimals": 0,
},
{
"field": "comments",
"title": _("Comments"),
"kind": "float",
"decimals": 0,
},
{
"field": "reviews",
"title": _("Reviews"),
"kind": "float",
"decimals": 0,
},
{
"field": "developers",
"title": _("Developers"),
"kind": "float",
"decimals": 0,
},
]
return []

def _improve_data(self, data, kind, **kwargs):
for key, values in data.items():
if kind == "contributors":
partner = request.env["res.partner"].browse(key)
values["name"] = partner._get_contributors_name(kind, **kwargs)
values["url"] = partner._get_contributor_url()
values["index"] = self._get_index(values)
elif kind == "organizations":
organization = request.env["res.partner"].browse(key)
values["name"] = organization._get_contributors_name(kind, **kwargs)
values["url"] = organization._get_contributor_url()
elif kind == "repositories":
repository = request.env["contributors.repository"].browse(key)
values["name"] = repository.name
github_name = f"{repository.organization_id.name}/{repository.name}"
values["url"] = f"https://github.com/{github_name}"
values["index"] = self._get_index(values)
return data
Loading