@@ -1091,7 +1091,13 @@ def create_new_diff(
10911091 packages
10921092 ) = self .get_added_and_removed_packages (head_full_scan_id , new_full_scan .id )
10931093
1094- diff = self .create_diff_report (added_packages , removed_packages )
1094+ # Separate unchanged packages from added/removed for --strict-blocking support
1095+ unchanged_packages = {
1096+ pkg_id : pkg for pkg_id , pkg in packages .items ()
1097+ if pkg_id not in added_packages and pkg_id not in removed_packages
1098+ }
1099+
1100+ diff = self .create_diff_report (added_packages , removed_packages , unchanged_packages )
10951101 diff .packages = packages
10961102
10971103 base_socket = "https://socket.dev/dashboard/org"
@@ -1114,6 +1120,7 @@ def create_diff_report(
11141120 self ,
11151121 added_packages : Dict [str , Package ],
11161122 removed_packages : Dict [str , Package ],
1123+ unchanged_packages : Optional [Dict [str , Package ]] = None ,
11171124 direct_only : bool = True
11181125 ) -> Diff :
11191126 """
@@ -1123,10 +1130,12 @@ def create_diff_report(
11231130 1. Records new/removed packages (direct only by default)
11241131 2. Collects alerts from both sets of packages
11251132 3. Determines new capabilities introduced
1133+ 4. Optionally collects alerts from unchanged packages for --strict-blocking
11261134
11271135 Args:
11281136 added_packages: Dict of packages added in new scan
11291137 removed_packages: Dict of packages removed in new scan
1138+ unchanged_packages: Dict of packages that didn't change (for --strict-blocking)
11301139 direct_only: If True, only direct dependencies are included in new/removed lists
11311140 (but alerts are still processed for all packages)
11321141
@@ -1137,6 +1146,7 @@ def create_diff_report(
11371146
11381147 alerts_in_added_packages : Dict [str , List [Issue ]] = {}
11391148 alerts_in_removed_packages : Dict [str , List [Issue ]] = {}
1149+ alerts_in_unchanged_packages : Dict [str , List [Issue ]] = {}
11401150
11411151 seen_new_packages = set ()
11421152 seen_removed_packages = set ()
@@ -1169,11 +1179,34 @@ def create_diff_report(
11691179 packages = removed_packages
11701180 )
11711181
1182+ # Process unchanged packages for --strict-blocking support
1183+ if unchanged_packages :
1184+ for package_id , package in unchanged_packages .items ():
1185+ # Skip packages that are in added or removed (they're already processed)
1186+ if package_id in added_packages or package_id in removed_packages :
1187+ continue
1188+
1189+ self .add_package_alerts_to_collection (
1190+ package = package ,
1191+ alerts_collection = alerts_in_unchanged_packages ,
1192+ packages = unchanged_packages
1193+ )
1194+
11721195 diff .new_alerts = Core .get_new_alerts (
11731196 alerts_in_added_packages ,
11741197 alerts_in_removed_packages
11751198 )
11761199
1200+ # Get unchanged alerts (for --strict-blocking mode)
1201+ diff .unchanged_alerts = Core .get_unchanged_alerts (
1202+ alerts_in_unchanged_packages
1203+ )
1204+
1205+ # Get removed alerts (for completeness)
1206+ diff .removed_alerts = Core .get_removed_alerts (
1207+ alerts_in_removed_packages
1208+ )
1209+
11771210 diff .new_capabilities = Core .get_capabilities_for_added_packages (added_packages )
11781211
11791212 Core .add_purl_capabilities (diff )
@@ -1433,3 +1466,62 @@ def get_new_alerts(
14331466 consolidated_alerts .add (alert_str )
14341467
14351468 return alerts
1469+
1470+ @staticmethod
1471+ def get_unchanged_alerts (
1472+ unchanged_package_alerts : Dict [str , List [Issue ]]
1473+ ) -> List [Issue ]:
1474+ """
1475+ Extract all alerts from unchanged packages that are errors or warnings.
1476+
1477+ This is used for --strict-blocking mode to identify existing violations
1478+ that should cause builds to fail.
1479+
1480+ Args:
1481+ unchanged_package_alerts: Dictionary of alerts from packages that didn't change
1482+
1483+ Returns:
1484+ List of all error/warning alerts from unchanged packages
1485+ """
1486+ alerts : List [Issue ] = []
1487+ consolidated_alerts = set ()
1488+
1489+ for alert_key in unchanged_package_alerts :
1490+ for alert in unchanged_package_alerts [alert_key ]:
1491+ # Consolidate by package and alert type
1492+ alert_str = f"{ alert .purl } ,{ alert .type } "
1493+
1494+ # Only include error or warning alerts
1495+ if (alert .error or alert .warn ) and alert_str not in consolidated_alerts :
1496+ alerts .append (alert )
1497+ consolidated_alerts .add (alert_str )
1498+
1499+ return alerts
1500+
1501+ @staticmethod
1502+ def get_removed_alerts (
1503+ removed_package_alerts : Dict [str , List [Issue ]]
1504+ ) -> List [Issue ]:
1505+ """
1506+ Extract all alerts from removed packages.
1507+
1508+ This is mainly for informational purposes - to show alerts that were removed.
1509+
1510+ Args:
1511+ removed_package_alerts: Dictionary of alerts from packages that were removed
1512+
1513+ Returns:
1514+ List of all alerts from removed packages
1515+ """
1516+ alerts : List [Issue ] = []
1517+ consolidated_alerts = set ()
1518+
1519+ for alert_key in removed_package_alerts :
1520+ for alert in removed_package_alerts [alert_key ]:
1521+ alert_str = f"{ alert .purl } ,{ alert .type } "
1522+
1523+ if alert_str not in consolidated_alerts :
1524+ alerts .append (alert )
1525+ consolidated_alerts .add (alert_str )
1526+
1527+ return alerts
0 commit comments