Files
rdgen/rdgenerator/build_backends/github.py
T

111 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""GitHub Actions 构建后端(迁自 views.py / web_views.py 的原有逻辑,行为保持一致)。"""
from .. import app_settings, ghnet
from .base import BackendError, DispatchResult, RunInfo, WORKFLOW_FILES, BuildBackend
API = 'https://api.github.com'
# 未进入 completed 的状态一律视为进行中
_GITHUB_ACTIVE = {'queued', 'in_progress', 'waiting', 'requested', 'pending'}
class GitHubBackend(BuildBackend):
name = 'github'
label = 'GitHub'
# ---- 配置 ----
def configured(self):
return bool(app_settings.get_value('GHUSER').strip()) \
and bool(app_settings.get_value('GHBEARER').strip())
def warnings(self):
warnings = []
if not app_settings.get_value('GHUSER').strip():
warnings.append('GitHub 用户名未配置,无法触发构建。')
if not app_settings.get_value('GHBEARER').strip():
warnings.append('GitHub 访问令牌未配置,无法触发构建。')
warnings.extend(self._shared_warnings(include_sh_secret=True))
return warnings
# ---- 工作流选择(windows selfhosted 走 sh-generator-windows.yml) ----
def workflow_file_for(self, platform, selfhosted=False):
if selfhosted and platform in ('windows',):
return 'sh-generator-windows.yml'
return WORKFLOW_FILES.get(platform, 'generator-windows.yml')
# ---- 触发 ----
def dispatch(self, workflow_file, inputs, *, timeout=20):
user = app_settings.get_value('GHUSER')
repo = app_settings.get_value('REPONAME')
url = f'{API}/repos/{user}/{repo}/actions/workflows/{workflow_file}/dispatches'
payload = {
'ref': app_settings.get_value('GHBRANCH'),
'inputs': inputs,
'return_run_details': True,
}
token = app_settings.get_value('GHBEARER')
try:
resp = ghnet.post(url, json=payload, token=token, timeout=timeout)
except Exception as e:
raise BackendError(f'无法连接 GitHub 构建服务:{e}', kind='network')
if resp.status_code not in (200, 204):
raise BackendError('GitHub 构建服务拒绝了启动请求,请检查服务配置或稍后重试。', kind='rejected')
data = {}
try:
data = resp.json()
except ValueError:
pass
return DispatchResult(run_id=data.get('workflow_run_id'), html_url=data.get('html_url') or '')
# ---- 状态查询 ----
def get_run(self, run_id, *, timeout=12):
user = app_settings.get_value('GHUSER')
repo = app_settings.get_value('REPONAME')
url = f'{API}/repos/{user}/{repo}/actions/runs/{run_id}'
try:
resp = ghnet.get(url, token=app_settings.get_value('GHBEARER'), timeout=timeout)
except Exception as e:
print(f'查询 GitHub 状态出错:{e}')
return None
if resp.status_code != 200:
return None
data = resp.json()
if data.get('status') == 'completed':
return RunInfo(finished=True, status=data.get('conclusion') or 'failure',
html_url=data.get('html_url') or self.log_url(run_id))
return RunInfo(finished=False, status=data.get('status') or 'in_progress',
html_url=data.get('html_url') or self.log_url(run_id))
# ---- 日志链接 ----
def log_url(self, run_id):
if not run_id:
return ''
return (
f"https://github.com/{app_settings.get_value('GHUSER')}"
f"/{app_settings.get_value('REPONAME')}/actions/runs/{run_id}"
)
# ---- 连接测试 ----
def test_connection(self):
user = app_settings.get_value('GHUSER').strip()
repo = app_settings.get_value('REPONAME').strip()
token = app_settings.get_value('GHBEARER').strip()
if not user or not token:
return {'ok': False, 'message': 'GitHub 用户名或访问令牌为空,请先保存配置。'}
try:
resp = ghnet.get(f'{API}/repos/{user}/{repo}', token=token, timeout=10)
if resp.status_code == 401:
return {'ok': False, 'message': '令牌无效或已过期(GitHub 返回 401)。'}
if resp.status_code == 404:
return {'ok': False,
'message': f'找不到仓库 {user}/{repo},或令牌无权访问该仓库(请确认仓库名与令牌的 Repository access)。'}
if resp.status_code != 200:
return {'ok': False, 'message': f'GitHub 返回异常状态码:{resp.status_code}。'}
act = ghnet.get(f'{API}/repos/{user}/{repo}/actions/workflows', token=token, timeout=10)
if act.status_code == 200:
return {'ok': True, 'message': f'连接正常:令牌可访问仓库 {user}/{repo},且具备 Actions 权限。'}
return {'ok': False,
'message': '可以访问仓库,但令牌缺少 Actions 权限;请编辑令牌,授予 Actions 与 Workflows 的读写权限。'}
except Exception as e:
return {'ok': False,
'message': f'无法连接 GitHub API:{e}(如服务器在国内网络,请在下方配置代理后重试)'}