-
-
Notifications
You must be signed in to change notification settings - Fork 274
Create a health evaluation criteria #1550
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c319404
a46b9e4
5984ea2
fdec122
032abbd
eca8635
23eb00a
bcedde3
5bcd9b8
8110192
58865cb
8d6c3c0
f7beaaf
cbbd63f
c515b51
dfac905
9d30c8e
3788253
fd0688d
5452beb
c85e2ea
acf0c66
56f3cf3
8845db3
9cea493
891074d
f5b4514
9faf664
1e70ad7
dc7adcd
8edde6d
c6a7061
a2eaf7a
b49f80d
4f24790
1702e50
e4d661a
8dabe94
1918428
b787163
9c555c8
5d1d1aa
56231b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| """A command to update OWASP project health metrics.""" | ||
|
|
||
| from django.core.management.base import BaseCommand | ||
|
|
||
| from apps.owasp.models.project import Project | ||
| from apps.owasp.models.project_health_metrics import ProjectHealthMetrics | ||
|
|
||
|
|
||
| class Command(BaseCommand): | ||
| help = "Update OWASP project health metrics." | ||
|
|
||
| def handle(self, *args, **options): | ||
| metric_project_field_mapping = { | ||
| "contributors_count": "contributors_count", | ||
| "created_at": "created_at", | ||
| "forks_count": "forks_count", | ||
| "is_funding_requirements_compliant": "is_funding_requirements_compliant", | ||
| "is_leader_requirements_compliant": "is_leader_requirements_compliant", | ||
| "last_committed_at": "pushed_at", | ||
| "last_released_at": "released_at", | ||
| "open_issues_count": "open_issues_count", | ||
| "open_pull_requests_count": "open_pull_requests_count", | ||
| "owasp_page_last_updated_at": "owasp_page_last_updated_at", | ||
| "pull_request_last_created_at": "pull_request_last_created_at", | ||
| "recent_releases_count": "recent_releases_count", | ||
| "stars_count": "stars_count", | ||
| "total_issues_count": "issues_count", | ||
| "total_pull_requests_count": "pull_requests_count", | ||
| "total_releases_count": "releases_count", | ||
| "unanswered_issues_count": "unanswered_issues_count", | ||
| "unassigned_issues_count": "unassigned_issues_count", | ||
| } | ||
| project_health_metrics = [] | ||
| for project in Project.objects.all(): | ||
| self.stdout.write(self.style.NOTICE(f"Evaluating metrics for project: {project.name}")) | ||
| metrics = ProjectHealthMetrics(project=project) | ||
|
|
||
| # Update metrics based on requirements. | ||
| for metric_field, project_field in metric_project_field_mapping.items(): | ||
| setattr(metrics, metric_field, getattr(project, project_field)) | ||
|
|
||
| project_health_metrics.append(metrics) | ||
|
|
||
| ProjectHealthMetrics.bulk_save(project_health_metrics) | ||
| self.stdout.write(self.style.SUCCESS("Evaluated projects health metrics successfully. ")) | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,66 @@ | ||||||||||||||||
| """A command to update OWASP project health metrics scores.""" | ||||||||||||||||
|
|
||||||||||||||||
| from django.core.management.base import BaseCommand | ||||||||||||||||
|
|
||||||||||||||||
| from apps.owasp.models.project_health_metrics import ProjectHealthMetrics | ||||||||||||||||
| from apps.owasp.models.project_health_requirements import ProjectHealthRequirements | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| class Command(BaseCommand): | ||||||||||||||||
| help = "Update OWASP project health metrics score." | ||||||||||||||||
|
|
||||||||||||||||
| def handle(self, *args, **options): | ||||||||||||||||
| forward_fields = { | ||||||||||||||||
| "age_days": 6.0, | ||||||||||||||||
| "contributors_count": 6.0, | ||||||||||||||||
| "forks_count": 6.0, | ||||||||||||||||
| "is_funding_requirements_compliant": 5.0, | ||||||||||||||||
| "is_leader_requirements_compliant": 5.0, | ||||||||||||||||
| "open_pull_requests_count": 6.0, | ||||||||||||||||
| "recent_releases_count": 6.0, | ||||||||||||||||
| "stars_count": 6.0, | ||||||||||||||||
| "total_pull_requests_count": 6.0, | ||||||||||||||||
| "total_releases_count": 6.0, | ||||||||||||||||
| } | ||||||||||||||||
| backward_fields = { | ||||||||||||||||
| "last_commit_days": 6.0, | ||||||||||||||||
| "last_pull_request_days": 6.0, | ||||||||||||||||
| "last_release_days": 6.0, | ||||||||||||||||
| "open_issues_count": 6.0, | ||||||||||||||||
| "owasp_page_last_update_days": 6.0, | ||||||||||||||||
| "unanswered_issues_count": 6.0, | ||||||||||||||||
| "unassigned_issues_count": 6.0, | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| project_health_metrics = [] | ||||||||||||||||
| project_health_requirements = { | ||||||||||||||||
| phr.level: phr for phr in ProjectHealthRequirements.objects.all() | ||||||||||||||||
| } | ||||||||||||||||
| for metric in ProjectHealthMetrics.objects.filter( | ||||||||||||||||
| score__isnull=True, | ||||||||||||||||
| ).select_related( | ||||||||||||||||
| "project", | ||||||||||||||||
| ): | ||||||||||||||||
| # Calculate the score based on requirements. | ||||||||||||||||
| self.stdout.write( | ||||||||||||||||
| self.style.NOTICE(f"Updating score for project: {metric.project.name}") | ||||||||||||||||
| ) | ||||||||||||||||
|
Comment on lines
+45
to
+47
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
- self.stdout.write(
- self.style.NOTICE(f"Updating score for project: {metric.project.name}")
- )
+ self.stdout.write(
+ self.style.WARNING(f"Updating score for project: {metric.project.name}")
+ )Or drop styling altogether if you just need plain output. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||
|
|
||||||||||||||||
| requirements = project_health_requirements[metric.project.level] | ||||||||||||||||
arkid15r marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
|
|
||||||||||||||||
| score = 0.0 | ||||||||||||||||
| for field, weight in forward_fields.items(): | ||||||||||||||||
| if int(getattr(metric, field)) >= int(getattr(requirements, field)): | ||||||||||||||||
| score += weight | ||||||||||||||||
|
|
||||||||||||||||
| for field, weight in backward_fields.items(): | ||||||||||||||||
| if int(getattr(metric, field)) <= int(getattr(requirements, field)): | ||||||||||||||||
| score += weight | ||||||||||||||||
arkid15r marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
|
|
||||||||||||||||
| metric.score = score | ||||||||||||||||
| project_health_metrics.append(metric) | ||||||||||||||||
|
|
||||||||||||||||
| ProjectHealthMetrics.bulk_save(project_health_metrics, fields=["score"]) | ||||||||||||||||
| self.stdout.write( | ||||||||||||||||
| self.style.SUCCESS("Updated projects health metrics score successfully.") | ||||||||||||||||
| ) | ||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Generated by Django 5.2.1 on 2025-06-03 14:47 | ||
|
|
||
| from django.db import migrations | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
| dependencies = [ | ||
| ("owasp", "0034_alter_chapter_leaders_and_more"), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.RenameField( | ||
| model_name="projecthealthmetrics", | ||
| old_name="total_pull_request_count", | ||
| new_name="total_pull_requests_count", | ||
| ), | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # Generated by Django 5.2.1 on 2025-06-08 02:58 | ||
|
|
||
| import django.core.validators | ||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
| dependencies = [ | ||
| ( | ||
| "owasp", | ||
| "0035_rename_total_pull_request_count_projecthealthmetrics_total_pull_requests_count", | ||
| ), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.AlterField( | ||
| model_name="projecthealthmetrics", | ||
| name="score", | ||
| field=models.FloatField( | ||
| help_text="Project health score (0-100)", | ||
| null=True, | ||
| validators=[ | ||
| django.core.validators.MinValueValidator(0.0), | ||
| django.core.validators.MaxValueValidator(100.0), | ||
| ], | ||
| ), | ||
| ), | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # Generated by Django 5.2.1 on 2025-06-08 03:01 | ||
|
|
||
| import django.db.models.deletion | ||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
| dependencies = [ | ||
| ("owasp", "0036_alter_projecthealthmetrics_score"), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.AlterField( | ||
| model_name="projecthealthmetrics", | ||
| name="project", | ||
| field=models.ForeignKey( | ||
| on_delete=django.db.models.deletion.CASCADE, | ||
| related_name="health_metrics", | ||
| to="owasp.project", | ||
| ), | ||
| ), | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # Generated by Django 5.2.2 on 2025-06-12 23:19 | ||
|
|
||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
| dependencies = [ | ||
| ("owasp", "0037_alter_projecthealthmetrics_project"), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.RemoveField( | ||
| model_name="projecthealthmetrics", | ||
| name="is_project_leaders_requirements_compliant", | ||
| ), | ||
| migrations.AddField( | ||
| model_name="projecthealthmetrics", | ||
| name="is_leaders_requirements_compliant", | ||
| field=models.BooleanField( | ||
| default=False, verbose_name="Is project leaders requirements compliant" | ||
| ), | ||
| ), | ||
|
Comment on lines
+11
to
+22
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove-then-add pattern silently drops existing column values
🤖 Prompt for AI Agents |
||
| ] | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.style.NOTICEwill raiseAttributeErrorDjango’s
color_styledoes not define aNOTICEstyle. Use one of the built-ins (SUCCESS,WARNING,ERROR, …) or output plain text.📝 Committable suggestion
🤖 Prompt for AI Agents