Skip to content

Commit a576b6d

Browse files
committed
add signals to trigger rule evaluation
Signed-off-by: tdruez <tdruez@aboutcode.org>
1 parent 12ea0de commit a576b6d

6 files changed

Lines changed: 50 additions & 13 deletions

File tree

dje/admin.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,14 +1245,16 @@ def get_fieldsets(self, request, obj=None):
12451245
fields = [f"rule_{rule_type}_disabled", f"rule_{rule_type}_threshold"]
12461246
for param_name in handler.parameters_schema:
12471247
fields.append(f"rule_{rule_type}_param_{param_name}")
1248-
rule_fieldsets.append((
1249-
handler.label,
1250-
{
1251-
"fields": fields,
1252-
"description": handler.description,
1253-
"classes": ("grp-collapse grp-open",),
1254-
},
1255-
))
1248+
rule_fieldsets.append(
1249+
(
1250+
handler.label,
1251+
{
1252+
"fields": fields,
1253+
"description": handler.description,
1254+
"classes": ("grp-collapse grp-open",),
1255+
},
1256+
)
1257+
)
12561258
return rule_fieldsets
12571259

12581260
def get_formset(self, request, obj=None, **kwargs):

policy/apps.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313
class PolicyConfig(AppConfig):
1414
name = "policy"
1515
verbose_name = _("Policy")
16+
17+
def ready(self):
18+
import policy.signals # noqa: F401

policy/engine.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ def evaluate_rules(product):
7070
# Explicitly resolve open violations so disabling a rule clears its history
7171
# rather than leaving stale unresolved records.
7272
ProductPolicyViolation.objects.filter(
73-
rule_type=rule_type, product=product, resolved=False,
73+
rule_type=rule_type,
74+
product=product,
75+
resolved=False,
7476
).update(resolved=True, resolved_date=timezone.now())
7577
continue
7678

policy/signals.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# DejaCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: AGPL-3.0-only
5+
# See https://github.com/aboutcode-org/dejacode for support or download.
6+
# See https://aboutcode.org for more information about AboutCode FOSS projects.
7+
#
8+
9+
import logging
10+
11+
from django.db.models.signals import post_save
12+
from django.dispatch import receiver
13+
14+
from policy.tasks import evaluate_product_rules_task
15+
16+
logger = logging.getLogger(__name__)
17+
18+
19+
@receiver(post_save, sender="product_portfolio.Product")
20+
def evaluate_product_rules_on_save(sender, instance, **kwargs):
21+
"""Queue a policy rule evaluation whenever a product is saved."""
22+
logger.debug(f"Queuing policy rule evaluation for product {instance.uuid}")
23+
evaluate_product_rules_task.delay(product_uuid=instance.uuid)

policy/tasks.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@
66
# See https://aboutcode.org for more information about AboutCode FOSS projects.
77
#
88

9+
import logging
10+
911
from django.apps import apps
1012

1113
from django_rq import job
1214

1315
from policy.engine import evaluate_rules
1416

17+
logger = logging.getLogger(__name__)
18+
1519

1620
@job
1721
def evaluate_product_rules_task(product_uuid):
@@ -21,9 +25,12 @@ def evaluate_product_rules_task(product_uuid):
2125
try:
2226
product = Product.objects.select_related("dataspace").get(uuid=product_uuid)
2327
except Product.DoesNotExist:
28+
logger.warning(f"evaluate_product_rules_task: product {product_uuid} not found, skipping.")
2429
return
2530

26-
evaluate_rules(product)
31+
logger.info(f"Evaluating policy rules for product {product}")
32+
violations = evaluate_rules(product)
33+
logger.info(f"Policy rules evaluated for {product}: {len(violations)} active violation(s).")
2734

2835

2936
@job
@@ -35,5 +42,7 @@ def evaluate_all_products_rules_task(include_locked=False):
3542
if not include_locked:
3643
products = products.exclude_locked()
3744

45+
count = products.count()
46+
logger.info(f"Queuing policy rule evaluation for {count} product(s).")
3847
for product in products:
3948
evaluate_product_rules_task.delay(product_uuid=product.uuid)

product_portfolio/views.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2845,9 +2845,7 @@ def get_license_compliance_context(licenses, distribution_limit=10):
28452845

28462846
@staticmethod
28472847
def get_policy_compliance_context(product):
2848-
policy_violations = product.policy_violations.filter(resolved=False).select_related(
2849-
"policy_rule"
2850-
)
2848+
policy_violations = product.policy_violations.filter(resolved=False)
28512849
return {
28522850
"policy_violations": policy_violations,
28532851
"policy_violation_count": policy_violations.count(),

0 commit comments

Comments
 (0)