




















@@ -1,6 +1,8 @@
11name: Mantis Discord Status Reactions
2233on:
4+issue_comment:
5+types: [created]
46workflow_dispatch:
57inputs:
68baseline_ref:
@@ -24,7 +26,7 @@ permissions:
2426pull-requests: write
25272628concurrency:
27-group: mantis-discord-status-reactions-${{ inputs.baseline_ref }}-${{ inputs.candidate_ref }}-${{ github.run_attempt }}
29+group: mantis-discord-status-reactions-${{ github.event.issue.number || inputs.pr_number || inputs.candidate_ref || github.run_id }}-${{ github.run_attempt }}
2830cancel-in-progress: false
29313032env:
@@ -37,6 +39,19 @@ env:
3739jobs:
3840authorize_actor:
3941name: Authorize workflow actor
42+if: >-
43+ ${{
44+ github.event_name == 'workflow_dispatch' ||
45+ (
46+ github.event_name == 'issue_comment' &&
47+ github.event.issue.pull_request &&
48+ (
49+ contains(github.event.comment.body, '@Mantis') ||
50+ contains(github.event.comment.body, '@mantis') ||
51+ contains(github.event.comment.body, '/mantis')
52+ )
53+ )
54+ }}
4055 runs-on: blacksmith-8vcpu-ubuntu-2404
4156steps:
4257 - name: Require maintainer-level repository access
@@ -58,9 +73,101 @@ jobs:
5873 );
5974 }
607576+ resolve_request:
77+name: Resolve Mantis request
78+needs: authorize_actor
79+runs-on: blacksmith-8vcpu-ubuntu-2404
80+outputs:
81+baseline_ref: ${{ steps.resolve.outputs.baseline_ref }}
82+candidate_ref: ${{ steps.resolve.outputs.candidate_ref }}
83+pr_number: ${{ steps.resolve.outputs.pr_number }}
84+request_source: ${{ steps.resolve.outputs.request_source }}
85+should_run: ${{ steps.resolve.outputs.should_run }}
86+steps:
87+ - name: Resolve refs and target PR
88+id: resolve
89+uses: actions/github-script@v8
90+with:
91+script: |
92+ const defaultBaseline = "0bf06e953fdda290799fc9fb9244a8f67fdae593";
93+ const eventName = context.eventName;
94+95+ function setOutput(name, value) {
96+ core.setOutput(name, value ?? "");
97+ core.info(`${name}=${value ?? ""}`);
98+ }
99+100+ if (eventName === "workflow_dispatch") {
101+ const inputs = context.payload.inputs ?? {};
102+ setOutput("should_run", "true");
103+ setOutput("baseline_ref", inputs.baseline_ref || defaultBaseline);
104+ setOutput("candidate_ref", inputs.candidate_ref || "main");
105+ setOutput("pr_number", inputs.pr_number || "");
106+ setOutput("request_source", "workflow_dispatch");
107+ return;
108+ }
109+110+ if (eventName !== "issue_comment") {
111+ core.setFailed(`Unsupported event: ${eventName}`);
112+ return;
113+ }
114+115+ const issue = context.payload.issue;
116+ const body = context.payload.comment?.body ?? "";
117+ if (!issue?.pull_request) {
118+ core.setFailed("Mantis issue_comment trigger requires a pull request comment.");
119+ return;
120+ }
121+122+ const normalized = body.toLowerCase();
123+ const requested =
124+ (normalized.includes("@mantis") || normalized.includes("/mantis")) &&
125+ normalized.includes("discord") &&
126+ normalized.includes("status") &&
127+ normalized.includes("reaction");
128+ if (!requested) {
129+ core.notice("Comment mentioned Mantis but did not request the Discord status-reactions scenario.");
130+ setOutput("should_run", "false");
131+ setOutput("baseline_ref", "");
132+ setOutput("candidate_ref", "");
133+ setOutput("pr_number", "");
134+ setOutput("request_source", "unsupported_issue_comment");
135+ return;
136+ }
137+138+ const { owner, repo } = context.repo;
139+ const { data: pr } = await github.rest.pulls.get({
140+ owner,
141+ repo,
142+ pull_number: issue.number,
143+ });
144+145+ const baselineMatch = body.match(/(?:baseline|base)[\s:=]+([^\s`]+)/i);
146+ const candidateMatch = body.match(/(?:candidate|head)[\s:=]+([^\s`]+)/i);
147+ const baseline = baselineMatch?.[1] ?? defaultBaseline;
148+ const rawCandidate = candidateMatch?.[1];
149+ const candidate =
150+ rawCandidate && !["head", "pr", "pr-head"].includes(rawCandidate.toLowerCase())
151+ ? rawCandidate
152+ : pr.head.sha;
153+154+ setOutput("should_run", "true");
155+ setOutput("baseline_ref", baseline);
156+ setOutput("candidate_ref", candidate);
157+ setOutput("pr_number", String(issue.number));
158+ setOutput("request_source", "issue_comment");
159+160+ await github.rest.reactions.createForIssueComment({
161+ owner,
162+ repo,
163+ comment_id: context.payload.comment.id,
164+ content: "eyes",
165+ }).catch((error) => core.warning(`Could not add eyes reaction: ${error.message}`));
166+61167 validate_refs:
62168name: Validate selected refs
63-needs: authorize_actor
169+needs: resolve_request
170+if: ${{ needs.resolve_request.outputs.should_run == 'true' }}
64171runs-on: blacksmith-8vcpu-ubuntu-2404
65172outputs:
66173baseline_revision: ${{ steps.validate.outputs.baseline_revision }}
@@ -76,8 +183,8 @@ jobs:
76183id: validate
77184env:
78185GH_TOKEN: ${{ github.token }}
79-BASELINE_REF: ${{ inputs.baseline_ref }}
80-CANDIDATE_REF: ${{ inputs.candidate_ref }}
186+BASELINE_REF: ${{ needs.resolve_request.outputs.baseline_ref }}
187+CANDIDATE_REF: ${{ needs.resolve_request.outputs.candidate_ref }}
81188shell: bash
82189run: |
83190 set -euo pipefail
@@ -126,7 +233,8 @@ jobs:
126233127234 run_status_reactions:
128235name: Run Discord status reaction before/after
129-needs: validate_refs
236+needs: [resolve_request, validate_refs]
237+if: ${{ needs.resolve_request.outputs.should_run == 'true' }}
130238runs-on: blacksmith-8vcpu-ubuntu-2404
131239timeout-minutes: 180
132240environment: qa-live-shared
@@ -268,7 +376,7 @@ jobs:
268376269377 - name: Create Mantis GitHub App token
270378id: mantis_app_token
271-if: ${{ always() && inputs.pr_number != '' }}
379+if: ${{ always() && needs.resolve_request.outputs.pr_number != '' }}
272380uses: actions/create-github-app-token@v3
273381with:
274382app-id: ${{ secrets.MANTIS_GITHUB_APP_ID }}
@@ -280,14 +388,14 @@ jobs:
280388permission-pull-requests: write
281389282390 - name: Comment PR with inline QA screenshots
283-if: ${{ always() && inputs.pr_number != '' && steps.run_mantis.outputs.output_dir != '' }}
391+if: ${{ always() && needs.resolve_request.outputs.pr_number != '' && steps.run_mantis.outputs.output_dir != '' }}
284392env:
285393GH_TOKEN: ${{ steps.mantis_app_token.outputs.token }}
286-TARGET_PR: ${{ inputs.pr_number }}
394+TARGET_PR: ${{ needs.resolve_request.outputs.pr_number }}
287395ARTIFACT_URL: ${{ steps.upload_artifact.outputs.artifact-url }}
288396BASELINE_SHA: ${{ needs.validate_refs.outputs.baseline_revision }}
289397CANDIDATE_SHA: ${{ needs.validate_refs.outputs.candidate_revision }}
290-MANTIS_COMMENT_BOT_LOGIN: ${{ vars.MANTIS_GITHUB_APP_BOT_LOGIN || 'openclaw-mantis-qa[bot]' }}
398+REQUEST_SOURCE: ${{ needs.resolve_request.outputs.request_source }}
291399shell: bash
292400run: |
293401 set -euo pipefail
@@ -343,6 +451,7 @@ jobs:
343451 baseline_status="$(jq -r '.baseline.status' "$root/comparison.json")"
344452 candidate_status="$(jq -r '.candidate.status' "$root/comparison.json")"
345453 pass="$(jq -r '.pass' "$root/comparison.json")"
454+ mantis_bot_login="$(gh api user --jq '.login')"
346455 comment_file="$(mktemp)"
347456 cat > "$comment_file" <<EOF
348457 <!-- mantis-discord-status-reactions -->
@@ -351,6 +460,7 @@ jobs:
351460 Summary: Mantis reran Discord status reactions against the known queued-only baseline and the candidate ref. The baseline reproduced the bug, while the candidate showed the expected queued -> thinking -> done reaction sequence.
352461353462 - Scenario: \`discord-status-reactions-tool-only\`
463+ - Trigger: \`${REQUEST_SOURCE}\`
354464 - Run: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}
355465 - Artifact: ${ARTIFACT_URL}
356466 - Baseline: \`${baseline_status}\` at \`${BASELINE_SHA}\`
@@ -366,7 +476,7 @@ jobs:
366476367477 comment_id="$(
368478 gh api --paginate "repos/${GITHUB_REPOSITORY}/issues/${TARGET_PR}/comments" \
369- --jq ".[] | select(.body | contains(\"<!-- mantis-discord-status-reactions -->\")) | select(.user.login == \"${MANTIS_COMMENT_BOT_LOGIN}\") | .id" \
479+ --jq ".[] | select(.body | contains(\"<!-- mantis-discord-status-reactions -->\")) | select(.user.login == \"${mantis_bot_login}\") | .id" \
370480 | tail -n 1
371481 )"
372482此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。