Repository navigation
202 lines (181 loc) · 9.06 KB
/
Copy pathupdate-plugin-versions.yml
File metadata and controls
202 lines (181 loc) · 9.06 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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# ============================================================
# 每日插件版本检查:拉取所有已录入插件的 PyPI 最新版本,
# 存在新版本时复用与 plugin-submission.yml 相同的验证逻辑重新验证,
# 验证通过后更新 assess 元数据并推送。
# ============================================================
name: update-plugin-versions
on:
schedule:
# 每天 UTC 02:00(北京时间 10:00)
- cron: "0 2 * * *"
workflow_dispatch:
permissions:
contents: write
jobs:
update:
name: 检查并更新插件版本
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: 检出仓库代码
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: 安装依赖
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq jq >/dev/null 2>&1
python3 -m pip install --upgrade pip >/dev/null 2>&1
- name: 检查 PyPI 新版本
id: check
run: |
python3 .github/scripts/check_pypi_updates.py > updates.json
echo "count=$(jq 'length' updates.json)" >> "$GITHUB_OUTPUT"
echo "fail_count=$(jq 'length' failures.json)" >> "$GITHUB_OUTPUT"
jq -r '.[] | "\(.pypi): \(.current_version) -> \(.latest_version)"' updates.json || true
- name: 重新验证并更新版本
id: update
if: steps.check.outputs.count != '0'
run: |
set +e
UPDATED=0
echo '[]' > updated.json
echo '[]' > failed.json
for entry in $(jq -c '.[]' updates.json); do
PYPI=$(echo "$entry" | jq -r '.pypi')
REPO=$(echo "$entry" | jq -r '.repo')
CUR=$(echo "$entry" | jq -r '.current_version')
LATEST=$(echo "$entry" | jq -r '.latest_version')
echo "===== 处理 ${PYPI}: ${CUR} -> ${LATEST} ====="
if [ -z "$REPO" ]; then
echo "[skip] ${PYPI}: 缺少仓库地址"
jq --arg p "$PYPI" --arg c "$CUR" --arg l "$LATEST" --arg r "缺少仓库地址" \
'. += [{pypi:$p, current:$c, latest:$l, reason:$r}]' failed.json > tmp_failed.json && mv tmp_failed.json failed.json
continue
fi
# 克隆插件仓库(与提交流程一致)
git clone --depth 1 "${REPO}.git" plugin_repo 2>&1 | tail -3
if [ ! -d plugin_repo ]; then
echo "[skip] ${PYPI}: 克隆仓库失败"
jq --arg p "$PYPI" --arg c "$CUR" --arg l "$LATEST" --arg r "克隆仓库失败" \
'. += [{pypi:$p, current:$c, latest:$l, reason:$r}]' failed.json > tmp_failed.json && mv tmp_failed.json failed.json
continue
fi
# 定位插件源码目录
PYPI_UNDER=$(echo "$PYPI" | tr '-' '_')
PLUGIN_DIR=$(find plugin_repo -type d -regex ".*/src/${PYPI_UNDER}\$" | head -n1 || true)
if [ -z "$PLUGIN_DIR" ]; then
PLUGIN_DIR=$(find plugin_repo -type d -regex '.*/src/axtbot_plugin_[^/]+$' | head -n1 || true)
fi
if [ -z "$PLUGIN_DIR" ] || [ ! -f "$PLUGIN_DIR/__init__.py" ]; then
echo "[skip] ${PYPI}: 找不到 src/.../__init__.py"
jq --arg p "$PYPI" --arg c "$CUR" --arg l "$LATEST" --arg r "找不到插件源码目录" \
'. += [{pypi:$p, current:$c, latest:$l, reason:$r}]' failed.json > tmp_failed.json && mv tmp_failed.json failed.json
rm -rf plugin_repo
continue
fi
# 解析最新 __meta__
python3 .github/scripts/parse_meta.py "$PLUGIN_DIR/__init__.py" 2>&1 | tail -3
if [ ! -f meta.json ]; then
echo "[skip] ${PYPI}: __meta__ 解析失败"
jq --arg p "$PYPI" --arg c "$CUR" --arg l "$LATEST" --arg r "__meta__ 解析失败" \
'. += [{pypi:$p, current:$c, latest:$l, reason:$r}]' failed.json > tmp_failed.json && mv tmp_failed.json failed.json
rm -rf plugin_repo
continue
fi
# pip 安装最新版
python3 -m pip install --quiet "$PYPI" 2>&1 | tail -3
# 克隆 AxTBot 主仓库并验证加载
rm -rf axtbot
git clone --depth 1 https://github.com/AxT-Team/AxTBot.git axtbot 2>&1 | tail -3
REL_DIR="${PLUGIN_DIR#plugin_repo/}"
mkdir -p "axtbot/$(dirname "$REL_DIR")"
cp -r "$PLUGIN_DIR" "axtbot/$REL_DIR"
cd axtbot
python3 -m pip install --quiet -e . 2>&1 | tail -3
PKG="${PLUGIN_DIR##*/}" python3 ../.github/scripts/verify_plugin.py 2>&1 | tail -3
cd ..
VERIFY_OK="false"
if [ -f axtbot/verify.json ]; then
VERIFY_OK=$(jq -r '.ok' axtbot/verify.json)
fi
if [ "$VERIFY_OK" != "true" ]; then
echo "[skip] ${PYPI}: 验证失败,跳过更新"
# 摘取验证错误日志末尾,供 Webhook 通知展示
VERR=""
if [ -f axtbot/verify.json ]; then
VERR=$(jq -r '.error // ""' axtbot/verify.json | python3 -c "import sys;print(sys.stdin.read()[-800:].strip())")
fi
jq --arg p "$PYPI" --arg c "$CUR" --arg l "$LATEST" --arg r "加载验证失败" --arg e "$VERR" \
'. += [{pypi:$p, current:$c, latest:$l, reason:$r, error:$e}]' failed.json > tmp_failed.json && mv tmp_failed.json failed.json
rm -rf plugin_repo axtbot meta.json form.json
continue
fi
# 构造表单并合成新元数据
PYPI_NAME="$PYPI" python3 .github/scripts/build_form_for_update.py
python3 .github/scripts/build_metadata.py
if [ ! -f axtbot-plugin-tmp.json ]; then
echo "[skip] ${PYPI}: 合成元数据失败"
jq --arg p "$PYPI" --arg c "$CUR" --arg l "$LATEST" --arg r "合成元数据失败" \
'. += [{pypi:$p, current:$c, latest:$l, reason:$r}]' failed.json > tmp_failed.json && mv tmp_failed.json failed.json
rm -rf plugin_repo axtbot meta.json form.json
continue
fi
# 版本号以 PyPI 最新版为准
jq --arg v "$LATEST" '.version = $v' axtbot-plugin-tmp.json > tmp.json \
&& mv tmp.json axtbot-plugin-tmp.json
cp axtbot-plugin-tmp.json "assess/${PYPI}.json"
PYPI_NAME="$PYPI" python3 .github/scripts/update_index.py >/dev/null 2>&1 || true
echo "[ok] ${PYPI} 已更新到 ${LATEST}"
jq --arg p "$PYPI" --arg v "$LATEST" \
'. += [{pypi:$p, version:$v}]' updated.json > tmp_updated.json && mv tmp_updated.json updated.json
UPDATED=1
rm -rf plugin_repo axtbot meta.json form.json axtbot-plugin-tmp.json
done
echo "updated=$UPDATED" >> "$GITHUB_OUTPUT"
- name: 提交并推送版本更新
if: steps.update.outputs.updated == '1'
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add assess/
git diff --cached --quiet || git commit -m "chore(assess): 自动更新插件版本"
git push
- name: 推送版本检查结果到 Webhook
if: always()
env:
NOTIFY_WEBHOOK_URL: ${{ secrets.AUTO_REVIEW_WEBHOOK_URL }}
NOTIFY_WEBHOOK_TOKEN: ${{ secrets.AUTO_REVIEW_WEBHOOK_TOKEN }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
set +e
# 汇总 updated / failed 数组(update step 未执行时为默认空数组)
UPDATED_JSON='[]'
FAILED_JSON='[]'
if [ -f updated.json ]; then
UPDATED_JSON=$(cat updated.json)
fi
if [ -f failed.json ]; then
FAILED_JSON=$(cat failed.json)
fi
# 把 PyPI 查询失败的插件也并入 failed 数组
if [ -f failures.json ]; then
PYPI_QUERY_FAILED=$(jq -c '[.[] | {pypi, current: .current_version, latest: "?", reason: "PyPI 查询失败"}]' failures.json)
FAILED_JSON=$(jq -nc --argjson a "$FAILED_JSON" --argjson b "$PYPI_QUERY_FAILED" '$a + $b')
fi
# 无任何更新与失败时不推送,避免每日空消息
UP_COUNT=$(jq 'length' <<<"$UPDATED_JSON")
FD_COUNT=$(jq 'length' <<<"$FAILED_JSON")
echo "updated=${UP_COUNT} failed=${FD_COUNT}"
if [ "$UP_COUNT" = "0" ] && [ "$FD_COUNT" = "0" ]; then
echo "插件无更新且无失败,跳过 Webhook 推送"
exit 0
fi
NOTIFY_JSON=$(jq -nc \
--arg ev "plugin_version_check" \
--arg src "plugin-store" \
--arg run "$RUN_URL" \
--argjson up "$UPDATED_JSON" \
--argjson fd "$FAILED_JSON" \
'{event:$ev, source:$src, updated:$up, failed:$fd, run:($run|if length>0 then . else null end)}')
NOTIFY_JSON="$NOTIFY_JSON" python3 .github/scripts/notify_webhook.py