-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: jingfelix <jingfelix@outlook.com>
- Loading branch information
Showing
6 changed files
with
172 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,89 @@ | ||
import os | ||
|
||
from celery_app import celery | ||
from model.schema import db | ||
from utils.github.application import get_installation_token, get_jwt | ||
from utils.github.organization import get_org_members | ||
from model.schema import BindUser, ObjID, Repo, RepoUser, User, db | ||
from model.team import add_team_member | ||
from utils.github.organization import GitHubAppOrg | ||
from utils.user import create_github_user | ||
|
||
|
||
@celery.task() | ||
def pull_repo(org_name: str, installation_id: str, application_id: str): | ||
"""Pull repo from GitHub, build Repo and RepoUser.""" | ||
# 获取 jwt 和 installation_token | ||
def pull_repo(org_name: str, installation_id: str, application_id: str, team_id: str): | ||
"""Pull repo from GitHub, build Repo and RepoUser. | ||
installation_token: str = get_installation_token( | ||
get_jwt( | ||
os.environ.get("GITHUB_APP_PRIVATE_KEY_PATH"), | ||
os.environ.get("GITHUB_APP_ID"), | ||
), | ||
installation_id, | ||
) # TODO: 这里有一个遗留问题:installation_token 有一小时的期限 | ||
# 解决方案是在 utils.github.application 中增加一个类,用于统一管理 jwt 和 installation_token | ||
Args: | ||
org_name: GitHub organization name. | ||
installation_id: GitHub App installation id. | ||
application_id: Code application id. | ||
""" | ||
# 获取 jwt 和 installation_token | ||
|
||
if installation_token is None: | ||
raise Exception("Failed to get installation token.") # TODO: 统一处理 celery 报错? | ||
github_app = GitHubAppOrg(installation_id) | ||
|
||
# 拉取所有组织成员,创建 BindUser | ||
members = get_org_members(org_name, installation_token) | ||
# 拉取所有组织成员,创建 User 和 BindUser | ||
members = github_app.get_org_members(org_name) | ||
if members is None or not isinstance(members, list): | ||
raise Exception("Failed to get org members.") | ||
|
||
for member in members: | ||
# 检查是否已经存在(其实只有一个人会重复?) | ||
pass | ||
# 已存在的用户不会重复创建 | ||
_, new_bind_user_id = create_github_user( | ||
github_id=member["id"], | ||
name=member["login"], | ||
email=member.get("email", None), | ||
avatar=member["avatar_url"], | ||
access_token=None, | ||
application_id=application_id, | ||
extra={}, | ||
) | ||
|
||
add_team_member(team_id, new_bind_user_id) | ||
|
||
# 拉取所有组织仓库,创建 Repo | ||
# 给每个仓库创建 RepoUser | ||
repos = github_app.get_org_repos(org_name) | ||
try: | ||
for repo in repos: | ||
# 检查是否已经存在 | ||
if Repo.query.filter_by(repo_id=repo["id"]).first() is not None: | ||
continue | ||
|
||
new_repo = Repo( | ||
id=ObjID.new_id(), | ||
application_id=application_id, | ||
owner_bind_id=None, # TODO: 暂定不填写 | ||
repo_id=repo["id"], | ||
description=repo["description"], | ||
) | ||
db.session.add(new_repo) | ||
db.session.flush() | ||
|
||
# 拉取仓库成员,创建 RepoUser | ||
repo_users = github_app.get_repo_collaborators(repo["name"], org_name) | ||
print(repo_users) | ||
|
||
# 检查是否有 bind_user | ||
for repo_user in repo_users: | ||
bind_user = ( | ||
db.session.query(BindUser) | ||
.filter( | ||
User.unionid == repo_user["id"], | ||
BindUser.platform == "github", | ||
BindUser.application_id == application_id, | ||
BindUser.user_id == User.id, | ||
) | ||
.first() | ||
) | ||
if bind_user is None: | ||
continue | ||
|
||
new_repo_user = RepoUser( | ||
id=ObjID.new_id(), | ||
application_id=application_id, | ||
repo_id=new_repo.id, | ||
bind_user_id=bind_user.id, | ||
) | ||
db.session.add(new_repo_user) | ||
db.session.commit() | ||
|
||
pass | ||
db.session.commit() | ||
except Exception as e: | ||
db.session.rollback() | ||
raise e |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,55 @@ | ||
import httpx | ||
from app import app | ||
from utils.github.bot import BaseGitHubApp | ||
|
||
|
||
def get_org_members(org_name: str, installation_token: str) -> list | None: | ||
"""Get a list of members of an organization. | ||
class GitHubAppOrg(BaseGitHubApp): | ||
def __init__(self, installation_id: str): | ||
super().__init__(installation_id) | ||
|
||
Args: | ||
org_name (str): The name of the organization. | ||
installation_token (str): The installation token for the GitHub App. | ||
def get_org_repos(self, org_name: str) -> list | None: | ||
"""Get org repos. | ||
Returns: | ||
list | None: A list of members of the organization. | ||
https://docs.github.com/zh/rest/orgs/members?apiVersion=2022-11-28#list-organization-members | ||
""" | ||
with httpx.Client() as client: | ||
response = client.get( | ||
f"https://api.github.com/orgs/{org_name}/members", | ||
headers={ | ||
"Accept": "application/vnd.github+json", | ||
"Authorization": f"token {installation_token}", | ||
"X-GitHub-Api-Version": "2022-11-28", | ||
}, | ||
Args: | ||
org_name (str): The name of the org. | ||
Returns: | ||
list: The org repos. | ||
https://docs.github.com/zh/rest/repos/repos?apiVersion=2022-11-28#list-organization-repositories | ||
""" | ||
|
||
return self.base_github_rest_api( | ||
f"https://api.github.com/orgs/{org_name}/repos", | ||
auth_type="install_token", | ||
) | ||
|
||
if response.status_code == 200: | ||
return response.json() | ||
else: | ||
app.logger.debug(f"Failed to get org members. {response.text}") | ||
return None | ||
def get_repo_collaborators(self, repo_name: str, owner_name: str) -> list | None: | ||
"""Get repo collaborators. | ||
Args: | ||
repo_name (str): The name of the repo. | ||
owner_name (str): The name of the owner. | ||
Returns: | ||
list: The repo collaborators. | ||
https://docs.github.com/zh/rest/collaborators/collaborators?apiVersion=2022-11-28#list-repository-collaborators | ||
""" | ||
|
||
return self.base_github_rest_api( | ||
f"https://api.github.com/repos/{owner_name}/{repo_name}/collaborators", | ||
auth_type="install_token", | ||
) | ||
|
||
def get_org_members(self, org_name: str) -> list | None: | ||
"""Get a list of members of an organization. | ||
Args: | ||
org_name (str): The name of the organization. | ||
Returns: | ||
list | None: A list of members of the organization. | ||
https://docs.github.com/zh/rest/orgs/members?apiVersion=2022-11-28#list-organization-members | ||
""" | ||
|
||
return self.base_github_rest_api( | ||
f"https://api.github.com/orgs/{org_name}/members", | ||
auth_type="install_token", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters