Skip to content

Commit bcabfb7

Browse files
vorporealoz-agent
andauthored
Unify PR creation codepaths for conflict/non-conflict syncs. (#20)
## Description Unifies the conflict and non-conflict codepaths in both `_sync_private_to_public` and `_sync_public_to_private`. Previously, a cherry-pick conflict caused the code to branch into a completely separate `_handle_cherry_pick_conflict` function that duplicated much of the standard flow (description building, trailer appending, push, PR creation). This made it easy for the two paths to drift — most recently, conflict PRs were getting `[CONFLICT]` prepended to their titles and losing their original PR descriptions. Now both functions follow a single linear flow with `is_conflict` conditionals at the points where behavior differs: 1. Cherry-pick → set `is_conflict` 2. Commit handling (raw conflict commit + resolution agent vs. amend) 3. Build PR description (shared, identical logic) 4. Append trailers (origin always; conflict trailer only if conflict) 5. Push + create PR 6. Post-creation conflict steps if needed (label, reviewer, comment, slack) Other changes: - Conflict PRs no longer get `[CONFLICT]` prepended to their title. - Conflict PRs now preserve the original description (source PR body or agent-generated) instead of replacing it with a generic conflict message. - A comment is posted on conflict PRs noting the reviewer assignment, rather than baking that info into the PR body. - Added `GhOps.add_pr_comment()` method. ## Testing All 251 existing tests pass. Verified via manual inspection of a conflict sync PR (warpdotdev/warp-internal#24195). Co-Authored-By: Oz <oz-agent@warp.dev>
1 parent 46eaa04 commit bcabfb7

3 files changed

Lines changed: 246 additions & 147 deletions

File tree

generate_jwt.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env bash
2+
3+
client_id=$1 # Client ID as first argument
4+
5+
pem=$( cat $2 ) # file path of the private key as second argument
6+
7+
now=$(date +%s)
8+
iat=$((${now} - 60)) # Issues 60 seconds in the past
9+
exp=$((${now} + 600)) # Expires 10 minutes in the future
10+
11+
b64enc() { openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n'; }
12+
13+
header_json='{
14+
"typ":"JWT",
15+
"alg":"RS256"
16+
}'
17+
# Header encode
18+
header=$( echo -n "${header_json}" | b64enc )
19+
20+
payload_json="{
21+
\"iat\":${iat},
22+
\"exp\":${exp},
23+
\"iss\":\"${client_id}\"
24+
}"
25+
# Payload encode
26+
payload=$( echo -n "${payload_json}" | b64enc )
27+
28+
# Signature
29+
header_payload="${header}"."${payload}"
30+
signature=$(
31+
openssl dgst -sha256 -sign <(echo -n "${pem}") \
32+
<(echo -n "${header_payload}") | b64enc
33+
)
34+
35+
# Create JWT
36+
JWT="${header_payload}"."${signature}"
37+
printf '%s' "$JWT"

src/repo_sync/stack/gh_ops.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,20 @@ def update_pr_body(self, pr_number: int, body: str) -> None:
247247
finally:
248248
os.unlink(body_file)
249249

250+
def add_pr_comment(self, pr_number: int, body: str) -> None:
251+
"""Add a comment to a PR."""
252+
self._run(
253+
[
254+
"pr",
255+
"comment",
256+
str(pr_number),
257+
"--repo",
258+
self.repo,
259+
"--body",
260+
body,
261+
]
262+
)
263+
250264
def request_reviewer(
251265
self, pr_number: int, reviewer: str
252266
) -> None:

0 commit comments

Comments
 (0)