forked from Ikalus1988/MisakaNet
-
Notifications
You must be signed in to change notification settings - Fork 0
128 lines (107 loc) · 4.39 KB
/
Copy pathlesson-quality.yml
File metadata and controls
128 lines (107 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# Lesson 质量门禁 — 在 PR 修改 lessons/ 时自动检查
# 检查项:
# 1. 文件名: 无中文, 无项目特定前缀, kebab-case
# 2. frontmatter: JSON 合法, 必填字段完整
# 3. 内容: 无硬编码路径/用户名, 建议英文正文
#
# 不满足则添加 quality:needs-review 标签并留下评论
name: Lesson Quality Gate
on:
pull_request:
paths:
- 'lessons/**'
- 'reference/**'
workflow_dispatch:
permissions:
contents: read
pull-requests: write
checks: write
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Run quality check
id: check
continue-on-error: true
run: |
: > quality_report.txt
if [ "${{ github.event_name }}" = "pull_request" ]; then
git fetch --no-tags --depth=1 origin "${{ github.base_ref }}"
mapfile -t TARGETS < <(git diff --name-only "origin/${{ github.base_ref }}" HEAD -- 'lessons/**/*.md' 'lessons/*.md' 'reference/**/*.md' 'reference/*.md')
else
mapfile -t TARGETS < <(find lessons reference -name '*.md' 2>/dev/null | sort)
fi
if [ "${#TARGETS[@]}" -eq 0 ]; then
echo "No changed lesson/reference markdown files." | tee -a quality_report.txt
else
for target in "${TARGETS[@]}"; do
[ -f "$target" ] || continue
python3 scripts/check_lesson_quality.py "$target" >> quality_report.txt 2>&1 || true
done
fi
cat quality_report.txt
ERRORS=$(awk '/总计:/ {sum += $2} END {print sum+0}' quality_report.txt)
WARNINGS=$(awk '/总计:/ {sum += $4} END {print sum+0}' quality_report.txt)
SUMMARY="总计: ${ERRORS} 错误, ${WARNINGS} 警告"
echo "summary=$SUMMARY" >> "$GITHUB_OUTPUT"
if [ "$ERRORS" -gt 0 ]; then
echo "verdict=fail" >> "$GITHUB_OUTPUT"
else
echo "verdict=pass" >> "$GITHUB_OUTPUT"
fi
- name: Quality Score v0
id: qscore
continue-on-error: true
run: |
python3 scripts/score_lessons.py --threshold 0.6 2>&1 | tee qscore_report.txt
echo "qscore_summary=$(grep 'Below threshold' qscore_report.txt || echo '0 below threshold')" >> "$GITHUB_OUTPUT"
if grep -q "Below threshold: [1-9]" qscore_report.txt; then
echo "qscore_verdict=warn" >> "$GITHUB_OUTPUT"
else
echo "qscore_verdict=ok" >> "$GITHUB_OUTPUT"
fi
- name: Post quality report on PR
if: always() && github.event_name == 'pull_request'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERDICT="${{ steps.check.outputs.verdict }}"
SUMMARY="${{ steps.check.outputs.summary }}"
QS_VERDICT="${{ steps.qscore.outputs.qscore_verdict }}"
QS_SUMMARY="${{ steps.qscore.outputs.qscore_summary }}"
PR_NUM="${{ github.event.pull_request.number }}"
REPORT_BODY=$(cat quality_report.txt)
QS_SECTION=""
if [ "$QS_VERDICT" = "warn" ]; then
QS_SECTION="
### ⚠️ Quality Score v0
Some lessons scored below the 0.6 threshold. See details in the CI log.
"
fi
if [ "$VERDICT" = "pass" ]; then
gh pr comment "$PR_NUM" --repo "${{ github.repository }}" \
--body "### ✅ Lesson Quality Gate Passed
${SUMMARY}${QS_SECTION}
All lessons meet the naming, frontmatter, and content standards." || \
echo "Could not post lesson quality pass comment to PR #$PR_NUM"
else
gh pr comment "$PR_NUM" --repo "${{ github.repository }}" \
--body "### ❌ Lesson Quality Gate Failed
${SUMMARY}${QS_SECTION}
<details>
<summary>Details</summary>
\`\`\`
${REPORT_BODY}
\`\`\`
</details>
Fix the errors above and push again." || \
echo "Could not post lesson quality failure comment to PR #$PR_NUM"
gh pr edit "$PR_NUM" --repo "${{ github.repository }}" --add-label "quality:needs-review" || \
echo "Could not add quality:needs-review label to PR #$PR_NUM"
fi