odoo-addon-odoo-repository 16.0.1.3.0.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. odoo/addons/odoo_repository/README.rst +81 -0
  2. odoo/addons/odoo_repository/__init__.py +2 -0
  3. odoo/addons/odoo_repository/__manifest__.py +58 -0
  4. odoo/addons/odoo_repository/controllers/__init__.py +1 -0
  5. odoo/addons/odoo_repository/controllers/main.py +32 -0
  6. odoo/addons/odoo_repository/data/ir_cron.xml +38 -0
  7. odoo/addons/odoo_repository/data/odoo.repository.csv +216 -0
  8. odoo/addons/odoo_repository/data/odoo_branch.xml +82 -0
  9. odoo/addons/odoo_repository/data/odoo_module.xml +16 -0
  10. odoo/addons/odoo_repository/data/odoo_repository.xml +71 -0
  11. odoo/addons/odoo_repository/data/odoo_repository_addons_path.xml +59 -0
  12. odoo/addons/odoo_repository/data/odoo_repository_org.xml +14 -0
  13. odoo/addons/odoo_repository/data/queue_job.xml +56 -0
  14. odoo/addons/odoo_repository/lib/__init__.py +0 -0
  15. odoo/addons/odoo_repository/lib/scanner.py +1302 -0
  16. odoo/addons/odoo_repository/migrations/16.0.1.1.0/post-migration.py +26 -0
  17. odoo/addons/odoo_repository/migrations/16.0.1.2.0/pre-migration.py +43 -0
  18. odoo/addons/odoo_repository/migrations/16.0.1.3.0/post-migration.py +19 -0
  19. odoo/addons/odoo_repository/models/__init__.py +18 -0
  20. odoo/addons/odoo_repository/models/authentication_token.py +12 -0
  21. odoo/addons/odoo_repository/models/odoo_author.py +16 -0
  22. odoo/addons/odoo_repository/models/odoo_branch.py +111 -0
  23. odoo/addons/odoo_repository/models/odoo_license.py +16 -0
  24. odoo/addons/odoo_repository/models/odoo_maintainer.py +31 -0
  25. odoo/addons/odoo_repository/models/odoo_module.py +24 -0
  26. odoo/addons/odoo_repository/models/odoo_module_branch.py +873 -0
  27. odoo/addons/odoo_repository/models/odoo_module_branch_version.py +123 -0
  28. odoo/addons/odoo_repository/models/odoo_module_category.py +15 -0
  29. odoo/addons/odoo_repository/models/odoo_module_dev_status.py +15 -0
  30. odoo/addons/odoo_repository/models/odoo_python_dependency.py +16 -0
  31. odoo/addons/odoo_repository/models/odoo_repository.py +664 -0
  32. odoo/addons/odoo_repository/models/odoo_repository_addons_path.py +40 -0
  33. odoo/addons/odoo_repository/models/odoo_repository_branch.py +98 -0
  34. odoo/addons/odoo_repository/models/odoo_repository_org.py +23 -0
  35. odoo/addons/odoo_repository/models/res_company.py +23 -0
  36. odoo/addons/odoo_repository/models/res_config_settings.py +23 -0
  37. odoo/addons/odoo_repository/models/ssh_key.py +12 -0
  38. odoo/addons/odoo_repository/readme/CONTRIBUTORS.rst +2 -0
  39. odoo/addons/odoo_repository/readme/DESCRIPTION.rst +1 -0
  40. odoo/addons/odoo_repository/security/ir.model.access.csv +27 -0
  41. odoo/addons/odoo_repository/security/res_groups.xml +25 -0
  42. odoo/addons/odoo_repository/static/description/README +4 -0
  43. odoo/addons/odoo_repository/static/description/icon.png +0 -0
  44. odoo/addons/odoo_repository/static/description/index.html +430 -0
  45. odoo/addons/odoo_repository/tests/__init__.py +6 -0
  46. odoo/addons/odoo_repository/tests/common.py +162 -0
  47. odoo/addons/odoo_repository/tests/test_base_scanner.py +214 -0
  48. odoo/addons/odoo_repository/tests/test_odoo_module_branch.py +97 -0
  49. odoo/addons/odoo_repository/tests/test_odoo_repository_scan.py +242 -0
  50. odoo/addons/odoo_repository/tests/test_repository_scanner.py +215 -0
  51. odoo/addons/odoo_repository/tests/test_sync_node.py +55 -0
  52. odoo/addons/odoo_repository/tests/test_utils.py +25 -0
  53. odoo/addons/odoo_repository/utils/__init__.py +0 -0
  54. odoo/addons/odoo_repository/utils/github.py +30 -0
  55. odoo/addons/odoo_repository/utils/module.py +25 -0
  56. odoo/addons/odoo_repository/utils/scanner.py +90 -0
  57. odoo/addons/odoo_repository/views/authentication_token.xml +63 -0
  58. odoo/addons/odoo_repository/views/menu.xml +38 -0
  59. odoo/addons/odoo_repository/views/odoo_author.xml +54 -0
  60. odoo/addons/odoo_repository/views/odoo_branch.xml +84 -0
  61. odoo/addons/odoo_repository/views/odoo_license.xml +40 -0
  62. odoo/addons/odoo_repository/views/odoo_maintainer.xml +69 -0
  63. odoo/addons/odoo_repository/views/odoo_module.xml +90 -0
  64. odoo/addons/odoo_repository/views/odoo_module_branch.xml +353 -0
  65. odoo/addons/odoo_repository/views/odoo_module_category.xml +40 -0
  66. odoo/addons/odoo_repository/views/odoo_module_dev_status.xml +40 -0
  67. odoo/addons/odoo_repository/views/odoo_python_dependency.xml +40 -0
  68. odoo/addons/odoo_repository/views/odoo_repository.xml +165 -0
  69. odoo/addons/odoo_repository/views/odoo_repository_addons_path.xml +49 -0
  70. odoo/addons/odoo_repository/views/odoo_repository_branch.xml +60 -0
  71. odoo/addons/odoo_repository/views/odoo_repository_org.xml +54 -0
  72. odoo/addons/odoo_repository/views/res_config_settings.xml +123 -0
  73. odoo/addons/odoo_repository/views/ssh_key.xml +63 -0
  74. odoo_addon_odoo_repository-16.0.1.3.0.13.dist-info/METADATA +100 -0
  75. odoo_addon_odoo_repository-16.0.1.3.0.13.dist-info/RECORD +77 -0
  76. odoo_addon_odoo_repository-16.0.1.3.0.13.dist-info/WHEEL +5 -0
  77. odoo_addon_odoo_repository-16.0.1.3.0.13.dist-info/top_level.txt +1 -0
