Skip to content

Commit 8b32b3b

Browse files
authored
DF PR Review workflow (#13687)
### Motivation and Context DF Automated PR review workflow. <!-- Thank you for your contribution to the semantic-kernel repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone 😄
1 parent 30aec16 commit 8b32b3b

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
name: DevFlow PR Review
2+
3+
on:
4+
pull_request_target:
5+
types:
6+
- opened
7+
- reopened
8+
- ready_for_review
9+
workflow_dispatch:
10+
inputs:
11+
pr_url:
12+
description: Pull request URL to review
13+
required: true
14+
type: string
15+
16+
permissions:
17+
contents: read
18+
issues: write
19+
pull-requests: write
20+
21+
concurrency:
22+
group: devflow-pr-review-${{ github.repository }}-${{ github.event.pull_request.number || github.run_id }}
23+
cancel-in-progress: true
24+
25+
env:
26+
DEVFLOW_REPOSITORY: ${{ vars.DF_REPO }}
27+
DEVFLOW_REF: main
28+
TARGET_REPO_PATH: ${{ github.workspace }}/target-repo
29+
DEVFLOW_PATH: ${{ github.workspace }}/devflow
30+
31+
jobs:
32+
review:
33+
runs-on: ubuntu-latest
34+
timeout-minutes: 60
35+
if: ${{ github.event_name != 'pull_request_target' || !github.event.pull_request.draft }}
36+
37+
steps:
38+
- name: Resolve PR metadata
39+
id: pr
40+
shell: bash
41+
env:
42+
PR_HTML_URL: ${{ github.event.pull_request.html_url }}
43+
PR_NUMBER: ${{ github.event.pull_request.number }}
44+
PR_URL_INPUT: ${{ inputs.pr_url }}
45+
run: |
46+
set -euo pipefail
47+
48+
if [[ "${GITHUB_EVENT_NAME}" == "pull_request_target" ]]; then
49+
echo "pr_url=${PR_HTML_URL}" >> "$GITHUB_OUTPUT"
50+
echo "pr_number=${PR_NUMBER}" >> "$GITHUB_OUTPUT"
51+
echo "repo=${GITHUB_REPOSITORY}" >> "$GITHUB_OUTPUT"
52+
exit 0
53+
fi
54+
55+
if [[ -z "$PR_URL_INPUT" ]]; then
56+
echo "workflow_dispatch requires pr_url" >&2
57+
exit 1
58+
fi
59+
60+
if [[ ! "$PR_URL_INPUT" =~ ^https://github\.com/([^/]+/[^/]+)/pull/([0-9]+)([/?].*)?$ ]]; then
61+
echo "Could not parse pull request URL (expected https://github.com/<owner>/<repo>/pull/<number>): $PR_URL_INPUT" >&2
62+
exit 1
63+
fi
64+
65+
pr_repo="${BASH_REMATCH[1]}"
66+
pr_number="${BASH_REMATCH[2]}"
67+
68+
if [[ "$pr_repo" != "$GITHUB_REPOSITORY" ]]; then
69+
echo "PR URL repository ($pr_repo) does not match current repository ($GITHUB_REPOSITORY)" >&2
70+
exit 1
71+
fi
72+
73+
echo "pr_url=${PR_URL_INPUT}" >> "$GITHUB_OUTPUT"
74+
echo "pr_number=${pr_number}" >> "$GITHUB_OUTPUT"
75+
echo "repo=${pr_repo}" >> "$GITHUB_OUTPUT"
76+
77+
# Safe checkout: base repo only, not the untrusted PR head.
78+
- name: Checkout target repo base
79+
uses: actions/checkout@v5
80+
with:
81+
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.base.sha || github.sha }}
82+
fetch-depth: 0
83+
persist-credentials: false
84+
path: target-repo
85+
86+
# Private DevFlow checkout: the PAT/token grants access to this repo's code.
87+
- name: Checkout DevFlow
88+
uses: actions/checkout@v5
89+
with:
90+
repository: ${{ env.DEVFLOW_REPOSITORY }}
91+
ref: ${{ env.DEVFLOW_REF }}
92+
token: ${{ secrets.DEVFLOW_TOKEN }}
93+
fetch-depth: 1
94+
persist-credentials: false
95+
path: devflow
96+
97+
- name: Set up Python
98+
uses: actions/setup-python@v5
99+
with:
100+
python-version: "3.13"
101+
102+
- name: Set up uv
103+
uses: astral-sh/setup-uv@v6
104+
with:
105+
version: "0.5.x"
106+
enable-cache: true
107+
108+
- name: Install DevFlow dependencies
109+
working-directory: ${{ env.DEVFLOW_PATH }}
110+
run: uv sync --frozen
111+
112+
- name: Classify PR relevance
113+
id: spam
114+
working-directory: ${{ env.DEVFLOW_PATH }}
115+
env:
116+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
117+
GH_COPILOT_TOKEN: ${{ secrets.GH_COPILOT_TOKEN }}
118+
SK_REPO_PATH: ${{ env.TARGET_REPO_PATH }}
119+
AGENT_REPO_PATH: ${{ env.TARGET_REPO_PATH }}
120+
PR_REPO: ${{ steps.pr.outputs.repo }}
121+
PR_NUMBER: ${{ steps.pr.outputs.pr_number }}
122+
run: |
123+
uv run python scripts/classify_pr_spam.py \
124+
--repo "$PR_REPO" \
125+
--pr-number "$PR_NUMBER" \
126+
--repo-path "${TARGET_REPO_PATH}" \
127+
--apply-labels
128+
129+
- name: Stop after spam gate
130+
if: ${{ steps.spam.outputs.decision != 'allow' }}
131+
shell: bash
132+
env:
133+
SPAM_DECISION: ${{ steps.spam.outputs.decision }}
134+
run: |
135+
echo "Skipping review because spam gate decided: ${SPAM_DECISION}"
136+
137+
- name: Run PR review
138+
if: ${{ steps.spam.outputs.decision == 'allow' }}
139+
id: review
140+
working-directory: ${{ env.DEVFLOW_PATH }}
141+
env:
142+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
143+
GH_COPILOT_TOKEN: ${{ secrets.GH_COPILOT_TOKEN }}
144+
SK_REPO_PATH: ${{ env.TARGET_REPO_PATH }}
145+
AGENT_REPO_PATH: ${{ env.TARGET_REPO_PATH }}
146+
PR_URL: ${{ steps.pr.outputs.pr_url }}
147+
run: |
148+
uv run python scripts/trigger_pr_review.py \
149+
--pr-url "$PR_URL" \
150+
--github-username "$GITHUB_ACTOR" \
151+
--no-require-comment-selection

0 commit comments

Comments
 (0)