Repository: StackStorm/st2

Issue:
st2-register-content should fail on failure (exit with non zero) by default
Right now it doesn't which means it easy to miss some (important) errors.

The change is not backward compatible, but it's a good one (imo). We can also add `--register-no-failure-on-failure` flag for users which desire old behavior.

See https://github.com/StackStorm/st2/issues/2827#issuecomment-235047780.



Discussion:

Resolving patch:
diff --git a/st2common/st2common/content/bootstrap.py b/st2common/st2common/content/bootstrap.py
--- a/st2common/st2common/content/bootstrap.py
+++ b/st2common/st2common/content/bootstrap.py
@@ -60,8 +60,12 @@ def register_opts():
         cfg.BoolOpt('setup-virtualenvs', default=False, help=('Setup Python virtual environments '
                                                               'all the Python runner actions.')),
 
-        cfg.BoolOpt('fail-on-failure', default=False, help=('Exit with non-zero of resource '
-                                                            'registration fails.'))
+        cfg.BoolOpt('no-fail-on-failure', default=False,
+                    help=('Don\'t exit with non-zero if some resource registration fails.')),
+        # Note: Fail on failure is now a default behavior. This flag is only left here for backward
+        # compatibility reasons, but it's not actually used.
+        cfg.BoolOpt('fail-on-failure', default=False,
+                    help=('Exit with non-zero if some resource registration fails.'))
     ]
     try:
         cfg.CONF.register_cli_opts(content_opts, group='register')
@@ -80,7 +84,7 @@ def setup_virtualenvs():
     LOG.info('=========================================================')
 
     pack_dir = cfg.CONF.register.pack
-    fail_on_failure = cfg.CONF.register.fail_on_failure
+    fail_on_failure = not cfg.CONF.register.no_fail_on_failure
 
     registrar = ResourceRegistrar()
 
@@ -117,7 +121,7 @@ def setup_virtualenvs():
 
 def register_triggers():
     pack_dir = cfg.CONF.register.pack
-    fail_on_failure = cfg.CONF.register.fail_on_failure
+    fail_on_failure = not cfg.CONF.register.no_fail_on_failure
 
     registered_count = 0
 
@@ -139,7 +143,7 @@ def register_triggers():
 
 def register_sensors():
     pack_dir = cfg.CONF.register.pack
-    fail_on_failure = cfg.CONF.register.fail_on_failure
+    fail_on_failure = not cfg.CONF.register.no_fail_on_failure
 
     registered_count = 0
 
@@ -163,7 +167,7 @@ def register_actions():
     # Register runnertypes and actions. The order is important because actions require action
     # types to be present in the system.
     pack_dir = cfg.CONF.register.pack
-    fail_on_failure = cfg.CONF.register.fail_on_failure
+    fail_on_failure = not cfg.CONF.register.no_fail_on_failure
 
     registered_count = 0
 
@@ -195,7 +199,7 @@ def register_actions():
 def register_rules():
     # Register ruletypes and rules.
     pack_dir = cfg.CONF.register.pack
-    fail_on_failure = cfg.CONF.register.fail_on_failure
+    fail_on_failure = not cfg.CONF.register.no_fail_on_failure
 
     registered_count = 0
 
@@ -223,7 +227,7 @@ def register_rules():
 
 def register_aliases():
     pack_dir = cfg.CONF.register.pack
-    fail_on_failure = cfg.CONF.register.fail_on_failure
+    fail_on_failure = not cfg.CONF.register.no_fail_on_failure
 
     registered_count = 0
 
@@ -245,7 +249,7 @@ def register_aliases():
 def register_policies():
     # Register policy types and policies.
     pack_dir = cfg.CONF.register.pack
-    fail_on_failure = cfg.CONF.register.fail_on_failure
+    fail_on_failure = not cfg.CONF.register.no_fail_on_failure
 
     registered_type_count = 0
 
@@ -278,7 +282,7 @@ def register_policies():
 
 def register_configs():
     pack_dir = cfg.CONF.register.pack
-    fail_on_failure = cfg.CONF.register.fail_on_failure
+    fail_on_failure = not cfg.CONF.register.no_fail_on_failure
 
     registered_count = 0
 


