




















@@ -0,0 +1,89 @@
1+name: Maintainer Command Reactions
2+3+on:
4+issue_comment:
5+types: [created, edited]
6+7+permissions: {}
8+9+concurrency:
10+group: maintainer-command-reactions-${{ github.event.comment.id }}
11+cancel-in-progress: true
12+13+jobs:
14+react:
15+if: ${{ github.event.issue.pull_request && !endsWith(github.actor, '[bot]') }}
16+runs-on: ubuntu-24.04
17+permissions:
18+issues: write
19+env:
20+CLOWNFISH_APP_ID: ${{ vars.CLOWNFISH_APP_ID || secrets.CLOWNFISH_APP_ID }}
21+CLOWNFISH_APP_AUTH_ENABLED: ${{ secrets.CLOWNFISH_APP_PRIVATE_KEY != '' && (vars.CLOWNFISH_APP_ID != '' || secrets.CLOWNFISH_APP_ID != '') && '1' || '0' }}
22+MAINTAINER_COMMAND_REACTIONS: ${{ vars.MAINTAINER_COMMAND_REACTIONS || '/automerge,/merge,/land,/landpr' }}
23+steps:
24+ - name: Create Clownfish reaction token
25+id: clownfish-token
26+if: ${{ env.CLOWNFISH_APP_AUTH_ENABLED == '1' }}
27+continue-on-error: true
28+uses: actions/create-github-app-token@v3
29+with:
30+app-id: ${{ env.CLOWNFISH_APP_ID }}
31+private-key: ${{ secrets.CLOWNFISH_APP_PRIVATE_KEY }}
32+owner: openclaw
33+repositories: openclaw
34+permission-issues: write
35+36+ - name: React to maintainer slash command
37+uses: actions/github-script@v9
38+with:
39+github-token: ${{ steps.clownfish-token.outputs.token || github.token }}
40+script: |
41+ const comment = context.payload.comment;
42+ const issue = context.payload.issue;
43+ const association = comment.author_association;
44+ const maintainerAssociations = new Set(["OWNER", "MEMBER", "COLLABORATOR"]);
45+ if (!maintainerAssociations.has(association)) {
46+ core.info(`Skipping non-maintainer command reaction for association ${association || "unknown"}.`);
47+ return;
48+ }
49+50+ if (!issue.pull_request) {
51+ core.info("Skipping command reaction because the comment is not on a pull request.");
52+ return;
53+ }
54+55+ const commands = (process.env.MAINTAINER_COMMAND_REACTIONS || "")
56+ .split(",")
57+ .map((command) => command.trim())
58+ .filter(Boolean);
59+ const commandLine = String(comment.body || "")
60+ .split(/\r?\n/)
61+ .map((line) => line.trim())
62+ .find((line) => commands.some((command) => line === command || line.startsWith(`${command} `)));
63+64+ if (!commandLine) {
65+ core.info(`Skipping comment ${comment.id}; no tracked maintainer command found.`);
66+ return;
67+ }
68+69+ async function react(content) {
70+ try {
71+ await github.rest.reactions.createForIssueComment({
72+ owner: context.repo.owner,
73+ repo: context.repo.repo,
74+ comment_id: comment.id,
75+ content,
76+ });
77+ core.info(`Added ${content} reaction to comment ${comment.id}.`);
78+ } catch (error) {
79+ if (error.status === 422 && /already exists/i.test(String(error.message))) {
80+ core.info(`${content} reaction already exists on comment ${comment.id}.`);
81+ return;
82+ }
83+ throw error;
84+ }
85+ }
86+87+ await react("eyes");
88+ core.info(`Maintainer command observed on PR #${issue.number}: ${commandLine}`);
89+ await react("+1");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。