[Agent] π Bounty T1: Mobile Responsive Audit & Fixes #1672
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: AI Code Review | |
| on: | |
| pull_request_target: | |
| types: [opened, synchronize] | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: 'PR number to review' | |
| required: true | |
| type: string | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: read | |
| jobs: | |
| ai-review: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout base repo (safe β never runs PR code) | |
| uses: actions/checkout@v4 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Install dependencies | |
| run: pip install openai requests | |
| - name: Resolve PR number | |
| id: pr | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # Use workflow_dispatch input if available, else pull_request_target event | |
| if [ -n "${{ inputs.pr_number }}" ]; then | |
| PR_NUM="${{ inputs.pr_number }}" | |
| else | |
| PR_NUM="${{ github.event.pull_request.number }}" | |
| fi | |
| echo "number=$PR_NUM" >> $GITHUB_OUTPUT | |
| # Get full PR details for workflow_dispatch case | |
| PR_JSON=$(gh pr view $PR_NUM --repo ${{ github.repository }} --json title,author,url,body 2>/dev/null || echo '{}') | |
| echo "title=$(echo "$PR_JSON" | python3 -c 'import sys,json; print(json.loads(sys.stdin.read()).get("title","Unknown"))' 2>/dev/null)" >> $GITHUB_OUTPUT | |
| echo "author=$(echo "$PR_JSON" | python3 -c 'import sys,json; print(json.loads(sys.stdin.read()).get("author",{}).get("login","unknown"))' 2>/dev/null)" >> $GITHUB_OUTPUT | |
| echo "url=$(echo "$PR_JSON" | python3 -c 'import sys,json; print(json.loads(sys.stdin.read()).get("url",""))' 2>/dev/null)" >> $GITHUB_OUTPUT | |
| # Write body to file to avoid shell escaping issues | |
| echo "$PR_JSON" | python3 -c 'import sys,json; print(json.loads(sys.stdin.read()).get("body",""))' > /tmp/pr_body.txt 2>/dev/null | |
| - name: Get PR diff | |
| id: diff | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh pr diff ${{ steps.pr.outputs.number }} --repo ${{ github.repository }} > /tmp/pr_diff.txt | |
| echo "diff_size=$(wc -c < /tmp/pr_diff.txt)" >> $GITHUB_OUTPUT | |
| - name: Get bounty context and submission order | |
| id: bounty | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # Read PR body from file (handles both triggers) | |
| if [ -f /tmp/pr_body.txt ]; then | |
| PR_BODY=$(cat /tmp/pr_body.txt) | |
| else | |
| PR_BODY="${{ github.event.pull_request.body }}" | |
| fi | |
| REPO="${{ github.repository }}" | |
| # Extract linked issue number from PR body (Closes #N) | |
| ISSUE_NUM=$(echo "$PR_BODY" | grep -ioP '(?:closes|fixes|resolves)\s+#\K\d+' | head -1) | |
| if [ -n "$ISSUE_NUM" ]; then | |
| echo "issue_num=$ISSUE_NUM" >> $GITHUB_OUTPUT | |
| # Get issue details | |
| ISSUE_JSON=$(gh api repos/$REPO/issues/$ISSUE_NUM 2>/dev/null || echo '{}') | |
| ISSUE_TITLE=$(echo "$ISSUE_JSON" | python3 -c "import sys,json; print(json.loads(sys.stdin.read()).get('title','Unknown'))" 2>/dev/null) | |
| # Get tier from labels | |
| TIER=$(echo "$ISSUE_JSON" | python3 -c " | |
| import sys,json | |
| data=json.loads(sys.stdin.read()) | |
| labels=[l['name'] for l in data.get('labels',[])] | |
| tier=next((l for l in labels if l.startswith('tier-')),'unknown') | |
| print(tier) | |
| " 2>/dev/null) | |
| # Extract reward amount | |
| REWARD=$(echo "$ISSUE_JSON" | python3 -c " | |
| import sys,json,re | |
| data=json.loads(sys.stdin.read()) | |
| text=(data.get('title','') or '') + ' ' + (data.get('body','') or '') | |
| m=re.search(r'(\d+)\s*\\\$?FNDRY', text) | |
| print(m.group(1) if m else '0') | |
| " 2>/dev/null) | |
| echo "issue_title=$ISSUE_TITLE" >> $GITHUB_OUTPUT | |
| echo "tier=$TIER" >> $GITHUB_OUTPUT | |
| echo "reward=$REWARD" >> $GITHUB_OUTPUT | |
| # Count how many PRs target this issue (submission order) | |
| ALL_PRS=$(gh pr list --repo $REPO --state all --limit 50 --json number,body 2>/dev/null) | |
| ORDER=$(echo "$ALL_PRS" | python3 -c " | |
| import sys,json,re | |
| prs=json.loads(sys.stdin.read()) | |
| count=0 | |
| for pr in prs: | |
| body=(pr.get('body','') or '').lower() | |
| if re.search(r'(?:closes|fixes|resolves)\s+#$ISSUE_NUM', body): | |
| count+=1 | |
| print(count) | |
| " 2>/dev/null) | |
| echo "submission_order=$ORDER" >> $GITHUB_OUTPUT | |
| else | |
| echo "issue_num=" >> $GITHUB_OUTPUT | |
| echo "tier=unknown" >> $GITHUB_OUTPUT | |
| echo "reward=0" >> $GITHUB_OUTPUT | |
| echo "submission_order=0" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Multi-LLM Review (GPT-5.4 + Gemini 2.5 Pro + Grok 4) | |
| env: | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} | |
| XAI_API_KEY: ${{ secrets.XAI_API_KEY }} | |
| SOLFOUNDRY_TELEGRAM_BOT_TOKEN: ${{ secrets.SOLFOUNDRY_TELEGRAM_BOT_TOKEN }} | |
| SOLFOUNDRY_TELEGRAM_CHAT_ID: ${{ secrets.SOLFOUNDRY_TELEGRAM_CHAT_ID }} | |
| PR_NUMBER: ${{ steps.pr.outputs.number }} | |
| PR_TITLE: ${{ steps.pr.outputs.title || github.event.pull_request.title }} | |
| PR_AUTHOR: ${{ steps.pr.outputs.author || github.event.pull_request.user.login }} | |
| PR_URL: ${{ steps.pr.outputs.url || github.event.pull_request.html_url }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| BOUNTY_ISSUE: ${{ steps.bounty.outputs.issue_num }} | |
| BOUNTY_TITLE: ${{ steps.bounty.outputs.issue_title }} | |
| BOUNTY_TIER: ${{ steps.bounty.outputs.tier }} | |
| BOUNTY_REWARD: ${{ steps.bounty.outputs.reward }} | |
| SUBMISSION_ORDER: ${{ steps.bounty.outputs.submission_order }} | |
| run: | | |
| # Load PR body from file to avoid shell escaping | |
| export PR_BODY="$(cat /tmp/pr_body.txt 2>/dev/null || echo '${{ github.event.pull_request.body }}')" | |
| python3 .github/scripts/ai_review.py |