Test patch:
diff --git a/st2common/tests/integration/test_register_content_script.py b/st2common/tests/integration/test_register_content_script.py
--- a/st2common/tests/integration/test_register_content_script.py
+++ b/st2common/tests/integration/test_register_content_script.py
@@ -45,7 +45,8 @@ def test_register_from_pack_success(self):
     def test_register_from_pack_fail_on_failure_pack_dir_doesnt_exist(self):
         # No fail on failure flag, should succeed
         pack_dir = 'doesntexistblah'
-        cmd = BASE_REGISTER_ACTIONS_CMD_ARGS + ['--register-pack=%s' % (pack_dir)]
+        cmd = BASE_REGISTER_ACTIONS_CMD_ARGS + ['--register-pack=%s' % (pack_dir),
+                                                '--register-no-fail-on-failure']
         exit_code, _, _ = run_command(cmd=cmd)
         self.assertEqual(exit_code, 0)
 
@@ -59,7 +60,8 @@ def test_register_from_pack_fail_on_failure_pack_dir_doesnt_exist(self):
     def test_register_from_pack_action_metadata_fails_validation(self):
         # No fail on failure flag, should succeed
         pack_dir = os.path.join(get_fixtures_packs_base_path(), 'dummy_pack_4')
-        cmd = BASE_REGISTER_ACTIONS_CMD_ARGS + ['--register-pack=%s' % (pack_dir)]
+        cmd = BASE_REGISTER_ACTIONS_CMD_ARGS + ['--register-pack=%s' % (pack_dir),
+                                                '--register-no-fail-on-failure']
         exit_code, _, stderr = run_command(cmd=cmd)
         self.assertTrue('Registered 0 actions.' in stderr)
         self.assertEqual(exit_code, 0)
@@ -83,7 +85,8 @@ def test_register_from_packs_doesnt_throw_on_missing_pack_resource_folder(self):
         self.assertTrue('Registered 0 sensors.' in stderr)
         self.assertEqual(exit_code, 0)
 
-        cmd = [SCRIPT_PATH, '--config-file=conf/st2.tests1.conf', '-v', '--register-all']
+        cmd = [SCRIPT_PATH, '--config-file=conf/st2.tests1.conf', '-v', '--register-all',
+               '--register-no-fail-on-failure']
         exit_code, _, stderr = run_command(cmd=cmd)
         self.assertTrue('Registered 0 actions.' in stderr)
         self.assertTrue('Registered 0 sensors.' in stderr)
@@ -92,7 +95,8 @@ def test_register_from_packs_doesnt_throw_on_missing_pack_resource_folder(self):
 
     def test_register_all_and_register_setup_virtualenvs(self):
         # Verify that --register-all works in combinations with --register-setuo-virtualenvs
-        cmd = BASE_CMD_ARGS + ['--register-all', '--register-setup-virtualenvs']
+        cmd = BASE_CMD_ARGS + ['--register-all', '--register-setup-virtualenvs',
+                               '--register-no-fail-on-failure']
         exit_code, stdout, stderr = run_command(cmd=cmd)
         self.assertTrue('Registering actions' in stderr)
         self.assertTrue('Registering rules' in stderr)
@@ -103,7 +107,8 @@ def test_register_setup_virtualenvs(self):
         # Single pack
         pack_dir = os.path.join(get_fixtures_packs_base_path(), 'dummy_pack_1')
 
-        cmd = BASE_CMD_ARGS + ['--register-pack=%s' % (pack_dir), '--register-setup-virtualenvs']
+        cmd = BASE_CMD_ARGS + ['--register-pack=%s' % (pack_dir), '--register-setup-virtualenvs',
+                               '--register-no-fail-on-failure']
         exit_code, stdout, stderr = run_command(cmd=cmd)
 
         self.assertTrue('Setting up virtualenv for pack "dummy_pack_1"' in stderr)
@@ -111,7 +116,7 @@ def test_register_setup_virtualenvs(self):
         self.assertEqual(exit_code, 0)
 
         # All packs
-        cmd = BASE_CMD_ARGS + ['--register-setup-virtualenvs']
+        cmd = BASE_CMD_ARGS + ['--register-setup-virtualenvs', '--register-no-fail-on-failure']
         exit_code, stdout, stderr = run_command(cmd=cmd)
         self.assertTrue('Setup virtualenv for 5 pack(s)' in stderr)
         self.assertEqual(exit_code, 0)