imbi-plugin-github 2.8.0__tar.gz → 2.9.1__tar.gz
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.
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/PKG-INFO +2 -2
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/pyproject.toml +4 -3
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/src/imbi_plugin_github/_hosts.py +17 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/src/imbi_plugin_github/_repos.py +25 -12
- imbi_plugin_github-2.9.1/src/imbi_plugin_github/commits.py +593 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/src/imbi_plugin_github/deployment.py +6 -7
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/src/imbi_plugin_github/lifecycle.py +78 -42
- imbi_plugin_github-2.9.1/tests/test_commits.py +549 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/tests/test_lifecycle.py +78 -0
- imbi_plugin_github-2.9.1/tests/test_repos.py +73 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/uv.lock +7 -7
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/.github/workflows/publish.yml +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/.github/workflows/test.yml +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/.gitignore +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/.pre-commit-config.yaml +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/CLAUDE.md +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/LICENSE +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/README.md +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/justfile +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/src/imbi_plugin_github/__init__.py +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/src/imbi_plugin_github/identity.py +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/tests/__init__.py +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/tests/test_deployment.py +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/tests/test_hosts.py +0 -0
- {imbi_plugin_github-2.8.0 → imbi_plugin_github-2.9.1}/tests/test_identity.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: imbi-plugin-github
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.1
|
|
4
4
|
Summary: GitHub identity plugin for Imbi (github.com / GHEC / GHES)
|
|
5
5
|
Author-email: "Gavin M. Roy" <gavinr@aweber.com>
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.14
|
|
14
14
|
Requires-Python: >=3.14
|
|
15
15
|
Requires-Dist: httpx>=0.27
|
|
16
|
-
Requires-Dist: imbi-common==2.
|
|
16
|
+
Requires-Dist: imbi-common[databases]==2.9.1
|
|
17
17
|
Requires-Dist: pydantic>=2
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "imbi-plugin-github"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.9.1"
|
|
4
4
|
description = "GitHub identity plugin for Imbi (github.com / GHEC / GHES)"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.14"
|
|
@@ -16,7 +16,7 @@ classifiers = [
|
|
|
16
16
|
]
|
|
17
17
|
dependencies = [
|
|
18
18
|
"httpx>=0.27",
|
|
19
|
-
"imbi-common==2.
|
|
19
|
+
"imbi-common[databases]==2.9.1",
|
|
20
20
|
"pydantic>=2",
|
|
21
21
|
]
|
|
22
22
|
|
|
@@ -30,12 +30,13 @@ github-deployment-es = "imbi_plugin_github.deployment:GitHubEnterpriseServerDepl
|
|
|
30
30
|
github-lifecycle = "imbi_plugin_github.lifecycle:GitHubLifecyclePlugin"
|
|
31
31
|
github-lifecycle-ec = "imbi_plugin_github.lifecycle:GitHubEnterpriseCloudLifecyclePlugin"
|
|
32
32
|
github-lifecycle-es = "imbi_plugin_github.lifecycle:GitHubEnterpriseServerLifecyclePlugin"
|
|
33
|
+
github-commit-sync = "imbi_plugin_github.commits:GitHubCommitSyncPlugin"
|
|
33
34
|
|
|
34
35
|
[dependency-groups]
|
|
35
36
|
dev = [
|
|
36
37
|
"basedpyright",
|
|
37
38
|
"coverage[toml]",
|
|
38
|
-
"imbi-common[server,databases]==2.
|
|
39
|
+
"imbi-common[server,databases]==2.9.1",
|
|
39
40
|
"pre-commit",
|
|
40
41
|
"pytest",
|
|
41
42
|
"pytest-asyncio",
|
|
@@ -48,3 +48,20 @@ def require_ghec_tenant_host(host: str, label: str) -> str:
|
|
|
48
48
|
f'got {host!r}'
|
|
49
49
|
)
|
|
50
50
|
return host
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def host_to_api_base(host: str) -> str:
|
|
54
|
+
"""Map a resolved GitHub host to its REST API base.
|
|
55
|
+
|
|
56
|
+
The single source of truth for GitHub's flavor routing:
|
|
57
|
+
``github.com`` -> ``api.github.com``, a ``*.ghe.com`` tenant ->
|
|
58
|
+
``api.<tenant>.ghe.com``, and a GHES appliance -> ``<host>/api/v3``.
|
|
59
|
+
Shared by the deployment plugins (which resolve the host per call
|
|
60
|
+
via ``_resolve_host``) and the commit-sync webhook action (which
|
|
61
|
+
resolves it from connected-plugin options at runtime).
|
|
62
|
+
"""
|
|
63
|
+
if host == 'github.com':
|
|
64
|
+
return 'https://api.github.com'
|
|
65
|
+
if host.endswith('.ghe.com'):
|
|
66
|
+
return f'https://api.{host}'
|
|
67
|
+
return f'https://{host}/api/v3'
|
|
@@ -66,23 +66,32 @@ def parse_owner_repo(url: str, target_host: str) -> tuple[str, str] | None:
|
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
def derive_owner_repo_from_links(
|
|
69
|
-
links: dict[str, str],
|
|
69
|
+
links: dict[str, str],
|
|
70
|
+
host: str,
|
|
71
|
+
*,
|
|
72
|
+
preferred_key: str | None = None,
|
|
70
73
|
) -> tuple[str, str] | None:
|
|
71
74
|
"""Find a project link pointing at ``host`` and parse owner/repo.
|
|
72
75
|
|
|
73
|
-
Prefers
|
|
74
|
-
present and
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
Prefers the dashboard link keyed by ``preferred_key`` (the bound
|
|
77
|
+
third-party-service slug) when present and pointing at ``host``,
|
|
78
|
+
then the legacy ``github-repository`` link key, then scans the
|
|
79
|
+
remaining same-host links and returns the first usable one.
|
|
80
|
+
Returns ``None`` when nothing matches.
|
|
77
81
|
"""
|
|
78
82
|
target = host.lower()
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
tried: set[str] = set()
|
|
84
|
+
for key in (preferred_key, 'github-repository'):
|
|
85
|
+
if not key or key in tried:
|
|
86
|
+
continue
|
|
87
|
+
tried.add(key)
|
|
88
|
+
url = links.get(key)
|
|
89
|
+
if url is not None:
|
|
90
|
+
owner_repo = parse_owner_repo(url, target)
|
|
91
|
+
if owner_repo is not None:
|
|
92
|
+
return owner_repo
|
|
84
93
|
for key, url in links.items():
|
|
85
|
-
if key
|
|
94
|
+
if key in tried:
|
|
86
95
|
continue
|
|
87
96
|
owner_repo = parse_owner_repo(url, target)
|
|
88
97
|
if owner_repo is not None:
|
|
@@ -110,7 +119,11 @@ def resolve_owner_repo(
|
|
|
110
119
|
so callers reacting to a slug rename (e.g. ``on_project_updated``)
|
|
111
120
|
can still locate the pre-rename repo on GitHub.
|
|
112
121
|
"""
|
|
113
|
-
derived = derive_owner_repo_from_links(
|
|
122
|
+
derived = derive_owner_repo_from_links(
|
|
123
|
+
ctx.project_links,
|
|
124
|
+
host,
|
|
125
|
+
preferred_key=ctx.third_party_service_slug,
|
|
126
|
+
)
|
|
114
127
|
if derived is not None:
|
|
115
128
|
return derived
|
|
116
129
|
if ctx.project_type_slugs:
|