Skip to content
Open
Show file tree
Hide file tree
Changes from 6 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
15 changes: 15 additions & 0 deletions backend/apps/github/migrations/0045_add_calculated_score.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("github", "0044_user_indexes"),
]
operations = [
migrations.AddField(
model_name="user",
name="calculated_score",
field=models.FloatField(
default=0,
help_text="Computed score based on contribution signals",
),
),
]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add trailing newline at end of file.

Static analysis flags W292 on Line 15 (No newline at end of file).

Suggested fix
     ]
+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
]
]
🧰 Tools
🪛 Ruff (0.15.10)

[warning] 15-15: No newline at end of file

Add trailing newline

(W292)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/apps/github/migrations/0045_add_calculated_score.py` at line 15, The
file backend/apps/github/migrations/0045_add_calculated_score.py is missing a
trailing newline (static analysis W292); open the migration file
(0045_add_calculated_score.py) and add a single newline character at the end of
the file so the file ends with a blank line, then save/commit the change.

37 changes: 36 additions & 1 deletion backend/apps/github/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,33 @@

class User(NodeModel, GenericUserModel, TimestampedModel, UserIndexMixin):
"""User model."""
calculated_score = models.FloatField( default=0 )

def calculate_score(self):
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
return (
self._contribution_score()
+ self._consistency_score()
+ self._recency_score()
)

def _contribution_score(self):
return (self.contributions_count or 0) * 1.0
def _consistency_score(self):
base = self.contributions_count or 0
if base > 50:
return 25
elif base > 10:
return 10
return 0
def _recency_score(self):
return 5 if (self.contributions_count or 0) > 0 else 0
Comment thread
coderabbitai[bot] marked this conversation as resolved.

def _leadership_score(self):
score = 0
# Simple leadership signal
if self.is_owasp_staff:
score += 30
return score

class Meta:
"""Model options."""
Expand Down Expand Up @@ -55,7 +82,13 @@ class Meta:
)

contributions_count = models.PositiveIntegerField(
verbose_name="Contributions count", default=0
verbose_name="Contributions count",
default=0
)

calculated_score = models.FloatField(
default=0,
help_text="Computed score based on contribution signals"
)
Comment on lines +89 to 92
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search the GitHub app for model and migration references to `calculated_score`.
rg -n -C2 "calculated_score|AddField\(|AlterField\(" backend/apps/github

Repository: OWASP/Nest

Length of output: 39202


Create a migration for the calculated_score field.

The calculated_score field is defined in the model but lacks a corresponding migration. When the ORM attempts to persist data to this field, the column won't exist in the database, causing failures. Add a migration using python manage.py makemigrations to add this column.

🧰 Tools
🪛 Ruff (0.15.6)

[warning] 82-85: Class field calculated_score is defined multiple times

Remove duplicate field definition for calculated_score

(PIE794)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/apps/github/models/user.py` around lines 82 - 85, The model field
calculated_score (models.FloatField) was added to the User model but no
migration exists; run Django's migration flow to create and apply the schema
change: run python manage.py makemigrations to generate a migration that adds
the calculated_score column (keeping the default=0 and help_text), inspect and
commit the produced migration file, then run python manage.py migrate to apply
it to the database so the column exists at runtime.


contribution_data = models.JSONField(
Expand Down Expand Up @@ -170,6 +203,8 @@ def from_github(self, gh_user) -> None:
setattr(self, model_field, value)

self.is_bot = gh_user.type == "Bot"
self.calculated_score = self.calculate_score()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Score becomes stale when contributions_count is updated via management command.

The github_update_users.py management command (lines 27-59) updates contributions_count via bulk_save() without calling from_github(). This means calculated_score will not be recalculated when contributions are aggregated through that path, causing the two fields to be out of sync.

Since the management command appears to be the primary mechanism for aggregating contribution counts from RepositoryContributor, this will leave calculated_score stale for most users.

Consider one of these approaches:

  1. Update the management command to also recalculate scores:
# In github_update_users.py, after setting contributions_count:
user.contributions_count = user_contributions.get(user.id, 0)
user.calculated_score = user.calculate_score()
users.append(user)

# And update bulk_save to include the new field:
User.bulk_save(users, fields=("contributions_count", "calculated_score"))
  1. Use a database-level computed/generated field if using PostgreSQL and Django 5+, so the score is always derived from stored values.

  2. Override the model's save() method to always recalculate the score when contributions_count changes (though this won't help with bulk_update).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/apps/github/models/user.py` at line 185, The calculated_score is set
only in the model via self.calculated_score = self.calculate_score(), so updates
to contributions_count performed by the github_update_users.py management
command using bulk_save() leave calculated_score stale; fix by updating the
management command to recalculate scores before bulk_save (for each User set
user.contributions_count = ... and user.calculated_score =
user.calculate_score(), then call User.bulk_save(users,
fields=("contributions_count","calculated_score"))), or alternatively implement
a DB computed/generated column or override User.save() to recompute
calculated_score when contributions_count changes (note override won’t affect
bulk_update paths).



def get_absolute_url(self):
"""Get absolute URL for the user."""
Expand Down