Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 9 additions & 23 deletions .github/workflows/org-router.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,21 @@ jobs:
permissions:
contents: read
discussions: write
actions: write
steps:
# ── 基础环境 ──────────────────────────────────────────────────────

- uses: actions/checkout@v4
with:
token: ${{ secrets.CSM_QA_GH_TOKEN }}

- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: '3.11'

- name: Restore venv cache
id: cache-venv
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: .venv
key: ${{ runner.os }}-venv-py3.11-${{ hashFiles('requirements-bot.txt') }}
Expand All @@ -90,7 +91,7 @@ jobs:

- name: Save venv cache
if: always() && steps.install-deps.outcome == 'success' && steps.cache-venv.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
uses: actions/cache/save@v5
with:
path: .venv
key: ${{ steps.cache-venv.outputs.cache-primary-key }}
Expand All @@ -115,12 +116,7 @@ jobs:
run: |
INTENT=$(python scripts/router.py \
--classify-only \
--discussion-number "${ROUTER_DISCUSSION_NUMBER}" \
--comment-body "${ROUTER_COMMENT_BODY}" \
--discussion-title "${ROUTER_DISCUSSION_TITLE}" \
--category-name "${ROUTER_CATEGORY_NAME}" \
--event-type "${ROUTER_EVENT_TYPE}" \
--comment-author "${ROUTER_COMMENT_AUTHOR}")
--discussion-number "${ROUTER_DISCUSSION_NUMBER}")
echo "result=${INTENT}" >> "$GITHUB_OUTPUT"
echo "Intent: ${INTENT}"

Expand All @@ -147,9 +143,6 @@ jobs:
python scripts/router.py \
--intent JOIN \
--discussion-number "${ROUTER_DISCUSSION_NUMBER}" \
--comment-body "${ROUTER_COMMENT_BODY}" \
--comment-author "${ROUTER_COMMENT_AUTHOR}" \
--event-type "${ROUTER_EVENT_TYPE}" \
${{ github.event.inputs.dry_run == 'true' && '--dry-run' || '' }}

# ════════════════════════════════════════════════════════════════════
Expand All @@ -161,7 +154,7 @@ jobs:
- name: Restore HuggingFace models cache
id: cache-hf
if: steps.classify.outputs.result == 'QA'
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: ~/.cache/huggingface
key: ${{ runner.os }}-hf-BAAI-bge-small-zh-v1.5
Expand Down Expand Up @@ -194,7 +187,7 @@ jobs:
- name: Restore vector store cache
id: cache-vs
if: steps.classify.outputs.result == 'QA'
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: |
.csm_llm_qa/vector_store
Expand All @@ -221,10 +214,6 @@ jobs:
python scripts/router.py \
--intent QA \
--discussion-number "${ROUTER_DISCUSSION_NUMBER}" \
--comment-body "${ROUTER_COMMENT_BODY}" \
--category-name "${ROUTER_CATEGORY_NAME}" \
--event-type "${ROUTER_EVENT_TYPE}" \
--comment-author "${ROUTER_COMMENT_AUTHOR}" \
${{ github.event.inputs.dry_run == 'true' && '--dry-run' || '' }}

# QA 之后才保存 RAG 缓存
Expand All @@ -242,7 +231,7 @@ jobs:

- name: Save HuggingFace models cache
if: always() && steps.classify.outputs.result == 'QA' && steps.cache-hf.outputs.cache-hit != 'true' && steps.check-hf-populated.outputs.populated == 'true'
uses: actions/cache/save@v4
uses: actions/cache/save@v5
with:
path: ~/.cache/huggingface
key: ${{ steps.cache-hf.outputs.cache-primary-key }}
Expand Down Expand Up @@ -274,7 +263,7 @@ jobs:

