Skip to content

Commit f4e16f2

Browse files
committed
refactor: complete reviewer-bot stage 1 remediation
1 parent 3a53e59 commit f4e16f2

File tree

115 files changed

+5230
-4765
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

115 files changed

+5230
-4765
lines changed

.github/workflows/reviewer-bot-issue-comment-direct.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ jobs:
6161
COMMENT_ID: ${{ github.event.comment.id }}
6262
COMMENT_CREATED_AT: ${{ github.event.comment.created_at }}
6363
COMMENT_USER_TYPE: ${{ github.event.comment.user.type }}
64-
COMMENT_AUTHOR_ASSOCIATION: ${{ github.event.comment.author_association }}
6564
COMMENT_SENDER_TYPE: ${{ github.event.sender.type }}
6665
COMMENT_INSTALLATION_ID: ${{ github.event.installation.id }}
6766
COMMENT_PERFORMED_VIA_GITHUB_APP: ${{ github.event.comment.performed_via_github_app != null }}
@@ -72,5 +71,4 @@ jobs:
7271
WORKFLOW_RUN_ID: ${{ github.run_id }}
7372
WORKFLOW_NAME: ${{ github.workflow }}
7473
WORKFLOW_JOB_NAME: ${{ github.job }}
75-
CURRENT_WORKFLOW_FILE: .github/workflows/reviewer-bot-issue-comment-direct.yml
7674
run: uv run --project "$BOT_SRC_ROOT" reviewer-bot

.github/workflows/reviewer-bot-issues.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ jobs:
5353
ISSUE_TITLE: ${{ github.event.issue.title }}
5454
ISSUE_BODY: ${{ github.event.issue.body }}
5555
ISSUE_UPDATED_AT: ${{ github.event.issue.updated_at }}
56+
EVENT_CREATED_AT: ${{ github.event.issue.updated_at }}
5657
ISSUE_AUTHOR: ${{ github.event.issue.user.login }}
5758
ISSUE_HTML_URL: ${{ github.event.issue.html_url }}
5859
ISSUE_LABELS: ${{ toJson(github.event.issue.labels.*.name) }}
@@ -67,5 +68,4 @@ jobs:
6768
WORKFLOW_RUN_ID: ${{ github.run_id }}
6869
WORKFLOW_NAME: ${{ github.workflow }}
6970
WORKFLOW_JOB_NAME: ${{ github.job }}
70-
CURRENT_WORKFLOW_FILE: .github/workflows/reviewer-bot-issues.yml
7171
run: uv run --project "$BOT_SRC_ROOT" reviewer-bot

.github/workflows/reviewer-bot-pr-comment-observer.yml

