Skip to content

Commit f20ab0f

Browse files
authored
ci: complete daily bot update PRs and automatic validation (#546)
* ci: run daily bot update PRs and dispatch candidate validation * fix: respect manual package PRs and pin reviewed bot updater * ci: grant read access for dispatched PR identity checks
1 parent 192c865 commit f20ab0f

18 files changed

Lines changed: 719 additions & 180 deletions

‎.agents/docs/2026-10-19-xpkgindex-update-design.md‎

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# xpkgindex-update:两个索引共用的声明式版本更新工具
22

33
日期:2026-10-19
4-
状态:实现联调中。工具开发 PR:openxlings/xpkgindex-update#1;mcpp 为首个 draft CI 接入仓库。
4+
状态:工具和索引接入已合并;2026-10-20 补齐每日 bot PR 与自动 CI,验收以第 16 节为准。
55

66
## 1. 目标与结论
77

@@ -546,3 +546,80 @@ package = {
546546
先等待索引候选与现有消费者 CI 全部成功,再 squash 合并 #543。将 #544 同步到 main 基线,以工具重新生成共享格式并验证后合入。随后手动触发 main 上的 Action,使用可选 package 输入限定一个真实更新包;从 artifact 取回同一份固定计划,由已合并的 CLI 创建针对 main 的更新 PR,等待实际构建、运行、锁文件及旧版本保留检查成功后 squash 合入。
547547

548548
写 PR 使用本地已有授权,不新建长期 token secret。现有 libmysqlclient 源故障豁免继续明确保留,不改变其历史版本。此节是实施时的计划及已核实证据,最终合并与 CI 结果另见汇报和 PR 记录。
549+
550+
## 15. 共享资源与真实更新验收记录
551+
552+
本节为用户授权 squash 合并后的真实结果;不创建 docs-only 提交以重复触发整套 CI。
553+
554+
| PR | 合并提交 | 结果 |
555+
|---|---|---|
556+
| [openxlings/xpkgindex-update #1](https://github.com/openxlings/xpkgindex-update/pull/1) | `23c5e04948c55e606bc56ee2c649ddd4849b7ec6` | squash 合并;59 测试、六种 OS/Python 组合及 Action/打包检查成功;工具 main CI 成功 |
557+
| [mcpp-index #543](https://github.com/mcpplibs/mcpp-index/pull/543) | `1a514dbd1d71de29f0c8e6a9c854bab92b928df9` | squash 合并前 74 个执行 checks 成功,52/52 共享资源候选构建/运行/锁文件检查和 13 个消费者回归分片成功 |
558+
| [mcpp-index #544](https://github.com/mcpplibs/mcpp-index/pull/544) | `54cad76b3058a46ceec4c63b7bfa2122d5fdb194` | 以 main 为基线,20 个执行 checks 成功后 squash 合并;hiredis 1.5.0 单资源定义,三个平台引用;旧 1.2.0 不变 |
559+
| [mcpp-index #545](https://github.com/mcpplibs/mcpp-index/pull/545) | `192c8653516a3057e6103ffacd9bc0e6e613b921` | 真实 Action 计划生成的 yyjson 0.13.0 更新,20 个执行 checks 成功后 squash 合并;旧 0.12.0 不变 |
560+
561+
### 15.1 真正的 main 更新流程
562+
563+
1. 在 main 的 `54cad76` 手动触发 [Action 39308549012](https://github.com/mcpplibs/mcpp-index/actions/runs/39308549012),输入 `package=compat:yyjson`。
564+
2. Action 扫描确认 `0.12.0 -> 0.13.0`,资源完整下载并计算 SHA256;四种平台/工具链的实际构建/运行/锁文件检查全部成功。
565+
3. 原样取回 artifact `12215250910` 的固定计划,不重新构造计划;用合并提交 `23c5e04` 的 CLI 消费,自动创建 #545。使用已有本地授权,不配置新的长期 token secret。
566+
4. 再次执行同一计划的 propose 返回 `pending`,未创建重复 PR。
567+
5. #545 的实际 diff 为一个文件新增 10 行,无删除;URL/SHA 只定义一次,三个平台引用同一资源。全部 PR CI 成功后按已验证 head squash 合并。
568+
6. 合并后重新 check 返回 `compat:yyjson 0.13.0 up-to-date`;再 propose 返回 `{ "packages": [] }`。
569+
7. 独立 guard 继续确认原始基线 `981a4f2` 的 254 个描述符历史版本条目全部保留。
570+
571+
### 15.2 发布索引的普通客户端验证
572+
573+
- 最新 main 的 [发布](https://github.com/mcpplibs/mcpp-index/actions/runs/39309716725)、[站点部署](https://github.com/mcpplibs/mcpp-index/actions/runs/39309716804)、[消费者验证](https://github.com/mcpplibs/mcpp-index/actions/runs/39309716862) 均成功。
574+
- 固定客户端 `mcpp 2026.10.1.2` 刷新正式发布索引,报告 mcpplibs revision `192c865`。
575+
- 新建独立消费者仅依赖 `compat:yyjson = 0.13.0`,没有 `[indices]` 或本地索引覆盖。
576+
- 静态断言版本宏为 0.13.0;运行时 `yyjson_version()` 与版本宏一致;真实解析布尔 JSON 成功,输出 `PUBLISHED_YYJSON_0_13_0=PASS`。
577+
- 实际构建/运行结果为 1 passed、0 failed;锁文件确认为 `compat.yyjson`、`version = 0.13.0`、`source = index+compat@0.13.0`。
578+
579+
### 15.3 保留的边界
580+
581+
旧版本不做批量去重迁移,原镜像、哈希、注释和顺序保持原样。共享优化用于新追加的版本,后续追加复用同一个表。URL 不同的平台不因哈希相同而混用来源。工具不执行 Lua、不自动改安装配方、不自动 mirror、不自动 merge;本轮 squash 合并由用户明确授权。
582+
583+
原有两个条件性通知/计时发布任务按原规则跳过,不是构建测试跳过。wellwei/libmysqlclient 的源故障豁免继续明确显示 error 和 NOT TESTED,不计作成功构建;其余失败均未屏蔽。xim-pkgindex 的 latest.ref 变更仍未启用。README 为 34 行,详细使用文档独立。
584+
585+
较早的 integration main 提交 `1a514db` 的 [自动完整回归 39307639699](https://github.com/mcpplibs/mcpp-index/actions/runs/39307639699) 也已全部成功,19 个执行 jobs 全部通过,无剩余失败或待完成构建。至此,工具 main、索引接入 PR/main、hiredis PR/main、真实 yyjson 更新 PR/main 的构建、测试、发布及部署均完成。
586+
587+
## 16. 每日无人值守更新与贡献规范(2026-10-20)
588+
589+
### 16.1 补齐原验收缺口
590+
591+
#545 是 Action 扫描、候选 CI 后,由本地 CLI 使用 Sunrisepeak 的已有授权创建的 PR。
592+
它证明了更新内容及发布有效,但不证明定时触发、Action 内提 PR 或 bot PR 无人值守 CI。
593+
此前“完成”的判断范围错误;本节单独验收这三个环节。
594+
595+
### 16.2 正式流程
596+
597+
- 使用原设计的 `17 2 * * *`,每日 02:17 UTC / 11:17 JST;手动默认分支 dispatch 走同一流程。
598+
- 扫描只读;固定 artifact 计划交给独立 propose job,不依赖本地 CLI 或本地用户 token。
599+
- 使用内置 `GITHUB_TOKEN`,PR 作者为 `github-actions[bot]`,不新增长期 secret。
600+
- 组织此前阻止 Actions 创建 PR(API 409);用户已开启组织设置,仓库级也已开启。
601+
仓库默认权限仍为 read,仅 propose job 获得 contents/pull-requests/actions write。
602+
- 按中央 `max_prs: 3` 每轮最多三个新 PR;每包一个打开 PR,关闭候选不重开。
603+
已有人工作业 PR 修改同一描述符时也不重复创建(例如已有 httplib #542);人工 PR 继续走普通 PR CI。
604+
- propose 后显式 dispatch validate、候选、site、openkal 四个 workflow,避免依赖受限的普通 PR 事件。
605+
- validate/openkal 以 PR number、bot 身份、同仓 head/base、默认 base、head SHA 和单描述符 diff 校验请求,
606+
然后选择受影响成员;普通不带 update_pr 的手动 validate 仍保持完整回归。
607+
- 新版本在 PR CI 内验证,不要求全量候选全部成功才能先开 PR;失败升级保留红色结果,由维护者适配。
608+
- 已有 PR 可补发缺失 dispatch;已有运行不自动重跑,失败仍可见。默认分支移动后拒绝旧扫描计划,须重跑。
609+
- 写入仅默认分支 schedule/dispatch 可执行;普通 PR 和更新分支都不会提 PR,无递归,也不自动审批或合并。
610+
611+
### 16.3 agent 与文档约定
612+
613+
新增或维护符合条件的公共 GitHub release/数字 tag 包时,skill 要求主动添加并验证
614+
`extensions.autoupdate`。快照、独立源码版本、非 GitHub 来源和需要修改配方的升级须说明例外。
615+
新版本仍只追加,旧版本/mirror 不改;不要求未来新版本自动 mirror。
616+
617+
两份根 README 精简为用途、使用、贡献与链接;删除逐包 Additional example、重复示例表与 agent 长提示词。
618+
包形态和示例保留在专门文档;自动更新新增中英文独立文档并登记站点导航。
619+
skill 明确普通包 PR 不改根 README 或站点配置;用户明确要求的文档整理除外。
620+
621+
### 16.4 验收
622+
623+
工具 #2 已 squash 合并为 `6c0bee2941e36132bc2ac3d1f7edbef8b5790320`,61 项回归和全部 7 个 CI checks 成功;索引固定使用此提交。
624+
本地 8 项编排/基线回归覆盖 bot/head/仓库/文件边界、默认分支移动、局部 dispatch 恢复、重复 PR、人工 PR 和局部提案失败。
625+
Actionlint、真实 PR CI 与 bot 生产验证结果在本节补充;未完成前不再报告无人值守链路已通过。

‎.agents/skills/add-mcpp-index-package/SKILL.md‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ description: Use when adding a new third-party library/package to the mcpp-index
66
# 向 mcpp-index 新增一个库(标准作业流程)
77

88
本文件定义将上游库收录进 [`mcpp-index`](https://github.com/mcpplibs/mcpp-index) 的标准流程。其产出包括:一个
9-
`pkgs/<x>/<name>.lua` 描述符、一个 GitCode CN 镜像、一个位于 `tests/examples/` 的最小工程、一条 README 记录,
9+
`pkgs/<x>/<name>.lua` 描述符、可用时的 GitCode CN 镜像、一个位于 `tests/examples/` 的最小工程、适用时的自动更新声明,
1010
以及一份设计文档。完整流程为:本地验证通过,提交 PR,CI 全部通过,由维护者合并。合并后,`publish-artifact.yml`
1111
将自动重新发布 index artifact。
1212

@@ -21,6 +21,7 @@ description: Use when adding a new third-party library/package to the mcpp-index
2121

2222
- [docs/zh/package-types.md](../../../docs/zh/package-types.md) —— 四种库形态的描述符模板与样例路径。
2323
- [docs/zh/cn-mirror.md](../../../docs/zh/cn-mirror.md) —— CN 镜像闭环,含无 `mcpp-res` 权限时的回退方案。
24+
- [docs/zh/automatic-updates.md](../../../docs/zh/automatic-updates.md) —— 自动更新适用条件、声明、每日 bot PR 和候选 CI。
2425
- [docs/zh/repository-and-schema.md](../../../docs/zh/repository-and-schema.md) —— 仓库结构、schema、CI 行为、关键文件与注意事项。
2526

2627
## 适用范围
@@ -71,7 +72,7 @@ description: Use when adding a new third-party library/package to the mcpp-index
7172
编译为 no-op `main`(`#ifdef __linux__ … #else int main(){return 0;} #endif` 模式)。
7273
- 如需测试 feature,依赖采用长式声明 `name = { version = "…", features = ["…"] }`。
7374
7. **本地验证**(使用与 CI 相同版本的 mcpp,详见下文“本地验证”)。必须实际执行 `mcpp test -p <member>` 并通过。
74-
8. **更新 README**:在对应分类表中新增一条记录 —— `README.md`(英文,默认)与 `README.zh-CN.md`(中文)两份都要更新。
75+
8. **接入自动更新**:按下节检查适用条件;符合条件的包必须添加 `extensions.autoupdate` 并验证。普通包 PR 不修改两份根 README,也不为新包修改站点配置;站点会自动发现描述符。
7576
9. **撰写设计文档** `.agents/docs/<YYYY-MM-DD>-add-<lib>-plan.md`,记录形态判定、镜像、feature 评估、验证结论
7677
与注意事项。
7778
10. **本地 lint**:在本地复现 `validate.yml` 的 lint 检查(语法、必填字段、无前导 v、镜像表校验)。详见
@@ -82,6 +83,23 @@ description: Use when adding a new third-party library/package to the mcpp-index
8283
(日志中 `selected members: <member>`),`lint`(含 `mcpp xpkg parse`)与 `mirror-cn-reachable`
8384
覆盖新增描述符与 CN url。合并由维护者执行。
8485

86+
## 自动更新与 PR 范围
87+
88+
- 对公共 GitHub release/数字 tag、稳定下载模板、无需改变构建配方的包,主动添加
89+
`package.extensions.autoupdate = { tag = "v${version}", url = "https://github.com/acme/foo/archive/refs/tags/${tag}.tar.gz" }`。
90+
实际 tag 不带 `v` 时使用 `${version}`;按真实上游规则填写,不照抄示例。
91+
- 共享 URL 或按平台映射均可。新版本可以直接使用 GitHub,不要求自动 mirror;不要声明尚不存在的 CN 模板。
92+
- commit 快照、独立源码/包版本映射、非 GitHub 来源、需要改配方的升级不强行接入;在 PR 中说明原因。
93+
- 使用 workflow 固定的工具提交运行 `inspect --package <namespace:name>` 和
94+
`check --package <namespace:name> --output plan.json`;确实存在候选时,在干净 worktree 中 `apply` 并检查补丁。
95+
新增版本必须有真实构建、运行、锁文件验证;不能只用仍依赖旧版本的测试证明升级成功。
96+
- 现有版本、URL、镜像、SHA256 和注释均保留;不迁移旧内联条目。相同新资源可以前置定义一次并由平台引用。
97+
- 每日默认分支 Action 由 `github-actions[bot]` 开 PR,并显式 dispatch 候选、消费者、站点和 openkal CI。
98+
它不审批、不自动合并;普通 PR 和更新分支不会创建更多 PR。
99+
- **一般包 PR 不改 README**:不要追加 “Additional example / 新增示例”、包列表、更新记录或 agent 提示词。
100+
用户明确要求整理文档或说明确有变化时才改入口文档。新增包通常也不改 `.xpkgindex.json`。
101+
- 详细字段、例外和认证机制见 [自动更新文档](../../../docs/zh/automatic-updates.md)。
102+
85103
## feature 机制
86104

87105
mcpp **0.0.68** 的包描述符 `features` 表**仅能门控 `sources`**;其余子字段会被解析器忽略(经 `manifest.cppm` 的

‎.github/workflows/openkal-compat.yml‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ on:
1313
- cron: "0 7 * * 0"
1414
workflow_dispatch:
1515
inputs:
16+
update_pr:
17+
description: "Bot update PR number; measure only members affected by its exact head"
18+
required: false
19+
default: ""
1620
members:
1721
description: "Space-separated members to measure (empty = every listed member)"
1822
required: false
@@ -62,6 +66,9 @@ jobs:
6266
name: measure (linux, windows through wine)
6367
runs-on: ubuntu-24.04
6468
timeout-minutes: 240
69+
permissions:
70+
contents: read
71+
pull-requests: read
6572
outputs:
6673
members: ${{ steps.select.outputs.members }}
6774
steps:
@@ -75,11 +82,20 @@ jobs:
7582
- name: Select the members
7683
id: select
7784
shell: bash
85+
env:
86+
UPDATE_PR: ${{ inputs.update_pr }}
87+
GH_TOKEN: ${{ github.token }}
88+
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
7889
run: |
7990
if [ "${{ github.event_name }}" = "pull_request" ]; then
8091
base=$(git merge-base "origin/${{ github.base_ref }}" HEAD)
8192
files=$(git diff --name-only "$base" HEAD)
8293
members=$(python3 tests/openkal/compat.py select --base "$base" $files)
94+
elif [ -n "$UPDATE_PR" ]; then
95+
requested_base=$(python3 tests/autoupdate/automation.py verify --pr "$UPDATE_PR")
96+
base=$(git merge-base "$requested_base" HEAD)
97+
files=$(git diff --name-only "$base" HEAD)
98+
members=$(python3 tests/openkal/compat.py select --base "$base" $files)
8399
else
84100
members="${{ github.event.inputs.members }}"
85101
[ -n "$members" ] || members=$(python3 tests/openkal/compat.py select tests/openkal/)

‎.github/workflows/validate.yml‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ on:
2323
- cron: "0 6 * * 0"
2424
workflow_dispatch:
2525
inputs:
26+
update_pr:
27+
description: "Bot update PR number; dispatch its exact head with selective regression"
28+
type: string
29+
required: false
2630
cache:
2731
description: "Package build cache — 'local' rebuilds every dependency per member, which is what the timing table should be read against when comparing"
2832
type: choice
@@ -680,6 +684,9 @@ jobs:
680684
# a selective one does not.
681685
select:
682686
runs-on: ubuntu-latest
687+
permissions:
688+
contents: read
689+
pull-requests: read
683690
outputs:
684691
members: ${{ steps.fanout.outputs.members }}
685692
matrix: ${{ steps.fanout.outputs.matrix }}
@@ -716,6 +723,10 @@ jobs:
716723
- name: Select affected workspace members
717724
id: plan
718725
shell: bash
726+
env:
727+
UPDATE_PR: ${{ inputs.update_pr }}
728+
GH_TOKEN: ${{ github.token }}
729+
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
719730
run: |
720731
# A FULL RUN IS NO LONGER SOMETHING A PR CAN TRIGGER BY ACCIDENT.
721732
#
@@ -799,6 +810,13 @@ jobs:
799810
|| { widen "push predecessor $base not in history"; usable=0; }
800811
fi
801812
if [ "$usable" = 1 ]; then range="$base..HEAD"; else range=""; fi ;;
813+
workflow_dispatch)
814+
if [ -n "$UPDATE_PR" ]; then
815+
base=$(python3 tests/autoupdate/automation.py verify --pr "$UPDATE_PR")
816+
range="$base...HEAD"
817+
else
818+
full "event=workflow_dispatch"
819+
fi ;;
802820
*)
803821
full "event=${{ github.event_name }}" ;;
804822
esac
@@ -1743,7 +1761,7 @@ jobs:
17431761
if: >-
17441762
always()
17451763
&& (needs.workspace.result == 'failure' || needs.mirror-cn-reachable.result == 'failure')
1746-
&& (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
1764+
&& (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.update_pr == ''))
17471765
runs-on: ubuntu-latest
17481766
permissions:
17491767
issues: write

0 commit comments

Comments
 (0)