python-github-plus 0.0.1__py3-none-any.whl → 0.0.3__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.
- python_github_plus/__init__.py +2 -6
- python_github_plus/github_plus.py +31 -31
- {python_github_plus-0.0.1.dist-info → python_github_plus-0.0.3.dist-info}/METADATA +3 -2
- python_github_plus-0.0.3.dist-info/RECORD +7 -0
- python_github_plus-0.0.1.dist-info/RECORD +0 -7
- {python_github_plus-0.0.1.dist-info → python_github_plus-0.0.3.dist-info}/WHEEL +0 -0
- {python_github_plus-0.0.1.dist-info → python_github_plus-0.0.3.dist-info}/licenses/LICENSE +0 -0
- {python_github_plus-0.0.1.dist-info → python_github_plus-0.0.3.dist-info}/top_level.txt +0 -0
python_github_plus/__init__.py
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
from dotenv import load_dotenv
|
|
2
2
|
|
|
3
|
-
from python_github_plus.github_plus import GitHubPRStatus, GitHubWorkflowStatus
|
|
3
|
+
from python_github_plus.github_plus import GitHubClient, GitHubPRStatus, GitHubWorkflowStatus
|
|
4
4
|
|
|
5
5
|
load_dotenv()
|
|
6
6
|
|
|
7
|
-
__all__ = [
|
|
8
|
-
'GitHubPRStatus',
|
|
9
|
-
'GitHubWorkflowStatus',
|
|
10
|
-
'GitHubClient'
|
|
11
|
-
]
|
|
7
|
+
__all__ = ["GitHubPRStatus", "GitHubWorkflowStatus", "GitHubClient"]
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
+
import builtins
|
|
1
2
|
import os
|
|
2
3
|
import time
|
|
3
4
|
from enum import Enum
|
|
4
|
-
from typing import Optional, List
|
|
5
5
|
|
|
6
|
-
from
|
|
6
|
+
from custom_python_logger import get_logger
|
|
7
|
+
from github import Auth, Github, GithubException
|
|
8
|
+
from github.Branch import Branch
|
|
9
|
+
from github.ContentFile import ContentFile
|
|
7
10
|
from github.GitRef import GitRef
|
|
8
11
|
from github.GitTag import GitTag
|
|
12
|
+
from github.PullRequest import PullRequest
|
|
9
13
|
from github.Repository import Repository
|
|
10
|
-
from github.Branch import Branch
|
|
11
14
|
from github.Tag import Tag
|
|
12
|
-
from github.PullRequest import PullRequest
|
|
13
|
-
from github.ContentFile import ContentFile
|
|
14
|
-
from custom_python_logger import get_logger
|
|
15
15
|
from github.Workflow import Workflow
|
|
16
16
|
from github.WorkflowRun import WorkflowRun
|
|
17
17
|
|
|
@@ -29,14 +29,14 @@ class GitHubWorkflowStatus(Enum):
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
class GitHubProjectService:
|
|
32
|
-
def __init__(self, repo: Repository):
|
|
32
|
+
def __init__(self, repo: Repository) -> None:
|
|
33
33
|
self.logger = get_logger(self.__class__.__name__)
|
|
34
34
|
self.repo = repo
|
|
35
35
|
|
|
36
36
|
def get_info(self) -> Repository:
|
|
37
37
|
return self.repo
|
|
38
38
|
|
|
39
|
-
def list_members(self):
|
|
39
|
+
def list_members(self) -> list:
|
|
40
40
|
return list(self.repo.get_collaborators())
|
|
41
41
|
|
|
42
42
|
def add_member(self, username: str, permission: str = "push") -> None:
|
|
@@ -55,7 +55,7 @@ class GitHubProjectService:
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
class GitHubWorkflowService:
|
|
58
|
-
def __init__(self, repo: Repository):
|
|
58
|
+
def __init__(self, repo: Repository) -> None:
|
|
59
59
|
self.logger = get_logger(self.__class__.__name__)
|
|
60
60
|
self.repo = repo
|
|
61
61
|
|
|
@@ -63,7 +63,7 @@ class GitHubWorkflowService:
|
|
|
63
63
|
"""List workflows configured in the repo (.github/workflows)."""
|
|
64
64
|
return list(self.repo.get_workflows())
|
|
65
65
|
|
|
66
|
-
def trigger(self, workflow_name: str, branch_name: str = "main", inputs:
|
|
66
|
+
def trigger(self, workflow_name: str, branch_name: str = "main", inputs: dict | None = None) -> Workflow:
|
|
67
67
|
"""
|
|
68
68
|
Dispatch a workflow by name on a given branch.
|
|
69
69
|
Requires 'workflow_dispatch' defined in the workflow YAML.
|
|
@@ -82,7 +82,7 @@ class GitHubWorkflowService:
|
|
|
82
82
|
def get_workflow_by_id(self, workflow_id: int) -> Workflow:
|
|
83
83
|
return self.repo.get_workflow(workflow_id)
|
|
84
84
|
|
|
85
|
-
def list_runs(self, workflow_name: str, branch:
|
|
85
|
+
def list_runs(self, workflow_name: str, branch: str | None = None) -> builtins.list[WorkflowRun]:
|
|
86
86
|
workflows = {wf.name: wf for wf in self.repo.get_workflows()}
|
|
87
87
|
if workflow_name not in workflows:
|
|
88
88
|
raise ValueError(f"❌ Workflow '{workflow_name}' not found.")
|
|
@@ -94,33 +94,32 @@ class GitHubWorkflowService:
|
|
|
94
94
|
return self.repo.get_workflow(workflow_id).get_runs()[0]
|
|
95
95
|
|
|
96
96
|
def status(self, run_id: int) -> str:
|
|
97
|
-
"""
|
|
97
|
+
"""Get the current status of a workflow run. run_id is the ID of the run, not the workflow."""
|
|
98
98
|
run = self.repo.get_workflow_run(run_id)
|
|
99
99
|
return run.status # "queued", "in_progress", "completed"
|
|
100
100
|
|
|
101
|
-
def conclusion(self, run_id: int) ->
|
|
102
|
-
"""
|
|
101
|
+
def conclusion(self, run_id: int) -> str | None:
|
|
102
|
+
"""
|
|
103
|
+
Get the conclusion of a completed workflow run.
|
|
104
|
+
None if still running. run_id is the ID of the run, not the workflow.
|
|
105
|
+
"""
|
|
103
106
|
run = self.repo.get_workflow_run(run_id)
|
|
104
107
|
return run.conclusion # "success", "failure", "cancelled", None if still running
|
|
105
108
|
|
|
106
|
-
def wait_until_finished(self, run_id: int, check_interval=10, timeout:
|
|
109
|
+
def wait_until_finished(self, run_id: int, check_interval: int = 10, timeout: int = 10) -> str:
|
|
107
110
|
start_time = time.time()
|
|
108
|
-
while
|
|
111
|
+
while (time.time() - start_time) >= timeout: # pylint: disable=W0149
|
|
109
112
|
run = self.repo.get_workflow_run(run_id)
|
|
110
|
-
|
|
111
113
|
if run.status == "completed":
|
|
112
114
|
self.logger.info(f"✅ Workflow run {run_id} finished with conclusion = {run.conclusion}")
|
|
113
115
|
return run.conclusion
|
|
114
|
-
|
|
115
|
-
if timeout and (time.time() - start_time) > timeout:
|
|
116
|
-
raise TimeoutError(f"⏰ Workflow run {run_id} did not complete within {timeout} seconds.")
|
|
117
|
-
|
|
118
116
|
self.logger.debug(f"⏳ Workflow run {run_id} still {run.status}...")
|
|
119
117
|
time.sleep(check_interval)
|
|
118
|
+
raise TimeoutError(f"⏰ Workflow run {run_id} did not complete within {timeout} seconds.")
|
|
120
119
|
|
|
121
120
|
|
|
122
121
|
class GitHubBranchService:
|
|
123
|
-
def __init__(self, repo: Repository):
|
|
122
|
+
def __init__(self, repo: Repository) -> None:
|
|
124
123
|
self.logger = get_logger(self.__class__.__name__)
|
|
125
124
|
self.repo = repo
|
|
126
125
|
|
|
@@ -146,7 +145,7 @@ class GitHubBranchService:
|
|
|
146
145
|
dismiss_stale_reviews: bool = True,
|
|
147
146
|
required_approving_review_count: int = 1,
|
|
148
147
|
require_status_checks: bool = False,
|
|
149
|
-
status_check_contexts:
|
|
148
|
+
status_check_contexts: builtins.list[str] | None = None,
|
|
150
149
|
) -> None:
|
|
151
150
|
"""
|
|
152
151
|
Protect a branch with common settings.
|
|
@@ -168,20 +167,20 @@ class GitHubBranchService:
|
|
|
168
167
|
|
|
169
168
|
|
|
170
169
|
class GitHubTagService:
|
|
171
|
-
def __init__(self, repo: Repository):
|
|
170
|
+
def __init__(self, repo: Repository) -> None:
|
|
172
171
|
self.logger = get_logger(self.__class__.__name__)
|
|
173
172
|
self.repo = repo
|
|
174
173
|
|
|
175
|
-
def
|
|
174
|
+
def create_from_sha(self, tag_name: str, sha: str, message: str | None = None) -> GitTag:
|
|
176
175
|
tag = self.repo.create_git_tag(tag=tag_name, message=message or tag_name, object="main", type="commit")
|
|
177
176
|
self.repo.create_git_ref(ref=f"refs/tags/{tag_name}", sha=tag.sha)
|
|
178
177
|
self.logger.info(f"✅ Tag '{tag_name}' created at commit {sha}")
|
|
179
178
|
return tag
|
|
180
179
|
|
|
181
|
-
def
|
|
180
|
+
def create(self, tag_name: str, from_branch: str, message: str | None = None) -> GitTag:
|
|
182
181
|
branch = self.repo.get_branch(from_branch)
|
|
183
182
|
sha = branch.commit.sha
|
|
184
|
-
return self.
|
|
183
|
+
return self.create_from_sha(tag_name=tag_name, sha=sha, message=message)
|
|
185
184
|
|
|
186
185
|
def delete(self, tag_name: str) -> None:
|
|
187
186
|
ref = self.repo.get_git_ref(f"tags/{tag_name}")
|
|
@@ -193,7 +192,7 @@ class GitHubTagService:
|
|
|
193
192
|
|
|
194
193
|
|
|
195
194
|
class GitHubPRService:
|
|
196
|
-
def __init__(self, repo: Repository):
|
|
195
|
+
def __init__(self, repo: Repository) -> None:
|
|
197
196
|
self.logger = get_logger(self.__class__.__name__)
|
|
198
197
|
self.repo = repo
|
|
199
198
|
|
|
@@ -243,7 +242,7 @@ class GitHubPRService:
|
|
|
243
242
|
|
|
244
243
|
|
|
245
244
|
class GitHubFileService:
|
|
246
|
-
def __init__(self, repo: Repository):
|
|
245
|
+
def __init__(self, repo: Repository) -> None:
|
|
247
246
|
self.logger = get_logger(self.__class__.__name__)
|
|
248
247
|
self.repo = repo
|
|
249
248
|
|
|
@@ -273,8 +272,9 @@ class GitHubFileService:
|
|
|
273
272
|
# Facade / User Interface #
|
|
274
273
|
# ----------------------- #
|
|
275
274
|
|
|
275
|
+
|
|
276
276
|
class GitHubClient:
|
|
277
|
-
def __init__(self, access_token:
|
|
277
|
+
def __init__(self, access_token: str | None, repo_full_name: str) -> None:
|
|
278
278
|
self.logger = get_logger(self.__class__.__name__)
|
|
279
279
|
self.github_access_token = access_token or os.environ.get("GITHUB_ACCESS_TOKEN")
|
|
280
280
|
|
|
@@ -297,6 +297,6 @@ class GitHubClient:
|
|
|
297
297
|
except Exception as e:
|
|
298
298
|
msg = f"❌ Failed to authenticate with GitHub: {e}"
|
|
299
299
|
if raise_if_not_connected:
|
|
300
|
-
raise ValueError(msg)
|
|
300
|
+
raise ValueError(msg) from e
|
|
301
301
|
self.logger.exception(msg)
|
|
302
302
|
return False
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-github-plus
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: Enhanced Python GitHub client.
|
|
5
5
|
Home-page: https://github.com/aviz92/python-github-plus
|
|
6
6
|
Author: Avi Zaguri
|
|
@@ -12,6 +12,7 @@ License-File: LICENSE
|
|
|
12
12
|
Requires-Dist: setuptools
|
|
13
13
|
Requires-Dist: wheel
|
|
14
14
|
Requires-Dist: python-dotenv
|
|
15
|
+
Requires-Dist: pre-commit
|
|
15
16
|
Requires-Dist: pytest
|
|
16
17
|
Requires-Dist: pygithub
|
|
17
18
|
Requires-Dist: custom-python-logger
|
|
@@ -199,7 +200,7 @@ github_client = GitHubClient(
|
|
|
199
200
|
)
|
|
200
201
|
|
|
201
202
|
# Create a tag
|
|
202
|
-
tag = github_client.tag.
|
|
203
|
+
tag = github_client.tag.create(
|
|
203
204
|
tag_name="v1.0.0",
|
|
204
205
|
from_branch="main",
|
|
205
206
|
message="Release version 1.0.0"
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
python_github_plus/__init__.py,sha256=X9i7u5Or-dmMMWc2R9Vq982MjK-BGpPbvSs3yL7i_ew,211
|
|
2
|
+
python_github_plus/github_plus.py,sha256=StZteUBh5njuXxj0lu0U6FfS_O-59m-AnIV-z1sNevo,12122
|
|
3
|
+
python_github_plus-0.0.3.dist-info/licenses/LICENSE,sha256=cSikHY6SZFsPZSBizCDAJ0-Bjjzxt-JtX6TVbKxwimo,1067
|
|
4
|
+
python_github_plus-0.0.3.dist-info/METADATA,sha256=SXlBVBtOom2m0G_PA_weI-6OPwJ-UTaURjrRLPGEm2Q,6652
|
|
5
|
+
python_github_plus-0.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
6
|
+
python_github_plus-0.0.3.dist-info/top_level.txt,sha256=lm_rQAamcpxcN00h3Thamd05_z5PdTfy-RVSuCpN_xA,19
|
|
7
|
+
python_github_plus-0.0.3.dist-info/RECORD,,
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
python_github_plus/__init__.py,sha256=MO6TwnFs1o64c3qmWrnFD85RQZ2yHCMoVblkzTsjnRU,225
|
|
2
|
-
python_github_plus/github_plus.py,sha256=1wfLgbM60HSPkHb6lNU_aS5fSO-LzcUO4LH6otEo30c,12078
|
|
3
|
-
python_github_plus-0.0.1.dist-info/licenses/LICENSE,sha256=cSikHY6SZFsPZSBizCDAJ0-Bjjzxt-JtX6TVbKxwimo,1067
|
|
4
|
-
python_github_plus-0.0.1.dist-info/METADATA,sha256=4LJcwAx0vRd4QQDV7aThFEV04n-scFpH3VoW54DVgz4,6636
|
|
5
|
-
python_github_plus-0.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
6
|
-
python_github_plus-0.0.1.dist-info/top_level.txt,sha256=lm_rQAamcpxcN00h3Thamd05_z5PdTfy-RVSuCpN_xA,19
|
|
7
|
-
python_github_plus-0.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|