BLT icon indicating copy to clipboard operation
BLT copied to clipboard

Create a badge that gets auto added to the issue when it is created (Use BLT-Action)

Open DonnieBLT opened this issue 9 months ago β€’ 7 comments

Show: activity / view count for the past 30 days for the issue by reading the logs of IP( for the badge image url have the github action edit the description to insert it show the current bounty amount read from GithubIssues

DonnieBLT avatar Mar 11 '25 17:03 DonnieBLT

/assign

nipunh avatar Mar 13 '25 21:03 nipunh

Hello @nipunh! You've been assigned to OWASP-BLT/BLT issue #3917. You have 24 hours to complete a pull request.

github-actions[bot] avatar Mar 13 '25 21:03 github-actions[bot]

⏰ This issue has been automatically unassigned due to 24 hours of inactivity. The issue is now available for anyone to work on again.

github-actions[bot] avatar Mar 15 '25 00:03 github-actions[bot]

/assign

HarshitVashisht11 avatar Mar 24 '25 13:03 HarshitVashisht11

Hello @HarshitVashisht11! You've been assigned to OWASP-BLT/BLT issue #3917. You have 24 hours to complete a pull request.

github-actions[bot] avatar Mar 24 '25 13:03 github-actions[bot]

[!TIP] For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's look at the issue to understand the requirements better
gh issue view 3917 --repo OWASP-BLT/BLT

# Let's also check if there's a BLT-Action repository or file
fd -t f "BLT-Action" -d 3

# Let's see what GitHub actions are currently in the repository
fd -t f "\.ya?ml" .github/workflows/ -d 3

# Let's get a basic understanding of the repository structure
find . -maxdepth 2 -type d | sort

# Check the README to understand the project better
cat README.md || echo "README.md not found"

Length of output: 2680


🏁 Script executed:

#!/bin/bash
# Let's check the existing badge implementation 
fd -t f "badge" -d 5 | grep -v node_modules

# Let's look at the existing GitHub workflows for issue management
cat .github/workflows/enforce-issue-number-in-description.yml
cat .github/workflows/assign-issues.yml

# Check for existing implementation related to issue stats or bounty tracking
rg "bounty" -t py --max-count=1 -l

# Let's check website views or activity tracking implementations
rg "views" -t py --max-count=1 -l

# Additional repository information to understand the context better
cat website/models.py

Length of output: 71216


@HarshitVashisht11 I'd be happy to explain this PR objective.

This PR is about creating a badge that automatically gets added to GitHub issues when they're created. The badge should display:

  1. Activity/view count for the past 30 days - This would track how many times an issue has been viewed by reading the IP logs from the IP model.

  2. Current bounty amount - This would display the bounty amount associated with the issue from the GithubIssues model.

The implementation would require:

  1. Extending the existing badge functionality (visible in the README where it uses https://blt.owasp.org/repos/blt/badge/)

  2. Modifying the BLT-Action (defined in .github/workflows/assign-issues.yml) to:

    • Generate a unique badge URL for each issue
    • Edit the issue description to insert this badge
  3. Creating or updating an endpoint that reads the IP logs and bounty information to generate the dynamic badge with the required statistics.

Would you like me to provide more specific implementation details about any part of this?

coderabbitai[bot] avatar Mar 24 '25 15:03 coderabbitai[bot]

⏰ This issue has been automatically unassigned due to 24 hours of inactivity. The issue is now available for anyone to work on again.

github-actions[bot] avatar Mar 25 '25 17:03 github-actions[bot]

/assign

ghost avatar Apr 04 '25 16:04 ghost

Hello @thedvlprguy! You've been assigned to OWASP-BLT/BLT issue #3917. You have 24 hours to complete a pull request.

github-actions[bot] avatar Apr 04 '25 16:04 github-actions[bot]

/coderabbit summary for this, like what the task actually is

ghost avatar Apr 04 '25 16:04 ghost

⏰ This issue has been automatically unassigned due to 24 hours of inactivity. The issue is now available for anyone to work on again.

github-actions[bot] avatar Apr 05 '25 18:04 github-actions[bot]

@coderabbitai is this issue resolved

razzasid avatar May 16 '25 04:05 razzasid

[!TIP] For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if issue #3917 is open or closed
echo "Checking status of issue #3917..."
gh issue view 3917 --repo OWASP-BLT/BLT --json state,title,body,closed

# Look for PRs that might have addressed this issue
echo -e "\nChecking for PRs that reference issue #3917..."
gh pr list --repo OWASP-BLT/BLT --search "#3917" --json number,title,state,url,mergedAt

# Additionally, check closed PRs in case they didn't explicitly mention the issue number
echo -e "\nChecking for recently closed PRs that might relate to badges..."
gh pr list --repo OWASP-BLT/BLT --state closed --limit 10 --json number,title,state,url,mergedAt | grep -i "badge\|activity\|bounty" -A 3 -B 3 || echo "No recent PRs matching badge keywords"

Length of output: 2655


@razzasid No, this issue is not resolved. I just checked the GitHub repository and found that issue #3917 ("Create a badge that gets auto added to the issue when it is created") is still open. There are no pull requests that reference this issue, and while there was a recent PR related to badges (#4219), it was about replacing suggestion badges with forum badges, which is different from what this issue is requesting.

The issue remains available for someone to implement the requested feature of automatically adding badges showing activity/view count and bounty amounts to GitHub issues.

coderabbitai[bot] avatar May 16 '25 04:05 coderabbitai[bot]

@coderabbitai what's the issue, and how can we solve it? Please guide me step by step to resolve this issue.

razzasid avatar May 27 '25 11:05 razzasid

[!TIP] For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the full issue details to understand exact requirements
echo "=== Issue #3917 Details ==="
gh issue view 3917 --repo OWASP-BLT/BLT

echo -e "\n=== Current Badge Implementation ==="
# Look for badge-related files and endpoints
rg "badge" -t py -A 3 -B 1

echo -e "\n=== GitHub Actions for Issue Management ==="
# Check the assign-issues workflow which was mentioned as BLT-Action
cat .github/workflows/assign-issues.yml

echo -e "\n=== IP Model for Activity Tracking ==="
# Find IP model definition for tracking views
rg "class IP" -t py -A 10

echo -e "\n=== GithubIssues Model for Bounty ==="
# Find GithubIssues model for bounty information
rg "class GithubIssues" -t py -A 10

echo -e "\n=== Current Badge URL Structure ==="
# Look for existing badge URL patterns
rg "badge/" -t py -A 2 -B 2

Length of output: 56059


🏁 Script executed:

#!/bin/bash
# Search for GithubIssues model more specifically
echo "=== Finding GithubIssues Model ==="
rg "GithubIssues" -t py -A 5 -B 2

echo -e "\n=== Looking for bounty-related models ==="
rg "bounty" -t py -A 3 -B 1

echo -e "\n=== Current Badge View Implementations ==="
# Find the badge view classes
rg "class.*Badge.*View" -t py -A 10

echo -e "\n=== Badge view files ==="
fd "badge" -t f -e py

echo -e "\n=== Current issue-related models ==="
rg "class.*Issue" -t py -A 5

Length of output: 18432


@razzasid Based on my analysis of the codebase, here's what issue #3917 requires and a complete step-by-step solution:

What the Issue Is About

Issue #3917 wants to create auto-generated badges that show up on GitHub issues with:

  1. Activity/view count for the past 30 days (tracked via IP logs)
  2. Current bounty amount (extracted from issue labels containing $)
  3. Automatic insertion into issue descriptions using the BLT-Action workflow

Step-by-Step Implementation Guide

Step 1: Create GitHub Issue Badge View

Create a new badge endpoint similar to existing ProjectBadgeView and RepoBadgeView:

# Add to website/views/project.py

class GitHubIssueBadgeView(APIView):
    def get_client_ip(self, request):
        # Reuse existing IP detection logic
        x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
        if x_forwarded_for:
            ip = x_forwarded_for.split(",")[0].strip()
            return ip
        x_real_ip = request.META.get("HTTP_X_REAL_IP")
        if x_real_ip:
            return x_real_ip
        return request.META.get("REMOTE_ADDR")

    def get_bounty_amount(self, issue_number):
        """Extract bounty amount from GitHub issue labels"""
        try:
            # Try to find existing GitHubIssue record first
            github_issue = GitHubIssue.objects.filter(
                issue_number=issue_number,
                p2p_amount_usd__isnull=False
            ).first()
            
            if github_issue:
                return f"${github_issue.p2p_amount_usd}"
            
            # If not found, fetch from GitHub API and parse labels
            from django.conf import settings
            import requests
            
            url = f"https://api.github.com/repos/{settings.GITHUB_REPO}/issues/{issue_number}"
            headers = {"Authorization": f"token {settings.GITHUB_TOKEN}"}
            
            response = requests.get(url, headers=headers)
            if response.status_code == 200:
                issue_data = response.json()
                for label in issue_data.get("labels", []):
                    label_name = label.get("name", "")
                    if "$" in label_name:
                        # Extract number from label like "$5", "$10", etc.
                        import re
                        amount_match = re.search(r'\$(\d+)', label_name)
                        if amount_match:
                            return f"${amount_match.group(1)}"
            
            return "$0"
        except Exception:
            return "$0"

    def get_activity_count(self, issue_number):
        """Get view count for the issue in past 30 days"""
        from django.utils import timezone
        from datetime import timedelta
        
        thirty_days_ago = timezone.now() - timedelta(days=30)
        
        # Count IP visits to this issue's path
        issue_path_patterns = [
            f"/issues/{issue_number}",
            f"/issues/{issue_number}/",
            f"github.com/OWASP-BLT/BLT/issues/{issue_number}"
        ]
        
        total_count = 0
        for pattern in issue_path_patterns:
            count = IP.objects.filter(
                path__contains=pattern,
                created__gte=thirty_days_ago
            ).aggregate(total=models.Sum('count'))['total'] or 0
            total_count += count
        
        return total_count

    def generate_badge_svg(self, activity_count, bounty_amount):
        """Generate SVG badge with activity count and bounty amount"""
        svg_template = '''
        <svg xmlns="http://www.w3.org/2000/svg" width="180" height="20">
            <linearGradient id="b" x2="0" y2="100%">
                <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
                <stop offset="1" stop-opacity=".1"/>
            </linearGradient>
            <clipPath id="a">
                <rect width="180" height="20" rx="3" fill="#fff"/>
            </clipPath>
            <g clip-path="url(#a)">
                <path fill="#555" d="M0 0h63v20H0z"/>
                <path fill="#4c1" d="M63 0h117v20H63z"/>
                <path fill="url(#b)" d="M0 0h180v20H0z"/>
            </g>
            <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
                <text x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Activity</text>
                <text x="325" y="140" transform="scale(.1)" textLength="530">Activity</text>
                <text x="1205" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="1070">{activity_count} views | {bounty_amount}</text>
                <text x="1205" y="140" transform="scale(.1)" textLength="1070">{activity_count} views | {bounty_amount}</text>
            </g>
        </svg>
        '''.format(activity_count=activity_count, bounty_amount=bounty_amount)
        
        return svg_template.strip()

    def get(self, request, issue_number):
        # Track this badge view
        client_ip = self.get_client_ip(request)
        badge_path = f"/issues/{issue_number}/badge/"
        
        # Log the badge view
        IP.objects.create(
            address=client_ip,
            path=badge_path,
            method="GET",
            agent=request.META.get("HTTP_USER_AGENT", "")[:255],
            issuenumber=issue_number
        )
        
        # Get metrics
        activity_count = self.get_activity_count(issue_number)
        bounty_amount = self.get_bounty_amount(issue_number)
        
        # Generate badge
        svg_content = self.generate_badge_svg(activity_count, bounty_amount)
        
        return HttpResponse(
            svg_content,
            content_type="image/svg+xml",
            headers={
                "Cache-Control": "no-cache, no-store, must-revalidate",
                "Pragma": "no-cache", 
                "Expires": "0"
            }
        )

Step 2: Add URL Route

Add the new endpoint to blt/urls.py:

# Add to the URL patterns in blt/urls.py
path("issues/<int:issue_number>/badge/", GitHubIssueBadgeView.as_view(), name="github-issue-badge"),

Step 3: Update GitHubIssue Model (Optional Enhancement)

Add a direct bounty field to make querying easier:

# Add to website/models.py in GitHubIssue class
class GitHubIssue(models.Model):
    # ... existing fields ...
    bounty_amount = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    
    def save(self, *args, **kwargs):
        # Auto-extract bounty from p2p_amount_usd if available
        if self.p2p_amount_usd and not self.bounty_amount:
            self.bounty_amount = self.p2p_amount_usd
        super().save(*args, **kwargs)

Step 4: Create Migration

python manage.py makemigrations website
python manage.py migrate

Step 5: Enhance BLT-Action Workflow

The BLT-Action needs to be modified to automatically add badges to issue descriptions. Since you're using the external OWASP-BLT/BLT-Action@main, you'll need to:

Option A: Fork and modify BLT-Action to include badge insertion logic.

Option B: Create a separate GitHub Action that runs on issue creation:

# Add to .github/workflows/auto-badge.yml
name: Auto Badge Issues

on:
  issues:
    types: [opened]

jobs:
  add-badge:
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - name: Add Activity Badge
        uses: actions/github-script@v6
        with:
          script: |
            const issue = context.payload.issue;
            const badgeUrl = `https://blt.owasp.org/issues/${issue.number}/badge/`;
            const badgeMarkdown = `![Activity Badge](${badgeUrl})`;
            
            // Check if badge already exists
            if (!issue.body || !issue.body.includes(badgeUrl)) {
              const newBody = issue.body 
                ? `${badgeMarkdown}\n\n${issue.body}`
                : badgeMarkdown;
              
              await github.rest.issues.update({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issue.number,
                body: newBody
              });
            }

Step 6: Add Required Settings

Add to Django settings:

# Add to settings.py
GITHUB_REPO = "OWASP-BLT/BLT"  # Your repository
GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN")  # For API access

Step 7: Test the Implementation

  1. Test Badge Endpoint:

    curl https://blt.owasp.org/issues/3917/badge/
    
  2. Test Badge in GitHub Issue:

    ![Activity Badge](https://blt.owasp.org/issues/3917/badge/)
    

Step 8: Add Required Imports

Make sure to add these imports to website/views/project.py:

from django.http import HttpResponse
from django.db import models
from website.models import GitHubIssue, IP
from rest_framework.views import APIView

Summary

This solution: βœ… Creates dynamic badges showing activity count and bounty amount
βœ… Tracks IP visits for activity metrics
βœ… Extracts bounty amounts from GitHub issue labels
βœ… Automatically adds badges to new issues via GitHub Actions
βœ… Uses existing infrastructure (IP model, badge patterns)
βœ… Follows the existing codebase patterns

The badge will update in real-time showing current activity and bounty information, making issues more engaging and informative for contributors!

coderabbitai[bot] avatar May 27 '25 11:05 coderabbitai[bot]

/assign

Nitish-Naik avatar Jul 29 '25 19:07 Nitish-Naik

Hello @Nitish-Naik! You've been assigned to OWASP-BLT/BLT issue #3917. You have 24 hours to complete a pull request.

github-actions[bot] avatar Jul 29 '25 19:07 github-actions[bot]

⏰ This issue has been automatically unassigned from Nitish-Naik due to 24 hours of inactivity. The issue is now available for anyone to work on again.

github-actions[bot] avatar Jul 30 '25 20:07 github-actions[bot]

/assign

Navneet032007 avatar Nov 04 '25 13:11 Navneet032007

Hello @Navneet032007! You've been assigned to OWASP-BLT/BLT issue #3917. You have 24 hours to complete a pull request.

github-actions[bot] avatar Nov 04 '25 13:11 github-actions[bot]

Hi! Is anyone currently working on this issue or is there an open PR for it? I’d like to help if it’s still available.

aaradhychinche-alt avatar Nov 17 '25 04:11 aaradhychinche-alt

/assign

kris70lesgo avatar Nov 18 '25 02:11 kris70lesgo

Hello @kris70lesgo! You've been assigned to OWASP-BLT/BLT issue #3917. You have 24 hours to complete a pull request.


This comment was generated by OWASP BLT-Action

github-actions[bot] avatar Nov 18 '25 02:11 github-actions[bot]

⚠️ This issue is already assigned to @kris70lesgo. Please pick another issue.

github-actions[bot] avatar Dec 16 '25 17:12 github-actions[bot]