Skip to content
Open
Changes from 1 commit
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: 14 additions & 1 deletion backend/apps/github/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,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 @@ -85,6 +91,12 @@ def issues(self):
"""
return self.created_issues.all()

def calculate_score(self):
score = 0.0
# Base contribution score
score += float( self.contributions_count or 0 )
return 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 | 🟡 Minor

Add docstring and fix formatting.

The method is missing a docstring (flagged by static analysis D102) and has non-standard spacing inside the parentheses on Line 97. Also consider adding a return type annotation for clarity.

📝 Suggested fix
     def calculate_score(self):
+        """Calculate a score based on contribution signals.
+
+        Returns:
+            float: The computed score for this user.
+
+        """
         score = 0.0
         # Base contribution score
-        score += float( self.contributions_count or 0 )
+        score += float(self.contributions_count or 0)
         return score
🧰 Tools
🪛 Ruff (0.15.6)

[warning] 94-94: Missing docstring in public method

(D102)

🤖 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 94 - 98, The calculate_score
method lacks a docstring, has non-standard spacing inside the float() call, and
should include a return type; update the method signature to def
calculate_score(self) -> float:, add a concise docstring explaining it computes
a base contribution score from self.contributions_count, and fix the formatting
to use float(self.contributions_count or 0) (no space after '(') before
returning the value.


@property
def nest_url(self) -> str:
"""Get Nest URL for user."""
Expand Down Expand Up @@ -170,6 +182,7 @@ 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