Repository: conda/conda

Issue:
conda run is not preserving exit code
## Current Behavior
`conda run` used to return the correct exit status of the target process, but it doesn't anymore. This was apparently working correctly in conda 4.8.0 but it seems broken since version 4.8.1. `conda run` now erroneously always return the exit status of 0. This is a serious problem as jobs fail silently now.

### Steps to Reproduce
```
$ conda -V
conda 4.8.1
$ conda run -n myenv /usr/bin/true; echo $?
0
$ conda run -n myenv /usr/bin/false; echo $?
ERROR conda.cli.main_run:execute(30): Subprocess for 'conda run ['/usr/bin/false']' command failed.  (See above for error)
0
```

## Expected Behavior
`conda run` should preserve the exit status of the target process, whether the target is `python` or otherwise. It worked correctly with the previous version:
```
$ conda -V
conda 4.8.0
$ conda run -n base /usr/bin/true; echo $?
0
$ conda run -n base /usr/bin/false; echo $?
ERROR conda.cli.main_run:execute(39): Subprocess for 'conda run ['/usr/bin/false']' command failed.  Stderr was:

1
```

## Environment Information
This issue really is independent of the environment as it happens both in various dockerfiles and on MacOS too.

---

@msarahan Please fix this bug considering I see a commit from 25 days that may have introduced it! Adding unit tests would also be wise.


Discussion:
Our team have many things to work on. PRs that try to fix this would be welcome if you are interested. Conda run is still not ready for prime time usage unfortunately.
We are not churning out new conda features. 
It appears commit https://github.com/conda/conda/commit/c7d5ada5d0a6038e81f9ab10380e5e69c7d65d1c introduced the error.

Returning a namedtuple (Response) instead of an int breaks this logic https://github.com/conda/conda/blob/e9a50561880696e57ba80472dce332e08e58ee0b/conda/cli/main.py#L84-L86

I can create a pull request to fix. Thoughts on reverting the return value to an int vs expanding the logic at the call site in main.py?  I can't find rationale for changing the return value.


Resolving patch:
diff --git a/conda/cli/main.py b/conda/cli/main.py
--- a/conda/cli/main.py
+++ b/conda/cli/main.py
@@ -84,6 +84,8 @@ def _main(*args, **kwargs):
     exit_code = do_call(args, p)
     if isinstance(exit_code, int):
         return exit_code
+    elif hasattr(exit_code, 'rc'):
+        return exit_code.rc
 
 
 if sys.platform == 'win32' and sys.version_info[0] == 2:


Test patch:
diff --git a/tests/test_cli.py b/tests/test_cli.py
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -162,3 +162,34 @@ def test_search_4(self):
     @pytest.mark.integration
     def test_search_5(self):
         self.assertIsInstance(capture_json_with_argv('conda search --platform win-32 --json'), dict)
+
+class TestRun(unittest.TestCase):
+    def test_run_returns_int(self):
+        from tests.test_create import make_temp_env
+        from tests.test_create import make_temp_prefix
+
+        prefix = make_temp_prefix(name='test')
+        with make_temp_env(prefix=prefix):
+            stdout, stderr, result = run_inprocess_conda_command('conda run -p {} echo hi'.format(prefix))
+            
+            assert isinstance(result, int)
+
+    def test_run_returns_zero_errorlevel(self):
+        from tests.test_create import make_temp_env
+        from tests.test_create import make_temp_prefix
+
+        prefix = make_temp_prefix(name='test')
+        with make_temp_env(prefix=prefix):
+            stdout, stderr, result = run_inprocess_conda_command('conda run -p {} exit 0'.format(prefix))
+            
+            assert result == 0
+
+    def test_run_returns_nonzero_errorlevel(self):
+        from tests.test_create import make_temp_env
+        from tests.test_create import make_temp_prefix
+
+        prefix = make_temp_prefix(name='test')
+        with make_temp_env(prefix=prefix) as prefix:
+            stdout, stderr, result = run_inprocess_conda_command('conda run -p "{}" exit 5'.format(prefix))
+            
+            assert result == 5