feat: App_Store 打包也发钉钉通知,Ad_Hoc/App_Store 各自的 @ 名单
- App_Store 完成后同样发送钉钉通知:标题改为「【iOS】App_Store 包信息」, 下载链接为 IPA 地址,不带二维码。 - 钉钉 markdown 消息需在正文出现 @手机号 才会真正 @ 到人,故除 at.atMobiles 外同时在正文追加。 - 新增 upload.dingtalk.at_mobiles(Ad_Hoc)与 at_mobiles_app_store(App_Store) 两份名单,按 BUILD_TYPE 选用;配置页「钉钉通知」区新增两个输入框。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YZULZ8fkiaiJrxqf318xTn
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
fa559101b9
commit
9ace2c8aca
@@ -498,22 +498,22 @@ async def run_build_task(task_id: str):
|
||||
if task.oss_url:
|
||||
await log_streamer.emit(task_id, f"下载链接: {task.oss_url}")
|
||||
|
||||
# App Store 仅提供 IPA 下载地址,不发送下载通知;Ad Hoc 才发送安装页二维码通知。
|
||||
if task.build_type == "Ad_Hoc":
|
||||
# 通知不影响已完成的打包结果,发送失败仅写入日志以便排查。
|
||||
dingtalk_config = config_data.get("_upload_config", {}).get("dingtalk", {})
|
||||
try:
|
||||
notified = await asyncio.to_thread(
|
||||
send_dingtalk_notification,
|
||||
dingtalk_config,
|
||||
config_data,
|
||||
task.oss_url or oss_url,
|
||||
task.qr_code_path or qr_code_path,
|
||||
)
|
||||
if notified:
|
||||
await log_streamer.emit(task_id, "钉钉通知发送成功")
|
||||
except NotificationError as exc:
|
||||
await log_streamer.emit(task_id, f"钉钉通知未发送: {exc}", level="warn")
|
||||
# Ad Hoc 发安装页二维码通知,App Store 发 IPA 下载地址通知;
|
||||
# 两者标题与 @ 名单不同,均由 send_dingtalk_notification 按 BUILD_TYPE 区分。
|
||||
# 通知不影响已完成的打包结果,发送失败仅写入日志以便排查。
|
||||
dingtalk_config = config_data.get("_upload_config", {}).get("dingtalk", {})
|
||||
try:
|
||||
notified = await asyncio.to_thread(
|
||||
send_dingtalk_notification,
|
||||
dingtalk_config,
|
||||
config_data,
|
||||
task.oss_url or oss_url,
|
||||
task.qr_code_path or qr_code_path,
|
||||
)
|
||||
if notified:
|
||||
await log_streamer.emit(task_id, "钉钉通知发送成功")
|
||||
except NotificationError as exc:
|
||||
await log_streamer.emit(task_id, f"钉钉通知未发送: {exc}", level="warn")
|
||||
|
||||
# 带超时执行打包
|
||||
await asyncio.wait_for(_do_build(), timeout=timeout_seconds)
|
||||
|
||||
@@ -27,8 +27,32 @@ def _signed_webhook_url(webhook_url: str, secret: str) -> str:
|
||||
return f"{webhook_url}{separator}timestamp={timestamp}&sign={quote(base64.b64encode(signature))}"
|
||||
|
||||
|
||||
def build_dingtalk_payload(config_data: dict, download_url: str, qr_code_url: str = "") -> dict:
|
||||
def _normalize_mobiles(at_mobiles) -> list:
|
||||
"""把手机号配置统一成去重、去空的字符串列表,兼容列表或逗号/换行分隔的字符串。"""
|
||||
if not at_mobiles:
|
||||
return []
|
||||
if isinstance(at_mobiles, str):
|
||||
raw = at_mobiles.replace("\n", ",").replace(",", ",").replace(" ", ",").split(",")
|
||||
else:
|
||||
raw = at_mobiles
|
||||
seen = []
|
||||
for item in raw:
|
||||
mobile = str(item).strip()
|
||||
if mobile and mobile not in seen:
|
||||
seen.append(mobile)
|
||||
return seen
|
||||
|
||||
|
||||
def build_dingtalk_payload(
|
||||
config_data: dict,
|
||||
download_url: str,
|
||||
qr_code_url: str = "",
|
||||
at_mobiles=None,
|
||||
) -> dict:
|
||||
"""生成与 AutoPacking/upload_iap.py 一致的钉钉 Markdown 内容。"""
|
||||
mobiles = _normalize_mobiles(at_mobiles)
|
||||
# App_Store 包与 Ad Hoc 用不同标题,App_Store 只有 IPA 下载地址、无二维码。
|
||||
heading = "【iOS】App_Store 包信息" if config_data.get("BUILD_TYPE") == "App_Store" else "【iOS】打包信息"
|
||||
details = (
|
||||
f"**环境:** {config_data.get('SERVER', '')}\n\n"
|
||||
f"**版本:** {config_data.get('VERSION', '')}\n\n"
|
||||
@@ -36,14 +60,18 @@ def build_dingtalk_payload(config_data: dict, download_url: str, qr_code_url: st
|
||||
f"**包名:** {config_data.get('BUNDLE_ID', '')}\n\n"
|
||||
f"**App Guid:** {config_data.get('APPID', '')}"
|
||||
)
|
||||
text = f"## 【iOS】打包信息\n\n{details}\n\n**iOS 下载链接:** {download_url}\n"
|
||||
text = f"## {heading}\n\n{details}\n\n**iOS 下载链接:** {download_url}\n"
|
||||
if qr_code_url:
|
||||
text += f"\n"
|
||||
# 钉钉 markdown 消息必须在正文内出现 @手机号 才会真正 @ 到人,
|
||||
# 仅靠 at.atMobiles 不生效。
|
||||
if mobiles:
|
||||
text += "\n\n" + " ".join(f"@{m}" for m in mobiles)
|
||||
|
||||
return {
|
||||
"msgtype": "markdown",
|
||||
"markdown": {"title": "iOS应用下载", "text": text},
|
||||
"at": {"atMobiles": [], "isAtAll": False},
|
||||
"at": {"atMobiles": mobiles, "isAtAll": False},
|
||||
}
|
||||
|
||||
|
||||
@@ -61,8 +89,11 @@ def send_dingtalk_notification(
|
||||
if not webhook_url:
|
||||
raise NotificationError("钉钉通知已启用,但未配置 Webhook URL")
|
||||
|
||||
payload = build_dingtalk_payload(config_data, download_url, qr_code_url)
|
||||
payload["at"]["atMobiles"] = dingtalk_config.get("at_mobiles", [])
|
||||
# Ad_Hoc 与 App_Store 使用各自的 @ 名单。
|
||||
mobiles_key = "at_mobiles_app_store" if config_data.get("BUILD_TYPE") == "App_Store" else "at_mobiles"
|
||||
payload = build_dingtalk_payload(
|
||||
config_data, download_url, qr_code_url, dingtalk_config.get(mobiles_key, [])
|
||||
)
|
||||
response = httpx.post(
|
||||
_signed_webhook_url(webhook_url, dingtalk_config.get("secret", "")),
|
||||
json=payload,
|
||||
|
||||
Reference in New Issue
Block a user