Repository: netbox-community/netbox
Issue: Webhooks fire erroneously when custom scripts fail causing a transaction rolback

### NetBox version

v3.2.4

### Python version

3.9

### Steps to Reproduce

* Register a webhook handler for the Contact object type.
* Run the following custom script:

```
from extras.scripts import Script
from tanancy.models import Contact

class MyScript(Script):
    def run(self, data, commit):
        contact = Contact(name="test")
        contact.full_clean()
        contact.save()
        raise Exception("Exception")
```

### Expected Behavior

No webhooks are sent as the script failed and the database transaction is rolled back.

### Observed Behavior

A weebhook is fired for the contact object.

Changed files:
netbox/extras/scripts.py, netbox/extras/management/commands/runscript.py

diff --git a/netbox/extras/management/commands/runscript.py b/netbox/extras/management/commands/runscript.py
index 12188619f..2296ce1ff 100644
--- a/netbox/extras/management/commands/runscript.py
+++ b/netbox/extras/management/commands/runscript.py
@@ -14,6 +14,7 @@ from extras.choices import JobResultStatusChoices
 from extras.context_managers import change_logging
 from extras.models import JobResult
 from extras.scripts import get_script
+from extras.signals import clear_webhooks
 from utilities.exceptions import AbortTransaction
 from utilities.utils import NetBoxFakeRequest
 
@@ -49,7 +50,7 @@ class Command(BaseCommand):
 
             except AbortTransaction:
                 script.log_info("Database changes have been reverted automatically.")
-
+                clear_webhooks.send(request)
             except Exception as e:
                 stacktrace = traceback.format_exc()
                 script.log_failure(
@@ -58,7 +59,7 @@ class Command(BaseCommand):
                 script.log_info("Database changes have been reverted due to error.")
                 logger.error(f"Exception raised during script execution: {e}")
                 job_result.set_status(JobResultStatusChoices.STATUS_ERRORED)
-
+                clear_webhooks.send(request)
             finally:
                 job_result.data = ScriptOutputSerializer(script).data
                 job_result.save()
diff --git a/netbox/extras/scripts.py b/netbox/extras/scripts.py
index 4332d72f7..e36cbb5a8 100644
--- a/netbox/extras/scripts.py
+++ b/netbox/extras/scripts.py
@@ -17,6 +17,7 @@ from django.utils.functional import classproperty
 
 from extras.api.serializers import ScriptOutputSerializer
 from extras.choices import JobResultStatusChoices, LogLevelChoices
+from extras.signals import clear_webhooks
 from ipam.formfields import IPAddressFormField, IPNetworkFormField
 from ipam.validators import MaxPrefixLengthValidator, MinPrefixLengthValidator, prefix_validator
 from utilities.exceptions import AbortTransaction
@@ -458,7 +459,7 @@ def run_script(data, request, commit=True, *args, **kwargs):
 
         except AbortTransaction:
             script.log_info("Database changes have been reverted automatically.")
-
+            clear_webhooks.send(request)
         except Exception as e:
             stacktrace = traceback.format_exc()
             script.log_failure(
@@ -467,7 +468,7 @@ def run_script(data, request, commit=True, *args, **kwargs):
             script.log_info("Database changes have been reverted due to error.")
             logger.error(f"Exception raised during script execution: {e}")
             job_result.set_status(JobResultStatusChoices.STATUS_ERRORED)
-
+            clear_webhooks.send(request)
         finally:
             job_result.data = ScriptOutputSerializer(script).data
             job_result.save()