mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
ff10db092b
* ci(mantis): extract shared request, trust, and reaction workflows * ci(mantis): drop caller-less params from shared resolve workflow * test(mantis): read candidate-override parsing from shared resolve workflow
245 lines
9.7 KiB
YAML
245 lines
9.7 KiB
YAML
name: Mantis Resolve Request
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
request-pattern:
|
|
description: JavaScript regex source matched against the normalized comment body
|
|
required: true
|
|
type: string
|
|
exclude-pattern:
|
|
description: Optional JavaScript regex source that suppresses a matching request
|
|
required: false
|
|
default: ""
|
|
type: string
|
|
skip-notice:
|
|
description: Notice emitted when a Mantis mention does not request this workflow
|
|
required: true
|
|
type: string
|
|
dispatch-params:
|
|
description: Workflow-specific dispatch inputs or issue-comment defaults as JSON
|
|
required: false
|
|
default: "{}"
|
|
type: string
|
|
runner:
|
|
description: Runner used for request resolution
|
|
required: false
|
|
default: ubuntu-24.04
|
|
type: string
|
|
secrets:
|
|
MANTIS_GITHUB_APP_ID:
|
|
required: true
|
|
MANTIS_GITHUB_APP_PRIVATE_KEY:
|
|
required: true
|
|
outputs:
|
|
should_run:
|
|
value: ${{ jobs.resolve.outputs.should_run }}
|
|
request_source:
|
|
value: ${{ jobs.resolve.outputs.request_source }}
|
|
pr_number:
|
|
value: ${{ jobs.resolve.outputs.pr_number }}
|
|
candidate_ref:
|
|
value: ${{ jobs.resolve.outputs.candidate_ref }}
|
|
baseline_ref:
|
|
value: ${{ jobs.resolve.outputs.baseline_ref }}
|
|
reaction_id:
|
|
value: ${{ jobs.resolve.outputs.reaction_id }}
|
|
params:
|
|
value: ${{ jobs.resolve.outputs.params }}
|
|
|
|
env:
|
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
|
|
|
jobs:
|
|
resolve:
|
|
name: Resolve Mantis request
|
|
runs-on: ${{ inputs.runner }}
|
|
outputs:
|
|
baseline_ref: ${{ steps.resolve.outputs.baseline_ref }}
|
|
candidate_ref: ${{ steps.resolve.outputs.candidate_ref }}
|
|
params: ${{ steps.resolve.outputs.params }}
|
|
pr_number: ${{ steps.resolve.outputs.pr_number }}
|
|
reaction_id: ${{ steps.add_reaction.outputs.reaction_id }}
|
|
request_source: ${{ steps.resolve.outputs.request_source }}
|
|
should_run: ${{ steps.resolve.outputs.should_run }}
|
|
steps:
|
|
- name: Resolve refs and target PR
|
|
id: resolve
|
|
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
|
|
env:
|
|
DISPATCH_PARAMS: ${{ inputs.dispatch-params }}
|
|
EXCLUDE_PATTERN: ${{ inputs.exclude-pattern }}
|
|
REQUEST_PATTERN: ${{ inputs.request-pattern }}
|
|
SKIP_NOTICE: ${{ inputs.skip-notice }}
|
|
with:
|
|
script: |
|
|
const eventName = context.eventName;
|
|
const dispatchParams = JSON.parse(process.env.DISPATCH_PARAMS || "{}");
|
|
|
|
function stringParam(value) {
|
|
return typeof value === "string" ? value : "";
|
|
}
|
|
|
|
function setOutput(name, value) {
|
|
core.setOutput(name, value ?? "");
|
|
core.info(`${name}=${value ?? ""}`);
|
|
}
|
|
|
|
function setResolvedOutputs({ baselineRef, candidateRef, params, prNumber, source }) {
|
|
setOutput("should_run", "true");
|
|
setOutput("baseline_ref", baselineRef);
|
|
setOutput("candidate_ref", candidateRef);
|
|
setOutput("pr_number", prNumber);
|
|
setOutput("request_source", source);
|
|
setOutput("params", JSON.stringify(params));
|
|
}
|
|
|
|
async function getPullRequest(pullNumber) {
|
|
const { owner, repo } = context.repo;
|
|
const { data: pullRequest } = await github.rest.pulls.get({
|
|
owner,
|
|
repo,
|
|
pull_number: Number(pullNumber),
|
|
});
|
|
return pullRequest;
|
|
}
|
|
|
|
if (eventName === "workflow_dispatch") {
|
|
const prNumber = stringParam(dispatchParams.pr_number);
|
|
const pullRequest = prNumber ? await getPullRequest(prNumber) : undefined;
|
|
const candidateRef = stringParam(dispatchParams.candidate_ref) || pullRequest?.head.sha || "";
|
|
const baselineRef = stringParam(dispatchParams.baseline_ref) || pullRequest?.base.sha || "";
|
|
const params = {
|
|
...dispatchParams,
|
|
baseline_ref: baselineRef,
|
|
candidate_ref: candidateRef,
|
|
crabbox_provider:
|
|
stringParam(dispatchParams.crabbox_provider) ||
|
|
stringParam(dispatchParams.provider),
|
|
lease_id:
|
|
stringParam(dispatchParams.crabbox_lease_id) ||
|
|
stringParam(dispatchParams.lease_id) ||
|
|
stringParam(dispatchParams.lease),
|
|
pr_number: prNumber,
|
|
provider_mode:
|
|
stringParam(dispatchParams.provider_mode) ||
|
|
stringParam(dispatchParams["provider-mode"]),
|
|
scenario: stringParam(dispatchParams.scenario),
|
|
};
|
|
setResolvedOutputs({
|
|
baselineRef,
|
|
candidateRef,
|
|
params,
|
|
prNumber,
|
|
source: "workflow_dispatch",
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (eventName !== "issue_comment") {
|
|
core.setFailed(`Unsupported event: ${eventName}`);
|
|
return;
|
|
}
|
|
|
|
const issue = context.payload.issue;
|
|
const body = context.payload.comment?.body ?? "";
|
|
if (!issue?.pull_request) {
|
|
core.setFailed("Mantis issue_comment trigger requires a pull request comment.");
|
|
return;
|
|
}
|
|
|
|
const normalized = body.toLowerCase();
|
|
const mentionsMantis =
|
|
normalized.includes("@openclaw-mantis") ||
|
|
normalized.includes("/openclaw-mantis");
|
|
const requested = new RegExp(process.env.REQUEST_PATTERN, "u").test(normalized);
|
|
const excluded =
|
|
process.env.EXCLUDE_PATTERN !== "" &&
|
|
new RegExp(process.env.EXCLUDE_PATTERN, "u").test(normalized);
|
|
if (!mentionsMantis || !requested || excluded) {
|
|
core.notice(process.env.SKIP_NOTICE);
|
|
setOutput("should_run", "false");
|
|
setOutput("baseline_ref", "");
|
|
setOutput("candidate_ref", "");
|
|
setOutput("pr_number", "");
|
|
setOutput("request_source", "unsupported_issue_comment");
|
|
setOutput("params", "{}");
|
|
return;
|
|
}
|
|
|
|
const pullRequest = await getPullRequest(issue.number);
|
|
const token = (keys) => {
|
|
const pattern = new RegExp(
|
|
`\\b(?:${keys.join("|")})\\s*[:=]\\s*\`?([^\\s\`]+)\`?`,
|
|
"i",
|
|
);
|
|
return body.match(pattern)?.[1] ?? "";
|
|
};
|
|
const rawCandidate = token(["candidate", "head"]);
|
|
const candidateRef =
|
|
rawCandidate && !["head", "pr", "pr-head"].includes(rawCandidate.toLowerCase())
|
|
? rawCandidate
|
|
: pullRequest.head.sha;
|
|
const baselineRef =
|
|
token(["baseline", "base"]) ||
|
|
stringParam(dispatchParams.baseline_ref) ||
|
|
pullRequest.base.sha;
|
|
const params = {
|
|
...dispatchParams,
|
|
baseline_ref: baselineRef,
|
|
candidate_ref: candidateRef,
|
|
crabbox_provider:
|
|
token(["provider", "crabbox_provider"]) ||
|
|
stringParam(dispatchParams.crabbox_provider) ||
|
|
stringParam(dispatchParams.provider),
|
|
lease_id:
|
|
token(["lease", "lease_id", "crabbox_lease_id"]) ||
|
|
stringParam(dispatchParams.crabbox_lease_id) ||
|
|
stringParam(dispatchParams.lease_id) ||
|
|
stringParam(dispatchParams.lease),
|
|
pr_number: String(issue.number),
|
|
provider_mode:
|
|
token(["provider_mode", "provider-mode"]) ||
|
|
stringParam(dispatchParams.provider_mode) ||
|
|
stringParam(dispatchParams["provider-mode"]),
|
|
scenario:
|
|
token(["scenario", "scenarios"]) || stringParam(dispatchParams.scenario),
|
|
};
|
|
setResolvedOutputs({
|
|
baselineRef,
|
|
candidateRef,
|
|
params,
|
|
prNumber: String(issue.number),
|
|
source: "issue_comment",
|
|
});
|
|
|
|
- name: Create Mantis reaction GitHub App token
|
|
id: mantis_reaction_token
|
|
if: ${{ steps.resolve.outputs.request_source == 'issue_comment' }}
|
|
continue-on-error: true
|
|
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3
|
|
with:
|
|
app-id: ${{ secrets.MANTIS_GITHUB_APP_ID }}
|
|
private-key: ${{ secrets.MANTIS_GITHUB_APP_PRIVATE_KEY }}
|
|
owner: ${{ github.repository_owner }}
|
|
repositories: ${{ github.event.repository.name }}
|
|
permission-issues: write
|
|
|
|
- name: Add Mantis eyes reaction
|
|
id: add_reaction
|
|
if: ${{ steps.resolve.outputs.request_source == 'issue_comment' && steps.mantis_reaction_token.outcome == 'success' }}
|
|
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
|
|
with:
|
|
github-token: ${{ steps.mantis_reaction_token.outputs.token }}
|
|
script: |
|
|
const { owner, repo } = context.repo;
|
|
await github.rest.reactions
|
|
.createForIssueComment({
|
|
owner,
|
|
repo,
|
|
comment_id: context.payload.comment.id,
|
|
content: "eyes",
|
|
})
|
|
.then(({ data: reaction }) => core.setOutput("reaction_id", String(reaction.id)))
|
|
.catch((error) => core.warning(`Could not add eyes reaction: ${error.message}`));
|