Skip to content

Commit ef1d976

Browse files
authored
Merge pull request #158 from devchat-ai/update_workreport
feat: Add GitHub repository API support for work reports
2 parents 345d121 + e19910f commit ef1d976

2 files changed

Lines changed: 165 additions & 7 deletions

File tree

community/github/git_api.py

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,12 @@ def get_current_repo():
4141
if not current_repo_dir:
4242
selected_data = IDEService().get_selected_range().dict()
4343
current_file = selected_data.get("abspath", None)
44+
4445
if not current_file:
4546
return None
4647
current_dir = os.path.dirname(current_file)
48+
if not os.path.exists(current_dir):
49+
current_dir = os.getcwd()
4750
try:
4851
# 获取仓库根目录
4952
current_repo_dir = (
@@ -585,3 +588,143 @@ def get_github_repo_issues(
585588
return response.json()
586589
else:
587590
return None
591+
592+
593+
def get_repo_issues(
594+
repo: str,
595+
assignee_username: str = None,
596+
state: str = "open",
597+
created_after=None,
598+
created_before=None,
599+
):
600+
"""
601+
Get issues from a GitHub repository with optional filtering.
602+
603+
Args:
604+
repo (str): Repository name in the format 'owner/repo'
605+
assignee_username (str, optional): Filter issues by assignee username.
606+
Special values: '*' (any assigned), 'none' (unassigned)
607+
state (str, optional): Filter issues by state ('open', 'closed', 'all'). Default is 'open'.
608+
created_after (str, optional): ISO 8601 formatted timestamp to filter issues created after
609+
this date
610+
created_before (str, optional): ISO 8601 formatted timestamp to filter issues created
611+
before this date
612+
613+
Returns:
614+
list: List of issue objects from the GitHub API
615+
"""
616+
url = f"{GITHUB_API_URL}/repos/{repo}/issues"
617+
618+
params = {
619+
"state": state,
620+
}
621+
622+
# 处理assignee参数
623+
if assignee_username is not None:
624+
# 如果提供了assignee_username,则使用它
625+
params["assignee"] = assignee_username
626+
627+
# GitHub uses 'since' parameter for created_after
628+
if created_after:
629+
params["since"] = created_after
630+
631+
headers = {
632+
"Authorization": f"token {GITHUB_ACCESS_TOKEN}",
633+
"Accept": "application/vnd.github.v3+json",
634+
}
635+
636+
response = requests.get(url, headers=headers, params=params)
637+
638+
if response.status_code == 200:
639+
issues = response.json()
640+
641+
# Filter by created_before if specified
642+
if created_before:
643+
issues = [
644+
issue
645+
for issue in issues
646+
if issue["created_at"][: len(created_before)] <= created_before
647+
]
648+
649+
return issues
650+
else:
651+
print(f"Failed to get issues: {response.status_code}", file=sys.stderr)
652+
print(response.text, file=sys.stderr)
653+
return []
654+
655+
656+
def get_commit_author():
657+
cmd = ["git", "config", "user.email"]
658+
return subprocess_check_output(cmd).decode("utf-8").strip()
659+
660+
661+
def get_repo_commits(repo: str, author=None, since=None, until=None):
662+
"""
663+
Get commits from a GitHub repository with optional filtering.
664+
665+
Args:
666+
repo (str): Repository name in the format 'owner/repo'
667+
author (str, optional): Filter commits by author
668+
since (str, optional): ISO 8601 formatted timestamp to filter commits after this date
669+
until (str, optional): ISO 8601 formatted timestamp to filter commits before this date
670+
671+
Returns:
672+
list: List of commit objects from the GitHub API
673+
"""
674+
url = f"{GITHUB_API_URL}/repos/{repo}/commits"
675+
676+
params = {}
677+
if author:
678+
params["author"] = author
679+
if since:
680+
params["since"] = since
681+
if until:
682+
params["until"] = until
683+
684+
headers = {
685+
"Authorization": f"token {GITHUB_ACCESS_TOKEN}",
686+
"Accept": "application/vnd.github.v3+json",
687+
}
688+
689+
response = requests.get(url, headers=headers, params=params)
690+
691+
if response.status_code == 200:
692+
return response.json()
693+
else:
694+
print(f"Failed to get commits: {response.status_code}")
695+
print(response.text)
696+
return None
697+
698+
699+
def is_github_repo():
700+
"""
701+
Check if the current repository is a GitHub repository.
702+
703+
Tries to determine if the current git repository is hosted on GitHub by
704+
examining the remote URL.
705+
706+
Returns:
707+
bool: True if the repository is hosted on GitHub, False otherwise.
708+
"""
709+
try:
710+
# 使用git命令获取当前仓库的URL
711+
result = subprocess_check_output(
712+
["git", "remote", "get-url", "origin"], stderr=subprocess.STDOUT
713+
).strip()
714+
715+
# 将结果从bytes转换为str
716+
repo_url = result.decode("utf-8")
717+
718+
# 检查URL是否包含github.com
719+
is_github = "github.com" in repo_url.lower()
720+
721+
IDEService().ide_logging("debug", f"Repository is GitHub: {is_github}")
722+
return is_github
723+
except subprocess.CalledProcessError as e:
724+
print(e, flush=True)
725+
# 如果发生错误,打印错误信息
726+
return None
727+
except FileNotFoundError:
728+
# 如果未找到git命令,可能是没有安装git或者不在PATH中
729+
print("==> File not found...", flush=True)
730+
return None

community/work_report/command.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,28 @@
33

44
from devchat.llm import chat, chat_json
55

6-
from community.gitlab.git_api import (
7-
get_commit_author,
8-
get_repo,
9-
get_repo_commits,
10-
get_repo_issues,
11-
get_username,
12-
)
6+
from community.github.git_api import is_github_repo
7+
8+
if is_github_repo():
9+
from community.github.git_api import (
10+
get_commit_author,
11+
get_repo_commits,
12+
get_repo_issues,
13+
)
14+
from community.github.git_api import (
15+
get_github_repo as get_repo,
16+
)
17+
from community.github.git_api import (
18+
get_github_username as get_username,
19+
)
20+
else:
21+
from community.gitlab.git_api import (
22+
get_commit_author,
23+
get_repo,
24+
get_repo_commits,
25+
get_repo_issues,
26+
get_username,
27+
)
1328
from lib.workflow.decorators import check_input
1429

1530

0 commit comments

Comments
 (0)