Lines changed: 0 additions & 90 deletions
This file was deleted.
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
name: Reviewer Bot PR Comment Router
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
7+
permissions:
8+
contents: read
9+
10+
env:
11+
STATE_ISSUE_NUMBER: '314'
12+
13+
jobs:
14+
route-pr-comment:
15+
if: ${{ github.event.issue.pull_request != null }}
16+
runs-on: ubuntu-latest
17+
permissions:
18+
contents: read
19+
actions: read
20+
outputs:
21+
route_outcome: ${{ steps.route.outputs.route_outcome }}
22+
pr_head_full_name: ${{ steps.route.outputs.pr_head_full_name }}
23+
pr_author: ${{ steps.route.outputs.pr_author }}
24+
issue_state: ${{ steps.route.outputs.issue_state }}
25+
issue_labels: ${{ steps.route.outputs.issue_labels }}
26+
comment_author_id: ${{ steps.route.outputs.comment_author_id }}
27+
reviewer_bot_trust_class: ${{ steps.route.outputs.reviewer_bot_trust_class }}
28+
steps:
29+
- name: Route PR comment
30+
id: route
31+
env:
32+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33+
PAYLOAD_PATH: ${{ runner.temp }}/deferred-comment.json
34+
run: |
35+
python - <<'PY'
36+
import json
37+
import os
38+
import urllib.error
39+
import urllib.request
40+
from pathlib import Path
41+
42+
event_path = Path(os.environ['GITHUB_EVENT_PATH'])
43+
event = json.loads(event_path.read_text(encoding='utf-8'))
44+
repo = os.environ['GITHUB_REPOSITORY']
45+
issue = event['issue']
46+
comment = event['comment']
47+
sender = event.get('sender') or {}
48+
installation = event.get('installation') or {}
49+
labels = [str(item.get('name') or '') for item in issue.get('labels') or []]
50+
issue_labels_json = json.dumps([label for label in labels if label])
51+
issue_state = str(issue.get('state') or '').strip()
52+
comment_author = str((comment.get('user') or {}).get('login') or '').strip()
53+
comment_user_type = str((comment.get('user') or {}).get('type') or '').strip()
54+
comment_sender_type = str(sender.get('type') or '').strip()
55+
comment_author_association = str(comment.get('author_association') or '').strip()
56+
performed_via_github_app = bool(comment.get('performed_via_github_app'))
57+
installation_id = installation.get('id')
58+
route_outcome = 'trusted_direct'
59+
pr_head_full_name = ''
60+
pr_author = ''
61+
62+
if (
63+
comment_user_type != 'User'
64+
or comment_author.endswith('[bot]')
65+
or performed_via_github_app
66+
or str(installation_id or '').strip()
67+
or not comment_author
68+
):
69+
route_outcome = 'safe_noop'
70+
else:
71+
pr_number = issue['number']
72+
req = urllib.request.Request(
73+
f"https://api.github.com/repos/{repo}/pulls/{pr_number}",
74+
headers={
75+
'Authorization': f"Bearer {os.environ['GITHUB_TOKEN']}",
76+
'Accept': 'application/vnd.github+json',
77+
},
78+
)
79+
try:
80+
with urllib.request.urlopen(req) as response:
81+
pull_request = json.load(response)
82+
except urllib.error.URLError:
83+
route_outcome = 'deferred_reconcile'
84+
else:
85+
head_repo = pull_request.get('head', {}).get('repo') or {}
86+
pr_head_full_name = str(head_repo.get('full_name') or '').strip()
87+
pr_author = str((pull_request.get('user') or {}).get('login') or '').strip()
88+
if (
89+
not pr_head_full_name
90+
or not pr_author
91+
or pr_head_full_name != repo
92+
or pr_author == 'dependabot[bot]'
93+
or comment_author_association not in {'OWNER', 'MEMBER', 'COLLABORATOR'}
94+
):
95+
route_outcome = 'deferred_reconcile'
96+
97+
with open(os.environ['GITHUB_OUTPUT'], 'a', encoding='utf-8') as handle:
98+
print(f'route_outcome={route_outcome}', file=handle)
99+
print(f'pr_head_full_name={pr_head_full_name}', file=handle)
100+
print(f'pr_author={pr_author}', file=handle)
101+
print(f'issue_state={issue_state}', file=handle)
102+
print(f'issue_labels={issue_labels_json}', file=handle)
103+
print(f'comment_author_id={int((comment.get("user") or {}).get("id") or 0)}', file=handle)
104+
print('reviewer_bot_trust_class=pr_trusted_direct', file=handle)
105+
106+
if route_outcome == 'deferred_reconcile':
107+
payload = {
108+
'payload_kind': 'deferred_comment',
109+
'schema_version': 3,
110+
'source_workflow_name': 'Reviewer Bot PR Comment Router',
111+
'source_workflow_file': '.github/workflows/reviewer-bot-pr-comment-router.yml',
112+
'source_run_id': int(os.environ['GITHUB_RUN_ID']),
113+
'source_run_attempt': int(os.environ['GITHUB_RUN_ATTEMPT']),
114+
'source_event_name': 'issue_comment',
115+
'source_event_action': 'created',
116+
'source_event_key': f"issue_comment:{comment['id']}",
117+
'pr_number': int(issue['number']),
118+
'comment_id': int(comment['id']),
119+
'comment_body': str(comment.get('body') or ''),
120+
'comment_created_at': str(comment.get('created_at') or ''),
121+
'comment_author': comment_author,
122+
'comment_author_id': int((comment.get('user') or {}).get('id') or 0),
123+
'comment_user_type': comment_user_type,
124+
'comment_sender_type': comment_sender_type,
125+
'comment_installation_id': str(installation_id) if installation_id is not None else None,
126+
'comment_performed_via_github_app': performed_via_github_app,
127+
'issue_author': str((issue.get('user') or {}).get('login') or ''),
128+
'issue_state': issue_state,
129+
'issue_labels': [label for label in labels if label],
130+
}
131+
Path(os.environ['PAYLOAD_PATH']).write_text(json.dumps(payload), encoding='utf-8')
132+
PY
133+
- name: Upload deferred comment artifact
134+
if: ${{ steps.route.outputs.route_outcome == 'deferred_reconcile' }}
135+
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
136+
with:
137+
name: reviewer-bot-comment-context-${{ github.run_id }}-attempt-${{ github.run_attempt }}
138+
path: ${{ runner.temp }}/deferred-comment.json
139+
retention-days: 7
140+
if-no-files-found: error
141+
142+
trusted-direct:
143+
if: ${{ needs.route-pr-comment.outputs.route_outcome == 'trusted_direct' }}
144+
needs: [route-pr-comment]
145+
runs-on: ubuntu-latest
146+
permissions:
147+
contents: write
148+
issues: write
149+
pull-requests: write
150+
actions: read
151+
steps:
152+
- name: Install uv
153+
run: python -m pip install uv
154+
- name: Fetch trusted bot source tarball
155+
env:
156+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
157+
run: |
158+
python - <<'PY'
159+
import io, os, tarfile, urllib.request
160+
from pathlib import Path
161+
req = urllib.request.Request(
162+
f"https://api.github.com/repos/{os.environ['GITHUB_REPOSITORY']}/tarball/{os.environ['GITHUB_SHA']}",
163+
headers={'Authorization': f"Bearer {os.environ['GITHUB_TOKEN']}", 'Accept': 'application/vnd.github+json'},
164+
)
165+
target = Path(os.environ['RUNNER_TEMP']) / 'reviewer-bot-src'
166+
target.mkdir(parents=True, exist_ok=True)
167+
with urllib.request.urlopen(req) as response:
168+
data = response.read()
169+
with tarfile.open(fileobj=io.BytesIO(data), mode='r:gz') as archive:
170+
archive.extractall(target)
171+
roots = list(target.iterdir())
172+
print(f'BOT_SRC_ROOT={roots[0]}', file=open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8'))
173+
PY
174+
- name: Run reviewer bot
175+
env:
176+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
177+
EVENT_NAME: issue_comment
178+
EVENT_ACTION: created
179+
ISSUE_NUMBER: ${{ github.event.issue.number }}
180+
ISSUE_AUTHOR: ${{ github.event.issue.user.login }}
181+
ISSUE_STATE: ${{ needs.route-pr-comment.outputs.issue_state }}
182+
ISSUE_LABELS: ${{ needs.route-pr-comment.outputs.issue_labels }}
183+
IS_PULL_REQUEST: 'true'
184+
COMMENT_BODY: ${{ github.event.comment.body }}
185+
COMMENT_AUTHOR: ${{ github.event.comment.user.login }}
186+
COMMENT_AUTHOR_ID: ${{ needs.route-pr-comment.outputs.comment_author_id }}
187+
COMMENT_ID: ${{ github.event.comment.id }}
188+
COMMENT_CREATED_AT: ${{ github.event.comment.created_at }}
189+
COMMENT_USER_TYPE: ${{ github.event.comment.user.type }}
190+
COMMENT_SENDER_TYPE: ${{ github.event.sender.type }}
191+
COMMENT_INSTALLATION_ID: ${{ github.event.installation.id }}
192+
COMMENT_PERFORMED_VIA_GITHUB_APP: ${{ github.event.comment.performed_via_github_app != null }}
193+
GITHUB_REPOSITORY: ${{ github.repository }}
194+
PR_HEAD_FULL_NAME: ${{ needs.route-pr-comment.outputs.pr_head_full_name }}
195+
PR_AUTHOR: ${{ needs.route-pr-comment.outputs.pr_author }}
196+
REVIEWER_BOT_ROUTE_OUTCOME: ${{ needs.route-pr-comment.outputs.route_outcome }}
197+
REVIEWER_BOT_TRUST_CLASS: ${{ needs.route-pr-comment.outputs.reviewer_bot_trust_class }}
198+
GITHUB_RUN_ID: ${{ github.run_id }}
199+
GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }}
200+
WORKFLOW_NAME: ${{ github.workflow }}
201+
WORKFLOW_JOB_NAME: ${{ github.job }}
202+
run: uv run --project "$BOT_SRC_ROOT" reviewer-bot

0 commit comments

Comments
 (0)