Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"enabledPlugins": {
"playground@claude-plugins-official": true
}
}
134 changes: 134 additions & 0 deletions .github/workflows/pr-diagram.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
name: PR Diagram

# Generates a Mermaid architecture diagram for the PR description when the
# `needs-diagram` label is applied. Label-only (one-shot): remove and re-add
# the label to refresh after new commits.

on:
pull_request:
types: [labeled]

permissions:
contents: read
pull-requests: write

concurrency:
group: pr-diagram-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
diagram:
if: github.event.label.name == 'needs-diagram'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
Comment on lines +7 to +25

- name: Fetch PR diff
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR: ${{ github.event.pull_request.number }}
run: |
gh pr diff "$PR" > /tmp/pr.diff
Comment on lines +24 to +32
SIZE=$(wc -c < /tmp/pr.diff)
MAX=200000
if [ "$SIZE" -gt "$MAX" ]; then
head -c "$MAX" /tmp/pr.diff > /tmp/pr.diff.trim
mv /tmp/pr.diff.trim /tmp/pr.diff
echo "TRUNCATED=true" >> "$GITHUB_ENV"
fi

- name: Generate Mermaid diagram
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plan to switch to Anthropic WIF auth, see this for example: https://github.com/stellar/internal-agents/blob/20ebd49e46ed2a4473a653e27de9b57cd3e8a024/.github/workflows/bug-finder.yml#L48-L56

Don't block on this though, we should just come back and generate a WIF auth setup for this repo to replace the key usage.

run: |
python3 - <<'PY'
import json, os, urllib.request, urllib.error, sys

with open('/tmp/pr.diff') as f:
diff = f.read()

system = (
"You are reviewing a pull request diff and producing ONE Mermaid "
"diagram for the PR description. Auto-pick the best diagram type "
"for what changed: sequenceDiagram for new flows or signing/submit "
"paths, flowchart for branching logic, classDiagram for new modules "
"or types, graph for component/import structure. Keep it under 30 "
"nodes. Be specific to this diff — do not produce a generic template. "
"Respond with ONLY a fenced ```mermaid``` block, no prose before or after."
)

payload = {
"model": "claude-sonnet-4-6",
"max_tokens": 4096,
"system": system,
"messages": [{
"role": "user",
"content": (
"Generate a Mermaid diagram summarizing the architectural "
"changes in this PR diff:\n\n" + diff
),
Comment on lines +61 to +70
}],
}

req = urllib.request.Request(
"https://api.anthropic.com/v1/messages",
data=json.dumps(payload).encode("utf-8"),
headers={
"x-api-key": os.environ["ANTHROPIC_API_KEY"],
"anthropic-version": "2023-06-01",
"content-type": "application/json",
},
)

try:
with urllib.request.urlopen(req, timeout=120) as resp:
data = json.load(resp)
except urllib.error.HTTPError as e:
print("API error:", e.code, e.read().decode("utf-8"), file=sys.stderr)
sys.exit(1)

text = data["content"][0]["text"].strip()
with open('/tmp/mermaid.md', 'w') as f:
f.write(text)
PY

- name: Update PR body
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR: ${{ github.event.pull_request.number }}
run: |
gh pr view "$PR" --json body -q '.body // ""' > /tmp/body.md

python3 - <<'PY'
import os, re

with open('/tmp/body.md') as f:
body = f.read()
with open('/tmp/mermaid.md') as f:
mermaid = f.read().strip()

# Extract the fenced mermaid block in case the model wrapped it in prose.
match = re.search(r'```mermaid.*?```', mermaid, re.DOTALL)
if match:
mermaid = match.group(0)

Comment on lines +111 to +115
trunc = os.environ.get('TRUNCATED') == 'true'
note = '\n\n_Note: diff was truncated to fit context; diagram covers the first ~200KB of changes._' if trunc else ''
block = f"\n\n<!-- pr-diagram:start -->\n## Architecture diagram\n\n{mermaid}{note}\n<!-- pr-diagram:end -->"

if '<!-- pr-diagram:start -->' in body:
body = re.sub(
r'\n*<!-- pr-diagram:start -->.*?<!-- pr-diagram:end -->\n*',
block,
body,
flags=re.DOTALL,
)
else:
body = body.rstrip() + block

with open('/tmp/new_body.md', 'w') as f:
f.write(body)
PY

gh pr edit "$PR" --body-file /tmp/new_body.md
Loading