Repository: oppia/oppia

Issue:
Refactor linter to fail if one of the sub-linter fails and exit
Right now if one of the sub-linter fails with an error, the linter keeps running, and status at then of linter appeared to be passed. Refactor the linter, if any sub-linter fails the main linter result as failed not passed.


Discussion:

Resolving patch:
diff --git a/scripts/linters/css_linter.py b/scripts/linters/css_linter.py
--- a/scripts/linters/css_linter.py
+++ b/scripts/linters/css_linter.py
@@ -22,7 +22,6 @@
 import os
 import re
 import subprocess
-import sys
 
 import python_utils
 
@@ -88,12 +87,9 @@ def lint_css_files(self):
         stylelint_path = os.path.join(
             'node_modules', 'stylelint', 'bin', 'stylelint.js')
         if not os.path.exists(stylelint_path):
-            python_utils.PRINT('')
-            python_utils.PRINT(
-                'ERROR    Please run start.sh first to install node-eslint ')
-            python_utils.PRINT(
-                '         or node-stylelint and its dependencies.')
-            sys.exit(1)
+            raise Exception(
+                'ERROR    Please run start.sh first to install node-eslint '
+                'or node-stylelint and its dependencies.')
         files_to_lint = self.all_filepaths
         num_files_with_errors = 0
         failed = False
@@ -113,9 +109,7 @@ def lint_css_files(self):
             linter_stdout = encoded_linter_stdout.decode(encoding='utf-8')
             linter_stderr = encoded_linter_stderr.decode(encoding='utf-8')
             if linter_stderr:
-                python_utils.PRINT('LINTER FAILED')
-                python_utils.PRINT(linter_stderr)
-                sys.exit(1)
+                raise Exception(linter_stderr)
 
             if linter_stdout:
                 num_files_with_errors += 1
diff --git a/scripts/linters/js_ts_linter.py b/scripts/linters/js_ts_linter.py
--- a/scripts/linters/js_ts_linter.py
+++ b/scripts/linters/js_ts_linter.py
@@ -1115,12 +1115,9 @@ def _lint_js_and_ts_files(self):
         eslint_path = os.path.join(
             'node_modules', 'eslint', 'bin', 'eslint.js')
         if not os.path.exists(eslint_path):
-            python_utils.PRINT('')
-            python_utils.PRINT(
-                'ERROR    Please run start.sh first to install node-eslint ')
-            python_utils.PRINT(
-                '         and its dependencies.')
-            sys.exit(1)
+            raise Exception(
+                'ERROR    Please run start.sh first to install node-eslint '
+                'and its dependencies.')
 
         files_to_lint = self.all_filepaths
         num_files_with_errors = 0
@@ -1140,9 +1137,7 @@ def _lint_js_and_ts_files(self):
             linter_stdout = encoded_linter_stdout.decode(encoding='utf-8')
             linter_stderr = encoded_linter_stderr.decode(encoding='utf-8')
             if linter_stderr:
-                python_utils.PRINT('LINTER FAILED')
-                python_utils.PRINT(linter_stderr)
-                sys.exit(1)
+                raise Exception(linter_stderr)
 
             if linter_stdout:
                 num_files_with_errors += 1


Test patch:
diff --git a/scripts/linters/css_linter_test.py b/scripts/linters/css_linter_test.py
--- a/scripts/linters/css_linter_test.py
+++ b/scripts/linters/css_linter_test.py
@@ -77,7 +77,9 @@ def mock_join(*unused_args):
         third_party_linter = css_linter.ThirdPartyCSSLintChecksManager(
             CONFIG_PATH, [INVALID_CSS_FILEPATH])
         with self.print_swap, join_swap, self.assertRaisesRegexp(
-            SystemExit, '1'):
+            Exception,
+            'ERROR    Please run start.sh first to install node-eslint or '
+            'node-stylelint and its dependencies.'):
             third_party_linter.perform_all_lint_checks()
 
     def test_perform_all_lint_checks_with_stderr(self):
@@ -95,7 +97,7 @@ def mock_communicate():
         third_party_linter = css_linter.ThirdPartyCSSLintChecksManager(
             CONFIG_PATH, [VALID_CSS_FILEPATH])
         with self.print_swap, popen_swap, self.assertRaisesRegexp(
-            SystemExit, '1'):
+            Exception, 'True'):
             third_party_linter.perform_all_lint_checks()
 
     def test_perform_all_lint_checks_with_no_files(self):
diff --git a/scripts/linters/js_ts_linter_test.py b/scripts/linters/js_ts_linter_test.py
--- a/scripts/linters/js_ts_linter_test.py
+++ b/scripts/linters/js_ts_linter_test.py
@@ -490,7 +490,7 @@ def test_third_party_linter(self):
         self.validate(lint_task_report, expected_messages, 1)
 
     def test_third_party_linter_with_stderr(self):
-        with self.assertRaisesRegexp(SystemExit, '1'):
+        with self.assertRaisesRegexp(Exception, 'Oops! Something went wrong'):
             js_ts_linter.ThirdPartyJsTsLintChecksManager(
                 INVALID_SORTED_DEPENDENCIES_FILEPATH
             ).perform_all_lint_checks()
@@ -501,7 +501,10 @@ def mock_exists(unused_path):
 
         exists_swap = self.swap(os.path, 'exists', mock_exists)
 
-        with exists_swap, self.assertRaisesRegexp(SystemExit, '1'):
+        with exists_swap, self.assertRaisesRegexp(
+            Exception,
+            'ERROR    Please run start.sh first to install node-eslint and '
+            'its dependencies.'):
             js_ts_linter.ThirdPartyJsTsLintChecksManager(
                 [INVALID_SORTED_DEPENDENCIES_FILEPATH]
             ).perform_all_lint_checks()