-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
245 lines (223 loc) · 11.3 KB
/
Copy pathchack-agent-pr-triage.yml
File metadata and controls
245 lines (223 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
name: Chack-Agent PR Triage
on:
workflow_run:
workflows: ["PR-tests"]
types: [completed]
jobs:
# NOTE: The windows-definitions bot PR is built, waited on and merged inline by
# update_windows_version_definitions.yml (it dispatches PR-tests with github.token, polls
# that run, then squash-merges with the CODEX_FIXER_TOKEN PAT so the push to master triggers
# the release). It is intentionally NOT handled here: a github.token-dispatched run does not
# emit a `workflow_run` event, so a job here could never reliably fire for it.
chack_agent_triage:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
env:
CHACK_LOGS_HTTP_URL: ${{ secrets.CHACK_LOGS_HTTP_URL }}
outputs:
should_run: ${{ steps.gate.outputs.should_run }}
pr_number: ${{ steps.gate.outputs.pr_number }}
pr_title: ${{ steps.gate.outputs.pr_title }}
pr_body: ${{ steps.gate.outputs.pr_body }}
base_ref: ${{ steps.gate.outputs.base_ref }}
head_ref: ${{ steps.gate.outputs.head_ref }}
base_sha: ${{ steps.gate.outputs.base_sha }}
head_sha: ${{ steps.gate.outputs.head_sha }}
trusted_automerge: ${{ steps.gate.outputs.trusted_automerge }}
trusted_automerge_reason: ${{ steps.gate.outputs.trusted_automerge_reason }}
decision: ${{ steps.parse.outputs.decision }}
message: ${{ steps.parse.outputs.message }}
steps:
- name: Resolve PR context
id: gate
env:
PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }}
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
run: |
pr_number="${PR_NUMBER}"
if [ -z "$pr_number" ] && [ -n "$HEAD_BRANCH" ]; then
pr_number="$(gh pr list --state open --head "$HEAD_BRANCH" --json number --jq '.[0].number')"
fi
if [ -z "$pr_number" ]; then
echo "No pull request found for this workflow_run; skipping."
echo "should_run=false" >> "$GITHUB_OUTPUT"
echo "pr_number=" >> "$GITHUB_OUTPUT"
exit 0
fi
author="$(gh pr view "$pr_number" --json author --jq .author.login)"
if [ "$author" != "carlospolop" ]; then
echo "PR author is $author; skipping."
echo "should_run=false" >> "$GITHUB_OUTPUT"
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
exit 0
fi
pr_title="$(gh pr view "$pr_number" --json title --jq .title)"
pr_body="$(gh pr view "$pr_number" --json body --jq .body)"
base_ref="$(gh pr view "$pr_number" --json baseRefName --jq .baseRefName)"
head_ref="$(gh pr view "$pr_number" --json headRefName --jq .headRefName)"
base_sha="$(gh pr view "$pr_number" --json baseRefOid --jq .baseRefOid)"
head_sha="$(gh pr view "$pr_number" --json headRefOid --jq .headRefOid)"
trusted_automerge=false
trusted_automerge_reason=""
if [ "$base_ref" = "master" ] || [ "$base_ref" = "main" ]; then
case "$head_ref:$pr_title" in
chack-agent/ci-master-fix-[0-9]*:"Fix CI-master_test failure (run #"*")")
trusted_automerge=true
trusted_automerge_reason="trusted CI-master Chack Agent fix PR"
;;
autoimprover/linpeas/[0-9]*:"autoimprover: simplify linpeas checks")
trusted_automerge=true
trusted_automerge_reason="trusted HackTricks-Feed linPEAS autoimprover PR"
;;
autoimprover/winpeas/[0-9]*:"autoimprover: simplify winpeas checks")
trusted_automerge=true
trusted_automerge_reason="trusted HackTricks-Feed winPEAS autoimprover PR"
;;
esac
fi
echo "should_run=true" >> "$GITHUB_OUTPUT"
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
echo "pr_title<<EOF" >> "$GITHUB_OUTPUT"
echo "$pr_title" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
echo "pr_body<<EOF" >> "$GITHUB_OUTPUT"
echo "$pr_body" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
echo "base_ref=$base_ref" >> "$GITHUB_OUTPUT"
echo "head_ref=$head_ref" >> "$GITHUB_OUTPUT"
echo "base_sha=$base_sha" >> "$GITHUB_OUTPUT"
echo "head_sha=$head_sha" >> "$GITHUB_OUTPUT"
echo "trusted_automerge=$trusted_automerge" >> "$GITHUB_OUTPUT"
echo "trusted_automerge_reason=$trusted_automerge_reason" >> "$GITHUB_OUTPUT"
- name: Checkout PR merge ref
uses: actions/checkout@v5
with:
ref: refs/pull/${{ steps.gate.outputs.pr_number }}/merge
if: ${{ steps.gate.outputs.should_run == 'true' && steps.gate.outputs.trusted_automerge != 'true' }}
- name: Pre-fetch base and head refs
if: ${{ steps.gate.outputs.should_run == 'true' && steps.gate.outputs.trusted_automerge != 'true' }}
run: |
git fetch --no-tags origin \
${{ steps.gate.outputs.base_ref }} \
+refs/pull/${{ steps.gate.outputs.pr_number }}/head
- name: Set up Node.js for Codex
if: ${{ steps.gate.outputs.should_run == 'true' && steps.gate.outputs.trusted_automerge != 'true' }}
uses: actions/setup-node@v5
with:
node-version: "20"
- name: Install Codex CLI
if: ${{ steps.gate.outputs.should_run == 'true' && steps.gate.outputs.trusted_automerge != 'true' }}
run: |
npm install -g @openai/codex
codex --version
- name: Run Chack Agent
id: run_chack
if: ${{ steps.gate.outputs.should_run == 'true' && steps.gate.outputs.trusted_automerge != 'true' }}
# Pin the action so dependency changes on its default branch cannot break PR triage.
uses: carlospolop/chack-agent@9fd38a0657ae7060cc9bb07329c0bde71d7ba0d9
with:
provider: codex
model_primary: BEST_QUALITY
max_turns: 125
main_action: peass-ng-pr-traige
sub_action: Chack-Agent PR Triage
system_prompt: |
You are Chack Agent, an elite PR reviewer for PEASS-ng.
Be conservative: merge only if changes are simple, safe, and valuable accoding to the uers give guidelines.
If in doubt, comment with clear questions or concerns.
Remember taht you are an autonomouts agent, use the exec tool to run the needed commands to list, read, analyze, modify, test...
tools_config_json: "{\"exec_enabled\": true}"
session_config_json: "{\"long_term_memory_enabled\": false}"
agent_config_json: "{\"self_critique_enabled\": false, \"require_task_steps_manager_init_first\": true}"
output_schema_file: .github/chack-agent/pr-merge-schema.json
user_prompt: |
You are reviewing PR #${{ steps.gate.outputs.pr_number }} for ${{ github.repository }}.
Decide whether to merge or comment. Merge only if all of the following are true:
- Changes are simple and safe (no DoS, no long operations, no backdoors).
- Changes follow common PEASS syntax and style without breaking anything and add useful checks or value.
- Changes simplify code or add new useful checks without breaking anything.
If you don't have any doubts, and all the previous conditions are met, decide to merge.
If you have serious doubts, choose "comment" and include your doubts or questions.
If you decide to merge, include a short rationale.
Pull request title and body:
----
${{ steps.gate.outputs.pr_title }}
${{ steps.gate.outputs.pr_body }}
Review ONLY the changes introduced by the PR:
git log --oneline ${{ steps.gate.outputs.base_sha }}...${{ steps.gate.outputs.head_sha }}
Output JSON only, following the provided schema:
.github/chack-agent/pr-merge-schema.json
codex_access_token: ${{ secrets.CODEX_ACCESS_TOKEN }}
openai_api_key: ${{ secrets.OPENAI_API_KEY }}
- name: Parse Chack Agent decision
id: parse
if: ${{ steps.gate.outputs.should_run == 'true' && steps.gate.outputs.trusted_automerge != 'true' }}
env:
CHACK_MESSAGE: ${{ steps.run_chack.outputs.final-message }}
run: |
python3 - <<'PY'
import json
import os
raw = (os.environ.get('CHACK_MESSAGE', '') or '').strip()
decision = 'comment'
message = 'Chack Agent did not provide details.'
try:
data = json.loads(raw or '{}')
if isinstance(data, dict):
decision = data.get('decision', 'comment')
message = data.get('message', '').strip() or message
else:
message = raw or message
except Exception:
message = raw or message
with open(os.environ['GITHUB_OUTPUT'], 'a') as handle:
handle.write(f"decision={decision}\n")
handle.write("message<<EOF\n")
handle.write(message + "\n")
handle.write("EOF\n")
PY
merge_or_comment:
runs-on: ubuntu-latest
needs: chack_agent_triage
if: ${{ github.event.workflow_run.conclusion == 'success' && needs.chack_agent_triage.outputs.should_run == 'true' && (needs.chack_agent_triage.outputs.trusted_automerge == 'true' || needs.chack_agent_triage.outputs.decision != '') }}
permissions:
contents: write
pull-requests: write
steps:
- name: Merge PR when approved
if: ${{ needs.chack_agent_triage.outputs.trusted_automerge == 'true' || needs.chack_agent_triage.outputs.decision == 'merge' }}
env:
GH_TOKEN: ${{ secrets.CODEX_FIXER_TOKEN || github.token }}
PR_NUMBER: ${{ needs.chack_agent_triage.outputs.pr_number }}
TRUSTED_AUTOMERGE: ${{ needs.chack_agent_triage.outputs.trusted_automerge }}
TRUSTED_AUTOMERGE_REASON: ${{ needs.chack_agent_triage.outputs.trusted_automerge_reason }}
run: |
if [ "$TRUSTED_AUTOMERGE" = "true" ]; then
echo "Auto-merging trusted generated PR #${PR_NUMBER}: ${TRUSTED_AUTOMERGE_REASON}"
fi
gh api \
-X PUT \
-H "Accept: application/vnd.github+json" \
/repos/${{ github.repository }}/pulls/${PR_NUMBER}/merge \
-f merge_method=squash \
-f commit_title="Auto-merge PR #${PR_NUMBER} (Chack Agent)"
- name: Comment with doubts
if: ${{ needs.chack_agent_triage.outputs.trusted_automerge != 'true' && needs.chack_agent_triage.outputs.decision == 'comment' }}
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.chack_agent_triage.outputs.pr_number }}
CHACK_MESSAGE: ${{ needs.chack_agent_triage.outputs.message }}
with:
github-token: ${{ github.token }}
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: Number(process.env.PR_NUMBER),
body: process.env.CHACK_MESSAGE,
});