ci(platform): notify maintainers when PRs change platform adapter files

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-authored-by: multica-agent <[email protected]>
This commit is contained in:
RockChinQ
2026-11-01 15:55:12 +00:00
co-authored by Claude Opus 5.5 multica-agent
parent 8ee321f8c1
commit d6bd73aee6
@@ -0,0 +1,107 @@
name: Platform Adapter Review Notice
on:
pull_request_target:
types: [opened, ready_for_review, synchronize]
permissions:
contents: read
pull-requests: write
concurrency:
group: platform-adapter-review-notice-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
notice:
name: Notify maintainers about platform adapter changes
runs-on: ubuntu-latest
# SECURITY: this workflow runs on pull_request_target (write token on the base
# repository). NEVER add an actions/checkout step for the PR head or run any code
# from the PR. It only reads the changed file list through the GitHub API.
steps:
- name: Comment on PR when platform adapter files change
uses: actions/github-script@v7
with:
script: |
const MARKER = '<!-- langbot-platform-adapter-review-notice -->';
const PLATFORM_LIBS = [
'dingtalk_api',
'official_account_api',
'openclaw_weixin_api',
'qq_official_api',
'slack_api',
'wechatpad_api',
'wecom_ai_bot_api',
'wecom_api',
'wecom_customer_service_api',
];
const isAdapterFile = (path) =>
path.startsWith('src/langbot/pkg/platform/adapters/') ||
path.startsWith('src/langbot/pkg/platform/sources/') ||
PLATFORM_LIBS.some((lib) => path.startsWith(`src/langbot/libs/${lib}/`));
const { owner, repo } = context.repo;
const pr = context.payload.pull_request;
const files = await github.paginate(github.rest.pulls.listFiles, {
owner,
repo,
pull_number: pr.number,
per_page: 100,
});
const changed = files.filter(
(f) => isAdapterFile(f.filename) || (f.previous_filename && isAdapterFile(f.previous_filename)),
);
if (changed.length === 0) {
core.info('No platform adapter files changed.');
return;
}
const list = changed
.map((f) => {
const name = f.previous_filename && f.previous_filename !== f.filename
? `\`${f.previous_filename}\` → \`${f.filename}\``
: `\`${f.filename}\``;
return `- ${name} (${f.status}, +${f.additions}/-${f.deletions})`;
})
.join('\n');
const body = [
MARKER,
'### ⚠️ 平台适配器变更提示 / Platform Adapter Change Notice',
'',
'本 PR 修改了平台适配器相关文件。平台适配器依赖真实的 IM 平台行为,单元测试无法完全覆盖,**合并前需要维护者在真实平台上进行实际检查**(收发消息、事件回调、媒体消息等关键链路)。',
'',
'This PR modifies platform adapter files. Platform adapters depend on real IM platform behavior that unit tests cannot fully cover, so **a maintainer must verify the change against the real platform before merging** (sending/receiving messages, event callbacks, media messages and other critical paths).',
'',
`**被修改的平台适配器文件 / Changed platform adapter files (${changed.length}):**`,
'',
list,
'',
`<sub>最近更新于提交 / Last updated for commit ${pr.head.sha.slice(0, 7)}</sub>`,
].join('\n');
const comments = await github.paginate(github.rest.issues.listComments, {
owner,
repo,
issue_number: pr.number,
per_page: 100,
});
const existing = comments.find(
(c) => c.user?.type === 'Bot' && c.body?.includes(MARKER),
);
if (existing) {
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
core.info(`Updated comment ${existing.id}`);
} else {
const { data } = await github.rest.issues.createComment({
owner,
repo,
issue_number: pr.number,
body,
});
core.info(`Created comment ${data.id}`);
}