- name: Save vector store cache
if: always() && steps.classify.outputs.result == 'QA' && steps.cache-vs.outputs.cache-hit != 'true' && steps.check-vs-populated.outputs.populated == 'true'
uses: actions/cache/save@v4
uses: actions/cache/save@v5
with:
path: |
.csm_llm_qa/vector_store
Expand All @@ -300,7 +289,4 @@ jobs:
python scripts/router.py \
--intent OTHER \
--discussion-number "${ROUTER_DISCUSSION_NUMBER}" \
--comment-body "${ROUTER_COMMENT_BODY}" \
--event-type "${ROUTER_EVENT_TYPE}" \
--comment-author "${ROUTER_COMMENT_AUTHOR}" \
${{ github.event.inputs.dry_run == 'true' && '--dry-run' || '' }}
33 changes: 21 additions & 12 deletions scripts/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -1265,26 +1265,26 @@ def parse_args(argv: Optional[list[str]] = None) -> argparse.Namespace:
parser.add_argument(
"--comment-body",
type=str,
default="",
help="评论正文(Webhook 传入,最大 800 字符)",
default=os.environ.get("ROUTER_COMMENT_BODY", ""),
help="评论正文(Webhook 传入,最大 800 字符;缺省时从 ROUTER_COMMENT_BODY 环境变量读取)",
)
parser.add_argument(
"--discussion-title",
type=str,
default="",
help="Discussion 标题(discussion 事件时用于拼接分类输入)",
default=os.environ.get("ROUTER_DISCUSSION_TITLE", ""),
help="Discussion 标题(discussion 事件时用于拼接分类输入;缺省时从 ROUTER_DISCUSSION_TITLE 环境变量读取)",
)
parser.add_argument(
"--comment-author",
type=str,
default="",
help="评论作者用户名",
default=os.environ.get("ROUTER_COMMENT_AUTHOR", ""),
help="评论作者用户名(缺省时从 ROUTER_COMMENT_AUTHOR 环境变量读取)",
)
parser.add_argument(
"--category-name",
type=str,
default="",
help="Discussion 所属分类名",
default=os.environ.get("ROUTER_CATEGORY_NAME", ""),
help="Discussion 所属分类名(缺省时从 ROUTER_CATEGORY_NAME 环境变量读取)",
)
parser.add_argument(
"--dry-run",
Expand All @@ -1295,8 +1295,8 @@ def parse_args(argv: Optional[list[str]] = None) -> argparse.Namespace:
parser.add_argument(
"--event-type",
type=str,
default="",
help="GitHub 事件类型(discussion / discussion_comment)",
default=os.environ.get("ROUTER_EVENT_TYPE", ""),
help="GitHub 事件类型(discussion / discussion_comment;缺省时从 ROUTER_EVENT_TYPE 环境变量读取)",
)
parser.add_argument(
"--classify-only",
Expand Down Expand Up @@ -1395,7 +1395,11 @@ def main(argv: Optional[list[str]] = None) -> int:

# 3. --classify-only:仅输出意图供 workflow 捕获(token 仅用于获取讨论上下文,非必需)
if args.classify_only:
print(intent)
try:
print(intent)
except Exception:
logger.exception("classify-only 模式输出异常")
print("OTHER")
return 0

# ── 后续操作需要 token ────────────────────────────────────────────
Expand Down Expand Up @@ -1428,4 +1432,9 @@ def main(argv: Optional[list[str]] = None) -> int:


if __name__ == "__main__":
sys.exit(main())
try:
sys.exit(main())
except Exception:
logger.exception("Router 执行异常,输出 fallback 结果")
print("OTHER")
sys.exit(0)
5 changes: 5 additions & 0 deletions tests/test_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from __future__ import annotations

import logging

import pytest
from unittest.mock import patch, MagicMock

Expand Down Expand Up @@ -948,6 +950,7 @@ def _argv_other(**overrides) -> list[str]:

def test_other_skipped_when_human_intervention(self, monkeypatch, caplog):
"""OTHER 路径下,thread 已有人工介入 → 跳过回复。"""
caplog.set_level(logging.INFO, logger="org_router")
monkeypatch.setattr("scripts.router.LLM_API_KEY", "")
monkeypatch.setenv("CSM_QA_GH_TOKEN", "fake-token")
monkeypatch.setattr(
Expand Down Expand Up @@ -976,6 +979,7 @@ def mock_post(*args, **kwargs):

def test_qa_guide_skipped_when_human_intervention(self, monkeypatch, caplog):
"""_handle_qa 非 Q&A 引导路径下,thread 已有人工介入 → 跳过回复。"""
caplog.set_level(logging.INFO, logger="org_router")
monkeypatch.setattr("scripts.router.LLM_API_KEY", "")
monkeypatch.setenv("CSM_QA_GH_TOKEN", "fake-token")
monkeypatch.setattr(
Expand Down Expand Up @@ -1041,6 +1045,7 @@ def mock_post(*args, **kwargs):

def test_join_skipped_when_human_intervention(self, monkeypatch, caplog):
"""JOIN 路径下,thread 已有人工介入 → 跳过处理。"""
caplog.set_level(logging.INFO, logger="org_router")
monkeypatch.setattr("scripts.router.LLM_API_KEY", "")
monkeypatch.setenv("CSM_QA_GH_TOKEN", "fake-token")
monkeypatch.setattr(
Expand Down
Loading