Files
market/.github/workflows/i18n-validate.yml
mashagua 6cd60a7141 feat: 新增外部条目上游健康检查与每周巡检工作流 (#188)
## 背景
外部条目只存上游指针,上游仓库被删除、分支被重写或技能目录移动时,客户端安装会静默失败,目前没有任何机制能发现(例如
`dingtalk-cli` 的上游已 404,见修复 PR)。

## 变更
- **`scripts/catalog/check_upstream_health.py`**:只读,逐个检查
`skills/`、`agents/`、`teams/` 下的 `entry.json`:
- 失效(退出码 1):`gone` 上游不存在 · `bad-branch` 分支不存在 · `bad-ref` 固定提交无法获取 ·
`bad-path` `source.path`、根 `SKILL.md` 或 children 路径在分支最新提交下缺失
- 提示:`unreachable` 网络错误(不等于失效)· `new-skill` 集合有未声明子技能(发现规则直接复用
`gen-collection-children.py` 的 `discover_children`,两者结论一致)· `outdated`
固定 ref 落后于分支 · `unpinned` 未锁定 ref
  - 只稀疏检出 `SKILL.md`,39 个条目本地全量运行约 12 秒
- **`scripts/catalog/test_check_upstream_health.py`**:9 个基于本地 Git
仓库的单测,已加入 `i18n-validate.yml`。
- **`.github/workflows/upstream-health.yml`**:每周一 01:23 UTC 运行(可手动触发),仅在
`desirecore/market` 运行:
- 报告写入 Job Summary,并维护唯一一个带 `upstream-health` 标签的
Issue:有待处理项时创建或更新,全部正常时评论并关闭
  - 有失效条目时任务标红
- 权限仅 `contents: read` + `issues: write`,**不改写任何目录文件**;修复与 `source.ref`
更新仍通过评审 PR(与固定 ref 的审查语义一致)
- README 中英文补充用法。

## 当前主干的检查结果
- 失效 1:`dingtalk-cli`(已有修复 PR)
- 未声明子技能 3:`khazix-skills`、`marketingskills`、`mattpocock-skills`
- 可更新 21 个,未锁定 1 个
- `amap-jsapi-skill`、`luckin-my-coffee` 在本地因代理显示 `unreachable`,需要 CI
环境确认

## 验证
```
uv run scripts/catalog/test_check_upstream_health.py   # Ran 9 tests OK
uv run scripts/catalog/check_upstream_health.py        # 如上
uv run scripts/i18n/validate-i18n.py                   # 0 error(s)
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_0191D9g1FhRQzEGTefUn6mTb

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Yige <a@wyr.me>
2026-09-26 16:13:14 +08:00

91 lines
3.1 KiB
YAML

name: i18n Validate
on:
pull_request:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
jobs:
validate:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Detect relevant changes
id: changes
env:
EVENT_NAME: ${{ github.event_name }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
PUSH_BEFORE: ${{ github.event.before }}
PUSH_AFTER: ${{ github.event.after }}
run: |
set -e
case "$EVENT_NAME" in
pull_request)
git fetch --no-tags --depth=1 origin "$BASE_SHA" 2>/dev/null || true
range="${BASE_SHA}...${HEAD_SHA}"
;;
push)
if [ -n "$PUSH_BEFORE" ] && [ "$PUSH_BEFORE" != "0000000000000000000000000000000000000000" ]; then
range="${PUSH_BEFORE}...${PUSH_AFTER}"
else
# initial push or unknown before — assume relevant
echo "relevant=true" >> "$GITHUB_OUTPUT"
exit 0
fi
;;
*)
echo "relevant=true" >> "$GITHUB_OUTPUT"
exit 0
;;
esac
changed=$(git diff --name-only "$range" || true)
if echo "$changed" | grep -qE '^(skills/|agents/|teams/|schemas/|manifest\.json$|categories\.json$|scripts/i18n/|scripts/catalog/|scripts/gen-collection-children\.py$)'; then
echo "relevant=true" >> "$GITHUB_OUTPUT"
else
echo "relevant=false" >> "$GITHUB_OUTPUT"
fi
- name: Install uv
if: steps.changes.outputs.relevant == 'true'
uses: astral-sh/setup-uv@v3
- name: Run validator unit tests
if: steps.changes.outputs.relevant == 'true'
run: uv run --quiet scripts/i18n/test_validate_i18n.py
- name: Run catalog validator unit tests
if: steps.changes.outputs.relevant == 'true'
run: |
uv run --quiet scripts/catalog/test_validate_catalog_metadata.py
uv run --quiet scripts/catalog/test_collection_generator.py
uv run --quiet scripts/catalog/test_check_upstream_health.py
- name: Validate catalog metadata
if: steps.changes.outputs.relevant == 'true'
run: uv run --quiet scripts/catalog/validate_catalog_metadata.py --require-complete
- name: Validate i18n
if: steps.changes.outputs.relevant == 'true'
run: uv run --quiet scripts/i18n/validate-i18n.py
- name: Check for stale translations
if: steps.changes.outputs.relevant == 'true'
run: uv run --quiet scripts/i18n/translate.py --check
- name: Check generated collection children
if: steps.changes.outputs.relevant == 'true'
run: uv run --quiet scripts/gen-collection-children.py --check
- name: Skip notice
if: steps.changes.outputs.relevant != 'true'
run: echo "No i18n-relevant changes; validation skipped."