From d6bd73aee624094b805955b9a4652970b650745f Mon Sep 17 00:00:00 2001 From: RockChinQ Date: Sun, 1 Nov 2026 15:55:12 +0000 Subject: [PATCH] ci(platform): notify maintainers when PRs change platform adapter files Co-Authored-By: Claude Opus 5.5 Co-authored-by: multica-agent --- .../platform-adapter-review-notice.yml | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 .github/workflows/platform-adapter-review-notice.yml diff --git a/.github/workflows/platform-adapter-review-notice.yml b/.github/workflows/platform-adapter-review-notice.yml new file mode 100644 index 000000000..63a831b67 --- /dev/null +++ b/.github/workflows/platform-adapter-review-notice.yml @@ -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 = ''; + 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, + '', + `最近更新于提交 / Last updated for commit ${pr.head.sha.slice(0, 7)}`, + ].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}`); + }