Repository: ansible/molecule

Issue:
Add support for checking exit codes on shell dependencies
# Issue Type

- Feature request

# Molecule and Ansible details

```
ansible 2.10.5
  config file = /Users/jhg03a/<redacted>/ansible.cfg
  configured module search path = ['/Users/jhg03a/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.9/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.9.2 (default, Feb 24 2021, 13:26:09) [Clang 12.0.0 (clang-1200.0.32.29)]
molecule 3.2.3 using python 3.9
    ansible:2.10.5
    delegated:3.2.3 from molecule
    docker:0.2.4 from molecule_docker
```

Molecule installation method (one of):

- pip

Ansible installation method (one of):

- pip

# Desired Behavior

Currently it appears that the dependency shell module doesn't take into account the exit code from the command.  If something goes wrong in the dependency phase, it's highly likely the rest of the run is going to fail or have inconsistent results.

### Example:
```yaml
dependency:
  name: shell
  command: 'false'
```



Discussion:

Resolving patch:
diff --git a/src/molecule/dependency/base.py b/src/molecule/dependency/base.py
--- a/src/molecule/dependency/base.py
+++ b/src/molecule/dependency/base.py
@@ -23,8 +23,9 @@
 import logging
 import os
 import time
+from subprocess import CalledProcessError
 
-from molecule import constants, util
+from molecule import util
 
 LOG = logging.getLogger(__name__)
 
@@ -53,11 +54,11 @@ def execute_with_retries(self):
 
         try:
             # print(555, self._sh_command)
-            util.run_command(self._sh_command, debug=self._config.debug)
+            util.run_command(self._sh_command, debug=self._config.debug, check=True)
             msg = "Dependency completed successfully."
             LOG.info(msg)
             return
-        except Exception:
+        except CalledProcessError:
             pass
 
         for counter in range(1, (self.RETRY + 1)):
@@ -70,15 +71,15 @@ def execute_with_retries(self):
             self.SLEEP += self.BACKOFF
 
             try:
-                util.run_command(self._sh_command, debug=self._config.debug)
+                util.run_command(self._sh_command, debug=self._config.debug, check=True)
                 msg = "Dependency completed successfully."
                 LOG.info(msg)
                 return
-            except Exception as _exception:
+            except CalledProcessError as _exception:
                 exception = _exception
 
-        LOG.error(str(exception), self._sh_command)
-        util.sysexit(getattr(exception, "exit_code", constants.RC_UNKNOWN_ERROR))
+        LOG.error(str(exception))
+        util.sysexit(exception.returncode)
 
     @abc.abstractmethod
     def execute(self):  # pragma: no cover


Test patch:
diff --git a/src/molecule/test/unit/dependency/ansible_galaxy/test_collections.py b/src/molecule/test/unit/dependency/ansible_galaxy/test_collections.py
--- a/src/molecule/test/unit/dependency/ansible_galaxy/test_collections.py
+++ b/src/molecule/test/unit/dependency/ansible_galaxy/test_collections.py
@@ -160,7 +160,9 @@ def test_execute(
     )
     assert os.path.isdir(role_directory)
 
-    patched_run_command.assert_called_once_with("patched-command", debug=False)
+    patched_run_command.assert_called_once_with(
+        "patched-command", debug=False, check=True
+    )
 
     msg = "Dependency completed successfully."
     patched_logger_info.assert_called_once_with(msg)
diff --git a/src/molecule/test/unit/dependency/ansible_galaxy/test_roles.py b/src/molecule/test/unit/dependency/ansible_galaxy/test_roles.py
--- a/src/molecule/test/unit/dependency/ansible_galaxy/test_roles.py
+++ b/src/molecule/test/unit/dependency/ansible_galaxy/test_roles.py
@@ -156,7 +156,9 @@ def test_execute(
     )
     assert os.path.isdir(role_directory)
 
-    patched_run_command.assert_called_once_with("patched-command", debug=False)
+    patched_run_command.assert_called_once_with(
+        "patched-command", debug=False, check=True
+    )
 
     msg = "Dependency completed successfully."
     patched_logger_info.assert_called_once_with(msg)
diff --git a/src/molecule/test/unit/dependency/test_shell.py b/src/molecule/test/unit/dependency/test_shell.py
--- a/src/molecule/test/unit/dependency/test_shell.py
+++ b/src/molecule/test/unit/dependency/test_shell.py
@@ -94,7 +94,9 @@ def test_execute(patched_run_command, patched_logger_info, _instance):
     _instance._sh_command = "patched-command"
     _instance.execute()
 
-    patched_run_command.assert_called_once_with("patched-command", debug=False)
+    patched_run_command.assert_called_once_with(
+        "patched-command", debug=False, check=True
+    )
 
     msg = "Dependency completed successfully."
     patched_logger_info.assert_called_once_with(msg)