Implement full stack admin dashboard #1311
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: Bounty Tracker | |
| on: | |
| pull_request: | |
| types: [closed] | |
| issues: | |
| types: [closed, labeled] | |
| permissions: | |
| contents: read | |
| issues: write | |
| pull-requests: write | |
| jobs: | |
| track-bounty: | |
| if: github.event.pull_request.merged == true || github.event_name == 'issues' | |
| runs-on: ubuntu-latest | |
| concurrency: | |
| group: bounty-tracker-${{ github.event.pull_request.number || github.event.issue.number }} | |
| steps: | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Install dependencies | |
| run: pip install requests | |
| - name: Track Bounty | |
| env: | |
| TELEGRAM_BOT_TOKEN: ${{ secrets.SOLFOUNDRY_TELEGRAM_BOT_TOKEN }} | |
| TELEGRAM_CHAT_ID: ${{ secrets.SOLFOUNDRY_TELEGRAM_CHAT_ID }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| PR_TITLE: ${{ github.event.pull_request.title }} | |
| PR_AUTHOR: ${{ github.event.pull_request.user.login }} | |
| PR_URL: ${{ github.event.pull_request.html_url }} | |
| PR_BODY: ${{ github.event.pull_request.body }} | |
| ISSUE_NUMBER: ${{ github.event.issue.number }} | |
| ISSUE_TITLE: ${{ github.event.issue.title }} | |
| ISSUE_BODY: ${{ github.event.issue.body }} | |
| run: | | |
| python3 << 'PYEOF' | |
| import os, re, requests, json | |
| def send_telegram(msg, reply_markup=None): | |
| token = os.environ.get("TELEGRAM_BOT_TOKEN") | |
| chat_id = os.environ.get("TELEGRAM_CHAT_ID") | |
| if not token or not chat_id: | |
| print("Telegram not configured") | |
| return | |
| payload = { | |
| "chat_id": chat_id, | |
| "text": msg, | |
| "parse_mode": "HTML", | |
| "disable_web_page_preview": True | |
| } | |
| if reply_markup: | |
| payload["reply_markup"] = json.dumps(reply_markup) | |
| requests.post( | |
| f"https://api.telegram.org/bot{token}/sendMessage", | |
| json=payload | |
| ) | |
| def gh_api_get(path): | |
| token = os.environ.get("GH_TOKEN", "") | |
| resp = requests.get( | |
| f"https://api.github.com/{path}", | |
| headers={"Authorization": f"token {token}", "Accept": "application/vnd.github.v3+json"} | |
| ) | |
| return resp.json() if resp.ok else None | |
| event = os.environ["EVENT_NAME"] | |
| if event == "pull_request": | |
| # PR was merged — check if it closes a bounty issue | |
| pr_body = os.environ.get("PR_BODY", "") | |
| pr_title = os.environ.get("PR_TITLE", "") | |
| pr_author = os.environ.get("PR_AUTHOR", "") | |
| pr_number = os.environ.get("PR_NUMBER", "") | |
| pr_url = os.environ.get("PR_URL", "") | |
| repo = os.environ.get("GITHUB_REPOSITORY", "SolFoundry/solfoundry") | |
| # Dedup check: skip if we already sent a bounty-tracked comment on this PR | |
| comments = gh_api_get(f"repos/{repo}/issues/{pr_number}/comments?per_page=50") | |
| if comments: | |
| already_tracked = any( | |
| "Bounty tracked" in (c.get("body", "") or "") or | |
| "bounty-tracked" in (c.get("body", "") or "") | |
| for c in comments if isinstance(c, dict) | |
| ) | |
| if already_tracked: | |
| print(f"PR #{pr_number}: already tracked, skipping duplicate") | |
| exit(0) | |
| # Find "Closes #N" patterns | |
| closes = re.findall(r'(?:closes|fixes|resolves)\s+#(\d+)', pr_body.lower()) | |
| keyboard = {"inline_keyboard": [[{"text": "\U0001f440 View PR", "url": pr_url}]]} | |
| if closes: | |
| issue_nums = ", ".join(f"#{n}" for n in closes) | |
| msg = ( | |
| f"\U0001f389 <b>Bounty PR Merged!</b>\n\n" | |
| f"PR #{pr_number}: {pr_title}\n" | |
| f"by @{pr_author}\n" | |
| f"Closes: {issue_nums}\n\n" | |
| f"\U0001f4b0 Review payout eligibility and send $FNDRY" | |
| ) | |
| send_telegram(msg, reply_markup=keyboard) | |
| else: | |
| msg = ( | |
| f"\u2705 <b>PR Merged</b>\n\n" | |
| f"PR #{pr_number}: {pr_title}\n" | |
| f"by @{pr_author}" | |
| ) | |
| send_telegram(msg, reply_markup=keyboard) | |
| # ── Auto-close competing PRs for the same bounty ── | |
| if event == "pull_request" and closes: | |
| import urllib.request | |
| gh_token = os.environ.get("GH_TOKEN", "") | |
| for issue_num in closes: | |
| # Find all OTHER open PRs targeting the same issue | |
| try: | |
| req = urllib.request.Request( | |
| f"https://api.github.com/repos/{repo}/pulls?state=open&per_page=100", | |
| headers={"Authorization": f"token {gh_token}", "Accept": "application/vnd.github.v3+json"} | |
| ) | |
| resp = urllib.request.urlopen(req, timeout=15) | |
| open_prs = json.loads(resp.read().decode()) | |
| for opr in open_prs: | |
| opr_num = opr["number"] | |
| if str(opr_num) == str(pr_number): | |
| continue # Skip the merged PR itself | |
| opr_body = (opr.get("body", "") or "").lower() | |
| opr_author = opr.get("user", {}).get("login", "unknown") | |
| # Check if this PR targets the same issue | |
| opr_closes = re.findall(r'(?:closes|fixes|resolves)\s+#(\d+)', opr_body) | |
| if issue_num in opr_closes: | |
| # Close competing PR with explanation | |
| close_body = json.dumps({ | |
| "body": ( | |
| f"🏭 **Bounty #{issue_num} completed** — PR #{pr_number} by @{pr_author} was merged first.\n\n" | |
| f"Thank you for your submission @{opr_author}! " | |
| f"Check out the other [open bounties](https://github.com/{repo}/issues?q=is%3Aissue+is%3Aopen+label%3Abounty) for more opportunities.\n\n" | |
| f"---\n*SolFoundry Bot 🏭*" | |
| ) | |
| }).encode() | |
| comment_req = urllib.request.Request( | |
| f"https://api.github.com/repos/{repo}/issues/{opr_num}/comments", | |
| data=close_body, method="POST", | |
| headers={"Authorization": f"token {gh_token}", "Accept": "application/vnd.github.v3+json", "Content-Type": "application/json"} | |
| ) | |
| urllib.request.urlopen(comment_req, timeout=15) | |
| close_data = json.dumps({"state": "closed"}).encode() | |
| close_req = urllib.request.Request( | |
| f"https://api.github.com/repos/{repo}/pulls/{opr_num}", | |
| data=close_data, method="PATCH", | |
| headers={"Authorization": f"token {gh_token}", "Accept": "application/vnd.github.v3+json", "Content-Type": "application/json"} | |
| ) | |
| urllib.request.urlopen(close_req, timeout=15) | |
| print(f"Auto-closed competing PR #{opr_num} by @{opr_author} (bounty #{issue_num} already won)") | |
| except Exception as e: | |
| print(f"Error auto-closing competing PRs for #{issue_num}: {e}") | |
| print("Bounty tracking complete") | |
| PYEOF |