Repository: Sceptre/sceptre

Issue:
Cloudformation Hook Status message in sceptre output is confusing
The cloudformation hook status reason and hook mode displayed as a part of sceptre cloudformation log is misleading.
As it appends the HookMode to the Hook Message, if the mode is FAIL and the hooks message is successful, it display as Hook Execution is Successful FAIL. This is misleading and the user tends to check for failure reason.

### Your environment
* version of sceptre - 4.5.2
* version of python - 3.9
* which OS/distro - Ubuntu

### Steps to reproduce
Setup the cloudformation hooks(WARN/FAIL) in you AWS account. Execute the cloudformation template through sceptre v 4.5.2

### Expected behaviour
The hook log should not have the hook mode added at the end of the hook message as its confusing the users. Sample sceptre cloudformation hook log below.

```
07:17:25  [2024-09-17 01:47:24] - sbox-01/sbucket Bucket AWS::S3::Bucket CREATE_IN_PROGRESS  sample::Generic::Megahookblock HOOK_COMPLETE_SUCCEEDED Hook succeeded with message: Hook Successfully completed
07:17:33  [2024-09-17 01:47:33] - sbox-01/sbucket Bucket AWS::S3::Bucket CREATE_IN_PROGRESS  sample::Generic::Megahookwarn HOOK_COMPLETE_FAILED Hook failed with message: Rule [
07:17:33          [CT.S3.PR.1]: Require an Amazon S3 bucket to have block public access settings configured
07:17:33          [FIX]: The parameters 'BlockPublicAcls', 'BlockPublicPolicy', 'IgnorePublicAcls', 'RestrictPublicBuckets' must be set to "true" under the bucket-level 'PublicAccessBlockConfiguration'.
07:17:33          ] failed.
07:17:33  [2024-09-17 01:47:33] - sbox-01/sbucket Bucket AWS::S3::Bucket CREATE_FAILED The following hook(s) failed: [sample::Generic::Megahookwarn]
```

### Actual behaviour
The Hook Mode gets added to the Hook status message. Sample sceptre cloudformation hook log below.

```
07:17:25  [2024-09-17 01:47:24] - sbox-01/sbucket Bucket AWS::S3::Bucket CREATE_IN_PROGRESS  sample::Generic::Megahookblock HOOK_COMPLETE_SUCCEEDED Hook succeeded with message: Hook Successfully completed **FAIL**
07:17:33  [2024-09-17 01:47:33] - sbox-01/sbucket Bucket AWS::S3::Bucket CREATE_IN_PROGRESS  sample::Generic::Megahookwarn HOOK_COMPLETE_FAILED Hook failed with message: Rule [
07:17:33          [CT.S3.PR.1]: Require an Amazon S3 bucket to have block public access settings configured
07:17:33          [FIX]: The parameters 'BlockPublicAcls', 'BlockPublicPolicy', 'IgnorePublicAcls', 'RestrictPublicBuckets' must be set to "true" under the bucket-level 'PublicAccessBlockConfiguration'.
07:17:33          ] failed. **FAIL**
07:17:33  [2024-09-17 01:47:33] - sbox-01/sbucket Bucket AWS::S3::Bucket CREATE_FAILED The following hook(s) failed: [sample::Generic::Megahookwarn]
```

Discussion:

Solution patch:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 778156889..87c1b233e 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -17,7 +17,7 @@ repos:
     hooks:
       - id: yamllint
   - repo: https://github.com/awslabs/cfn-python-lint
-    rev: v1.12.4
+    rev: v1.15.0
     hooks:
       - id: cfn-python-lint
         args:
diff --git a/docs/_source/docs/install.rst b/docs/_source/docs/install.rst
index 8f37b6dc9..cff5af775 100644
--- a/docs/_source/docs/install.rst
+++ b/docs/_source/docs/install.rst
@@ -36,8 +36,8 @@ Using Docker image
 
 To use our Docker image follow these instructions:
 
-1. Pull the image ``docker pull cloudreach/sceptre:[SCEPTRE_VERSION_NUMBER]`` e.g.
-   ``docker pull cloudreach/sceptre:2.1.3``. Leave out the version number if you
+1. Pull the image ``docker pull sceptreorg/sceptre:[SCEPTRE_VERSION_NUMBER]`` e.g.
+   ``docker pull sceptreorg/sceptre:4.5.2``. Leave out the version number if you
    wish to run `latest`.
 
 2. Run the image. You will need to mount the working directory where your
diff --git a/sceptre/plan/actions.py b/sceptre/plan/actions.py
index d8022b2ba..d932d8770 100644
--- a/sceptre/plan/actions.py
+++ b/sceptre/plan/actions.py
@@ -919,7 +919,6 @@ def _log_new_events(self, after_datetime: datetime) -> datetime:
                         event["HookType"],
                         event["HookStatus"],
                         event.get("HookStatusReason", ""),
-                        event["HookFailureMode"],
                     ]
                 )
             self.logger.info(" ".join(stack_event_status))


Test patch:
diff --git a/tests/test_actions.py b/tests/test_actions.py
index 77933e298..392a147b8 100644
--- a/tests/test_actions.py
+++ b/tests/test_actions.py
@@ -1125,7 +1125,6 @@ def test_log_new_events_with_hook_status_prints_correct_event(
                         "ResourceStatus": "resource-with-cf-hook",
                         "HookType": "type-3",
                         "HookStatus": "HOOK_COMPLETE_SUCCEEDED",
-                        "HookFailureMode": "WARN",
                     },
                     {
                         "Timestamp": datetime.datetime(
@@ -1138,7 +1137,6 @@ def test_log_new_events_with_hook_status_prints_correct_event(
                         "HookType": "type-4",
                         "HookStatus": "HOOK_IN_PROGRESS",
                         "HookStatusReason": "Good hook",
-                        "HookFailureMode": "WARN",
                     },
                 ]
             }
@@ -1153,7 +1151,6 @@ def test_log_new_events_with_hook_status_prints_correct_event(
                 self.actions.describe_events()["StackEvents"][1]["ResourceStatus"],
                 self.actions.describe_events()["StackEvents"][1]["HookType"],
                 self.actions.describe_events()["StackEvents"][1]["HookStatus"],
-                self.actions.describe_events()["StackEvents"][1]["HookFailureMode"],
             ].sort() == caplog.messages[0].split().sort()
             assert [
                 self.actions.stack.name,
@@ -1166,7 +1163,6 @@ def test_log_new_events_with_hook_status_prints_correct_event(
                 self.actions.describe_events()["StackEvents"][0]["HookType"],
                 self.actions.describe_events()["StackEvents"][0]["HookStatus"],
                 self.actions.describe_events()["StackEvents"][0]["HookStatusReason"],
-                self.actions.describe_events()["StackEvents"][0]["HookFailureMode"],
             ].sort() == caplog.messages[1].split().sort()
 
     @patch("sceptre.plan.actions.StackActions._get_cs_status")