@@ -0,0 +1,215 @@
1
+ # Copyright 2024 Camptocamp SA
2
+ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3
+
4
+ from odoo.addons.odoo_repository.utils.scanner import RepositoryScannerOdooEnv
5
+
6
+ from .common import Common
7
+
8
+
9
+ class TestRepositoryScanner(Common):
10
+ def _init_scanner(self, **params):
11
+ kwargs = {
12
+ "org": self.org.name,
13
+ "name": self.repo_name,
14
+ "clone_url": self.repo_upstream_path,
15
+ "version": self.branch.name,
16
+ "branch": self.branch.name,
17
+ "addons_paths_data": [
18
+ {
19
+ "relative_path": ".",
20
+ "is_standard": False,
21
+ "is_enterprise": False,
22
+ "is_community": True,
23
+ },
24
+ ],
25
+ "repositories_path": self.repositories_path,
26
+ "env": self.env,
27
+ }
28
+ if params:
29
+ kwargs.update(params)
30
+ return RepositoryScannerOdooEnv(**kwargs)
31
+
32
+ def test_init(self):
33
+ scanner = self._init_scanner()
34
+ self.assertTrue(scanner.repositories_path.exists())
35
+ self.assertEqual(scanner.path.parts[-1], self.repo_name)
36
+ self.assertEqual(scanner.path.parts[-2], self.fork_org)
37
+ self.assertEqual(scanner.full_name, f"{self.fork_org}/{self.repo_name}")
38
+
39
+ def test_sync(self):
40
+ scanner = self._init_scanner()
41
+ scanner.sync()
42
+
43
+ def test_get_odoo_repository_id(self):
44
+ scanner = self._init_scanner()
45
+ repo_id = scanner._get_odoo_repository_id()
46
+ self.assertEqual(repo_id, self.odoo_repository.id)
47
+
48
+ def test_get_odoo_branch_id(self):
49
+ scanner = self._init_scanner()
50
+ branch_id = scanner._get_odoo_branch_id(self.branch.name)
51
+ self.assertEqual(branch_id, self.branch.id)
52
+
53
+ def test_create_odoo_repository_branch(self):
54
+ scanner = self._init_scanner()
55
+ repo_id = scanner._get_odoo_repository_id()
56
+ branch_id = scanner._get_odoo_branch_id(self.branch.name)
57
+ # The repository branch doesn't exist yet
58
+ expected_repo_branch_id = scanner._get_odoo_repository_branch_id(
59
+ repo_id, branch_id
60
+ )
61
+ self.assertFalse(expected_repo_branch_id)
62
+ # Create it
63
+ repo_branch_id = scanner._create_odoo_repository_branch(repo_id, branch_id)
64
+ self.assertTrue(repo_branch_id)
65
+ self.assertEqual(
66
+ repo_branch_id, scanner._get_odoo_repository_branch_id(repo_id, branch_id)
67
+ )
68
+
69
+ def test_get_repo_last_scanned_commit(self):
70
+ scanner = self._init_scanner()
71
+ repo_id = scanner._get_odoo_repository_id()
72
+ branch_id = scanner._get_odoo_branch_id(self.branch.name)
73
+ repo_branch_id = scanner._create_odoo_repository_branch(repo_id, branch_id)
74
+ repo_branch = self.env["odoo.repository.branch"].browse(repo_branch_id)
75
+ # Nothing has been scanned until now
76
+ self.assertFalse(scanner._get_repo_last_scanned_commit(repo_branch_id))
77
+ # Clone/fetch the repo
78
+ scanner.sync()
79
+ with scanner.repo() as repo:
80
+ last_fetched_commit = scanner._get_last_fetched_commit(
81
+ repo, self.branch.name
82
+ )
83
+ # Simulate the end of scan
84
+ repo_branch.last_scanned_commit = last_fetched_commit
85
+ # Check again
86
+ last_scanned_commit = scanner._get_repo_last_scanned_commit(repo_branch_id)
87
+ self.assertEqual(last_fetched_commit, last_scanned_commit)
88
+
89
+ def test_detect_modules_to_scan(self):
90
+ scanner = self._init_scanner()
91
+ scanner._clone()
92
+ repo_id = scanner._get_odoo_repository_id()
93
+ with scanner.repo() as repo:
94
+ res = scanner._detect_modules_to_scan(repo, repo_id)
95
+ self.assertTrue(res)
96
+ self.assertIn("my_module", res["addons_paths"]["."]["modules_to_scan"])
97
+
98
+ def test_detect_modules_to_scan_in_addons_path(self):
99
+ scanner = self._init_scanner()
100
+ scanner._clone()
101
+ with scanner.repo() as repo:
102
+ scanner._checkout_branch(repo, self.branch.name)
103
+ repo_id = scanner._get_odoo_repository_id()
104
+ branch_id = scanner._get_odoo_branch_id(self.branch.name)
105
+ repo_branch_id = scanner._create_odoo_repository_branch(repo_id, branch_id)
106
+ last_fetched_commit = scanner._get_last_fetched_commit(
107
+ repo, self.branch.name
108
+ )
109
+ last_scanned_commit = scanner._get_repo_last_scanned_commit(repo_branch_id)
110
+ # Scan the addons_path (root of the repository here)
111
+ modules_to_scan = scanner._detect_modules_to_scan_in_addons_path(
112
+ repo,
113
+ scanner.addons_paths_data[0]["relative_path"],
114
+ repo_branch_id,
115
+ last_fetched_commit,
116
+ last_scanned_commit,
117
+ )
118
+ module = self.addon
119
+ self.assertIn(module, modules_to_scan)
120
+
121
+ def test_scan_module(self):
122
+ scanner = self._init_scanner()
123
+ scanner._clone()
124
+ with scanner.repo() as repo:
125
+ scanner._checkout_branch(repo, self.branch.name)
126
+ repo_id = scanner._get_odoo_repository_id()
127
+ branch_id = scanner._get_odoo_branch_id(self.branch.name)
128
+ repo_branch_id = scanner._create_odoo_repository_branch(repo_id, branch_id)
129
+ module_path = self.addon
130
+ remote_branch = f"origin/{self.branch.name}"
131
+ module_tree = repo.tree(remote_branch) / module_path
132
+ last_module_commit = scanner._get_last_commit_of_git_tree(
133
+ remote_branch, module_tree
134
+ )
135
+ # Scan module
136
+ specs = scanner.addons_paths_data[0]
137
+ data = scanner._scan_module(
138
+ repo,
139
+ repo_branch_id,
140
+ module_path,
141
+ last_module_commit,
142
+ specs,
143
+ )
144
+ self.assertTrue(data)
145
+ self.assertTrue(data["code"])
146
+ self.assertTrue(data["manifest"])
147
+ self.assertEqual(data["is_standard"], specs["is_standard"])
148
+ self.assertEqual(data["is_enterprise"], specs["is_enterprise"])
149
+ self.assertEqual(data["is_community"], specs["is_community"])
150
+ self.assertEqual(data["last_scanned_commit"], last_module_commit)
151
+ self.assertIn("1.0.0", data["versions"])
152
+ self.assertEqual(data["versions"]["1.0.0"]["commit"], last_module_commit)
153
+ self.assertFalse(data["versions"]["1.0.0"]["migration_script"])
154
+
155
+ def test_push_scanned_data(self):
156
+ scanner = self._init_scanner()
157
+ scanner._clone()
158
+ with scanner.repo() as repo:
159
+ scanner._checkout_branch(repo, self.branch.name)
160
+ repo_id = scanner._get_odoo_repository_id()
161
+ branch_id = scanner._get_odoo_branch_id(self.branch.name)
162
+ repo_branch_id = scanner._create_odoo_repository_branch(repo_id, branch_id)
163
+ module = self.addon
164
+ remote_branch = f"origin/{self.branch.name}"
165
+ module_tree = repo.tree(remote_branch) / module
166
+ last_module_commit = scanner._get_last_commit_of_git_tree(
167
+ remote_branch, module_tree
168
+ )
169
+ specs = scanner.addons_paths_data[0]
170
+ data = scanner._scan_module(
171
+ repo,
172
+ repo_branch_id,
173
+ module,
174
+ last_module_commit,
175
+ specs,
176
+ )
177
+ # Push scanned data
178
+ module_branch = scanner._push_scanned_data(repo_branch_id, module, data)
179
+ self.assertEqual(module_branch.module_id.name, module)
180
+ self.assertEqual(module_branch.repository_branch_id.id, repo_branch_id)
181
+ self.assertRecordValues(
182
+ module_branch,
183
+ [
184
+ {
185
+ "repository_branch_id": repo_branch_id,
186
+ "is_standard": specs["is_standard"],
187
+ "is_enterprise": specs["is_enterprise"],
188
+ "is_community": specs["is_community"],
189
+ "application": data["manifest"].get("application", False),
190
+ "installable": data["manifest"]["installable"],
191
+ "sloc_python": data["code"]["Python"],
192
+ "sloc_xml": data["code"]["XML"],
193
+ "sloc_js": data["code"]["JavaScript"],
194
+ "sloc_css": data["code"]["CSS"],
195
+ "last_scanned_commit": last_module_commit,
196
+ }
197
+ ],
198
+ )
199
+
200
+ def test_update_last_scanned_commit(self):
201
+ scanner = self._init_scanner()
202
+ scanner._clone()
203
+ repo_id = scanner._get_odoo_repository_id()
204
+ branch_id = scanner._get_odoo_branch_id(self.branch.name)
205
+ repo_branch_id = scanner._create_odoo_repository_branch(repo_id, branch_id)
206
+ repo_branch = self.env["odoo.repository.branch"].browse(repo_branch_id)
207
+ with scanner.repo() as repo:
208
+ last_repo_commit = scanner._get_last_fetched_commit(repo, self.branch.name)
209
+ self.assertFalse(repo_branch.last_scanned_commit)
210
+ scanner._update_last_scanned_commit(repo_branch_id, last_repo_commit)
211
+ self.assertEqual(repo_branch.last_scanned_commit, last_repo_commit)
212
+
213
+ def test_workaround_fs_errors(self):
214
+ scanner = self._init_scanner(workaround_fs_errors=True)
215
+ scanner.sync()
@@ -0,0 +1,55 @@
1
+ # Copyright 2024 Camptocamp SA
2
+ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3
+
4
+ from .common import Common
5
+
6
+
7
+ class TestSyncNode(Common):
8
+ def test_sync_node(self):
9
+ # Scan a repository
10
+ self.odoo_repository.with_context(queue_job__no_delay=True).action_scan(
11
+ self.branch.ids
12
+ )
13
+ # Check data to sync
14
+ data = self.env["odoo.module.branch"]._get_modules_data()
15
+ self.assertEqual(len(data), 1) # 1 module scanned
16
+ module = data[0]
17
+ self.assertEqual(module["module"], self.module_name)
18
+ self.assertEqual(module["branch"], self.branch.name)
19
+ self.assertEqual(module["version"], "1.0.0")
20
+ self.assertTrue(module["versions"])
21
+ self.assertEqual(module["addons_path"], ".")
22
+ self.assertEqual(module["repository"]["name"], self.odoo_repository.name)
23
+ self.assertEqual(module["repository"]["org"], self.odoo_repository.org_id.name)
24
+ self.assertEqual(
25
+ module["repository"]["repo_type"], self.odoo_repository.repo_type
26
+ )
27
+ self.assertEqual(
28
+ module["repository"]["repo_url"], self.odoo_repository.repo_url
29
+ )
30
+ # Sync these data with a node
31
+ # NOTE as we are using the same node to sync with in tests, we change
32
+ # the content of the data to sync to create a new module
33
+ data[0].update(
34
+ module="synced",
35
+ version="2.0.0",
36
+ branch=self.branch2_name,
37
+ )
38
+ new_module = self.env["odoo.module"].search([("name", "=", "synced")])
39
+ self.assertFalse(new_module)
40
+ self.env["odoo.repository"]._import_data(data)
41
+ nb_modules = self.env["odoo.module"].search_count([])
42
+ self.assertTrue(nb_modules >= 2)
43
+ new_module = self.env["odoo.module.branch"].search(
44
+ [("module_name", "=", "synced")]
45
+ )
46
+ self.assertTrue(new_module)
47
+ self.assertEqual(new_module.version, "2.0.0")
48
+ self.assertEqual(new_module.branch_id.name, self.branch2_name)
49
+ # Existing module didn't changed
50
+ existing_module = self.env["odoo.module.branch"].search(
51
+ [("module_name", "=", self.module_name)]
52
+ )
53
+ self.assertTrue(existing_module)
54
+ self.assertEqual(existing_module.version, "1.0.0")
55
+ self.assertEqual(existing_module.branch_id, self.branch)
@@ -0,0 +1,25 @@
1
+ # Copyright 2024 Camptocamp SA
2
+ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3
+
4
+ from odoo.tests.common import TransactionCase
5
+
6
+ from odoo.addons.odoo_repository.utils.module import adapt_version
7
+
8
+
9
+ class TestUtils(TransactionCase):
10
+ @classmethod
11
+ def setUpClass(cls):
12
+ super().setUpClass()
13
+ cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
14
+
15
+ def test_adapt_version(self):
16
+ # Module version equals major version: add prefix
17
+ self.assertEqual(adapt_version("14.0", "14.0"), "14.0.14.0")
18
+ # Basic module version: add prefix
19
+ self.assertEqual(adapt_version("14.0", "1.0.0"), "14.0.1.0.0")
20
+ # Module version already prefixed with major version
21
+ self.assertEqual(adapt_version("14.0", "14.0.1.0.0"), "14.0.1.0.0")
22
+ # Dot chars added as prefix or suffix in the provided version
23
+ self.assertEqual(adapt_version("14.0", ".1.0.0"), "14.0.1.0.0")
24
+ self.assertEqual(adapt_version("14.0", "1.0.0."), "14.0.1.0.0")
25
+ self.assertEqual(adapt_version("14.0", "...1.0.0..."), "14.0.1.0.0")
File without changes
@@ -0,0 +1,30 @@
1
+ # Copyright 2023 Camptocamp SA
2
+ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3
+
4
+ import os
5
+
6
+ import requests
7
+
8
+ GITHUB_URL = "https://github.com"
9
+ GITHUB_API_URL = "https://api.github.com"
10
+
11
+
12
+ def request(env, url, method="get", params=None, json=None):
13
+ """Request GitHub API."""
14
+ headers = {"Accept": "application/vnd.github.groot-preview+json"}
15
+ key = "odoo_repository_github_token"
16
+ token = env["ir.config_parameter"].sudo().get_param(key, "") or os.environ.get(
17
+ "GITHUB_TOKEN"
18
+ )
19
+ if token:
20
+ headers.update({"Authorization": f"token {token}"})
21
+ full_url = "/".join([GITHUB_API_URL, url])
22
+ kwargs = {"headers": headers}
23
+ if json:
24
+ kwargs.update(json=json)
25
+ if params:
26
+ kwargs.update(params=params)
27
+ response = getattr(requests, method)(full_url, **kwargs)
28
+ if not response.ok:
29
+ raise RuntimeError(response.text)
30
+ return response.json()
@@ -0,0 +1,25 @@
1
+ # Copyright 2023 Camptocamp SA
2
+ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)
3
+
4
+
5
+ def adapt_version(major_version: str, module_version: str):
6
+ """Return the module version prefixed with major version.
7
+
8
+ This function has been copied and adapted from upstream Odoo source code:
9
+ https://github.com/odoo/odoo/blob/16.0/odoo/modules/module.py#L527-L533
10
+ """
11
+ # Remove extra special characters (e.g. '14.0.' => '14.0')
12
+ # NOTE: we need to sanitize such versions in order to compute a
13
+ # sequence number helping the sort of module versions.
14
+ chars = ["."]
15
+ for char in chars:
16
+ while module_version.startswith(char):
17
+ module_version = module_version[1:]
18
+ while module_version.endswith(char):
19
+ module_version = module_version[:-1]
20
+ # Append major Odoo version as prefix if needed
21
+ if module_version == major_version or not module_version.startswith(
22
+ major_version + "."
23
+ ):
24
+ module_version = "%s.%s" % (major_version, module_version)
25
+ return module_version
@@ -0,0 +1,90 @@
1
+ # Copyright 2023 Camptocamp SA
2
+ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3
+
4
+ from odoo.tools import config
5
+
6
+ from ..lib.scanner import RepositoryScanner
7
+
8
+
9
+ class RepositoryScannerOdooEnv(RepositoryScanner):
10
+ """RepositoryScanner running on the same server than Odoo.
11
+
12
+ This class takes an additional `env` parameter (`odoo.api.Environment`)
13
+ used to request Odoo, and implement required methods to use it.
14
+ """
15
+
16
+ def __init__(self, *args, **kwargs):
17
+ if kwargs.get("env"):
18
+ self.env = kwargs.pop("env")
19
+ super().__init__(*args, **kwargs)
20
+
21
+ def _get_odoo_repository_id(self):
22
+ return (
23
+ self.env["odoo.repository"]
24
+ .search([("name", "=", self.name), ("org_id", "=", self.org)])
25
+ .id
26
+ )
27
+
28
+ def _get_odoo_branch_id(self, version):
29
+ return self.env["odoo.branch"].search([("name", "=", version)]).id
30
+
31
+ def _get_odoo_repository_branch_id(self, repo_id, branch_id):
32
+ args = [
33
+ ("repository_id", "=", repo_id),
34
+ ("branch_id", "=", branch_id),
35
+ ]
36
+ repo_branch = self.env["odoo.repository.branch"].search(args, limit=1)
37
+ if repo_branch:
38
+ return repo_branch.id
39
+
40
+ def _create_odoo_repository_branch(self, repo_id, branch_id, cloned_branch=None):
41
+ repo_branch_id = self._get_odoo_repository_branch_id(repo_id, branch_id)
42
+ if not repo_branch_id:
43
+ values = {
44
+ "repository_id": repo_id,
45
+ "branch_id": branch_id,
46
+ }
47
+ if cloned_branch:
48
+ values["cloned_branch"] = cloned_branch
49
+ repo_branch_model = self.env["odoo.repository.branch"]
50
+ repo_branch_id = repo_branch_model.create(values).id
51
+ return repo_branch_id
52
+
53
+ def _get_repo_last_scanned_commit(self, repo_branch_id):
54
+ repo_branch_model = self.env["odoo.repository.branch"]
55
+ repo_branch = repo_branch_model.browse(repo_branch_id)
56
+ return repo_branch.last_scanned_commit
57
+
58
+ def _is_module_blacklisted(self, module):
59
+ return bool(
60
+ self.env["odoo.module"].search_count(
61
+ [("name", "=", module), ("blacklisted", "=", True)]
62
+ )
63
+ )
64
+
65
+ def _get_module_last_scanned_commit(self, repo_branch_id, module_name):
66
+ module_branch_model = self.env["odoo.module.branch"]
67
+ args = [
68
+ ("repository_branch_id", "=", repo_branch_id),
69
+ ("module_name", "=", module_name),
70
+ ]
71
+ module = module_branch_model.search(args)
72
+ return module.last_scanned_commit
73
+
74
+ def _push_scanned_data(self, repo_branch_id, module, data):
75
+ res = self.env["odoo.module.branch"].push_scanned_data(
76
+ repo_branch_id, module, data
77
+ )
78
+ # Commit after each module
79
+ if not config["test_enable"]:
80
+ self.env.cr.commit() # pylint: disable=invalid-commit
81
+ return res
82
+
83
+ def _update_last_scanned_commit(self, repo_branch_id, last_fetched_commit):
84
+ repo_branch_model = self.env["odoo.repository.branch"]
85
+ repo_branch = repo_branch_model.browse(repo_branch_id)
86
+ repo_branch.last_scanned_commit = last_fetched_commit
87
+ # Commit after each repository/branch
88
+ if not config["test_enable"]:
89
+ self.env.cr.commit() # pylint: disable=invalid-commit
90
+ return True
@@ -0,0 +1,63 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <!-- Copyright 2024 Camptocamp SA
3
+ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
4
+ <odoo>
5
+
6
+ <record id="authentication_token_view_form" model="ir.ui.view">
7
+ <field name="name">authentication.token.form</field>
8
+ <field name="model">authentication.token</field>
9
+ <field
10
+ name="groups_id"
11
+ eval="[(4,ref('odoo_repository.group_odoo_repository_manager'))]"
12
+ />
13
+ <field name="arch" type="xml">
14
+ <form>
15
+ <sheet>
16
+ <group>
17
+ <field name="name" />
18
+ <field name="token" password="True" />
19
+ </group>
20
+ </sheet>
21
+ </form>
22
+ </field>
23
+ </record>
24
+
25
+ <record id="authentication_token_view_tree" model="ir.ui.view">
26
+ <field name="name">authentication.token.tree</field>
27
+ <field name="model">authentication.token</field>
28
+ <field name="arch" type="xml">
29
+ <tree>
30
+ <field name="name" />
31
+ </tree>
32
+ </field>
33
+ </record>
34
+
35
+ <record id="authentication_token_view_search" model="ir.ui.view">
36
+ <field name="name">authentication.token.search</field>
37
+ <field name="model">authentication.token</field>
38
+ <field name="type">search</field>
39
+ <field name="arch" type="xml">
40
+ <search>
41
+ <field name="name" />
42
+ </search>
43
+ </field>
44
+ </record>
45
+
46
+ <record id="authentication_token_action" model="ir.actions.act_window">
47
+ <field name="name">Authentication Tokens</field>
48
+ <field name="type">ir.actions.act_window</field>
49
+ <field name="res_model">authentication.token</field>
50
+ <field name="view_id" ref="authentication_token_view_tree" />
51
+ <field
52
+ name="groups_id"
53
+ eval="[(4,ref('odoo_repository.group_odoo_repository_manager'))]"
54
+ />
55
+ </record>
56
+
57
+ <menuitem
58
+ id="authentication_token_menu"
59
+ parent="config_odoo_repository_menu"
60
+ action="authentication_token_action"
61
+ />
62
+
63
+ </odoo>
@@ -0,0 +1,38 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <!-- Copyright 2023 Camptocamp SA
3
+ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
4
+ <odoo>
5
+
6
+ <menuitem
7
+ id="main_odoo_repository_menu"
8
+ groups="odoo_repository.group_odoo_repository_user"
9
+ web_icon="odoo_repository,static/description/icon.png"
10
+ name="Odoo Repositories"
11
+ />
12
+ <menuitem
13
+ id="data_odoo_repository_menu"
14
+ parent="main_odoo_repository_menu"
15
+ name="Data"
16
+ sequence="20"
17
+ />
18
+ <menuitem
19
+ id="report_odoo_repository_menu"
20
+ parent="main_odoo_repository_menu"
21
+ name="Report"
22
+ sequence="30"
23
+ />
24
+ <menuitem
25
+ id="misc_odoo_repository_menu"
26
+ parent="main_odoo_repository_menu"
27
+ name="Misc."
28
+ sequence="40"
29
+ />
30
+ <menuitem
31
+ id="config_odoo_repository_menu"
32
+ parent="main_odoo_repository_menu"
33
+ groups="odoo_repository.group_odoo_repository_manager"
34
+ name="Configuration"
35
+ sequence="50"
36
+ />
37
+
38
+ </odoo>
@@ -0,0 +1,54 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <!-- Copyright 2023 Camptocamp SA
3
+ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
4
+ <odoo>
5
+
6
+ <record id="odoo_author_view_form" model="ir.ui.view">
7
+ <field name="name">odoo.author.form</field>
8
+ <field name="model">odoo.author</field>
9
+ <field name="arch" type="xml">
10
+ <form>
11
+ <sheet>
12
+ <group>
13
+ <field name="name" />
14
+ </group>
15
+ </sheet>
16
+ </form>
17
+ </field>
18
+ </record>
19
+
20
+ <record id="odoo_author_view_tree" model="ir.ui.view">
21
+ <field name="name">odoo.author.tree</field>
22
+ <field name="model">odoo.author</field>
23
+ <field name="arch" type="xml">
24
+ <tree>
25
+ <field name="name" />
26
+ </tree>
27
+ </field>
28
+ </record>
29
+
30
+ <record id="odoo_author_view_search" model="ir.ui.view">
31
+ <field name="name">odoo.author.search</field>
32
+ <field name="model">odoo.author</field>
33
+ <field name="type">search</field>
34
+ <field name="arch" type="xml">
35
+ <search>
36
+ <field name="name" />
37
+ </search>
38
+ </field>
39
+ </record>
40
+
41
+ <record id="odoo_author_action" model="ir.actions.act_window">
42
+ <field name="name">Authors</field>
43
+ <field name="type">ir.actions.act_window</field>
44
+ <field name="res_model">odoo.author</field>
45
+ <field name="view_id" ref="odoo_author_view_tree" />
46
+ </record>
47
+
48
+ <menuitem
49
+ id="odoo_author_menu"
50
+ parent="misc_odoo_repository_menu"
51
+ action="odoo_author_action"
52
+ />
53
+
54
+ </odoo>