Repository: mlflow/mlflow

Issue:
[BUG]  'env_activate_cmd' referenced before assignment when using mlflow models build-docker --env-manager=local
### Willingness to contribute

Yes. I can contribute a fix for this bug independently.

### MLflow version

1.26.1

### System information

- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: Archlinux
- **Python version**: 3.9.9




### Describe the problem

I have a very tiny mlflow pyfunc model which I can build into a docker using
```bash
mlflow models build-docker --model-uri 'models:/predict_service/latest' --enable-mlserver --name predict_service
```
When using `--env-manager=local`, I get a Python error saying:

```bash
  2022/06/10 10:00:47 INFO mlflow.models.container: creating and activating custom environment
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/usr/local/lib/python3.7/dist-packages/mlflow/models/container/__init__.py", line 124, in _install_pyfunc_deps
      activate_cmd = [env_activate_cmd] if has_env else []
  UnboundLocalError: local variable 'env_activate_cmd' referenced before assignment
```
Which refers to https://github.com/mlflow/mlflow/blob/master/mlflow/models/container/__init__.py#L124 where indeed the variable is reference before assignment.


### Tracking information

_No response_

### Code to reproduce issue

mlflow models build-docker --model-uri 'models:/predict_service/latest' --enable-mlserver --name predict_service --env-manager=local

### Other info / logs

_No response_

### What component(s) does this bug affect?

- [ ] `area/artifacts`: Artifact stores and artifact logging
- [X] `area/build`: Build and test infrastructure for MLflow
- [ ] `area/docs`: MLflow documentation pages
- [ ] `area/examples`: Example code
- [ ] `area/model-registry`: Model Registry service, APIs, and the fluent client calls for Model Registry
- [ ] `area/models`: MLmodel format, model serialization/deserialization, flavors
- [ ] `area/projects`: MLproject format, project running backends
- [ ] `area/scoring`: MLflow Model server, model deployment tools, Spark UDFs
- [ ] `area/server-infra`: MLflow Tracking server backend
- [ ] `area/tracking`: Tracking Service, tracking client APIs, autologging

### What interface(s) does this bug affect?

- [ ] `area/uiux`: Front-end, user experience, plotting, JavaScript, JavaScript dev server
- [ ] `area/docker`: Docker use across MLflow's components, such as MLflow Projects and MLflow Models
- [ ] `area/sqlalchemy`: Use of SQLAlchemy in the Tracking Service or Model Registry
- [ ] `area/windows`: Windows support

### What language(s) does this bug affect?

- [ ] `language/r`: R APIs and clients
- [ ] `language/java`: Java APIs and clients
- [ ] `language/new`: Proposals for new client languages

### What integration(s) does this bug affect?

- [ ] `integrations/azure`: Azure and Azure ML integrations
- [ ] `integrations/sagemaker`: SageMaker integrations
- [ ] `integrations/databricks`: Databricks integrations


Discussion:
Hi @bneijt, thanks for reporting this issue. Can you fix this issue?
We can fix `mlflow/models/container/__init__.py` like this:

```diff
diff --git a/mlflow/models/container/__init__.py b/mlflow/models/container/__init__.py
index 1c56997dd..0f7b58b41 100644
--- a/mlflow/models/container/__init__.py
+++ b/mlflow/models/container/__init__.py
@@ -94,7 +94,7 @@ def _install_pyfunc_deps(
     dependencies into the environment - MLflow is not installed as it's not available via conda.
     """
     # If model is a pyfunc model, create its conda env (even if it also has mleap flavor)
-    has_env = False
+    activate_cmd = []
     if model_path:
         model_config_path = os.path.join(model_path, MLMODEL_FILE_NAME)
         model = Model.load(model_config_path)
@@ -116,12 +116,13 @@ def _install_pyfunc_deps(
                 if Popen(["bash", "-c", conda_create_model_env]).wait() != 0:
                     raise Exception("Failed to create model environment.")
                 env_activate_cmd = "source /miniconda/bin/activate custom_env"
+                activate_cmd = [env_activate_cmd]
             elif env_manager == em.VIRTUALENV:
                 env_activate_cmd = _get_or_create_virtualenv(model_path)
                 path = env_activate_cmd.split(" ")[-1]
                 os.symlink(path, "/opt/activate")
-            has_env = True
-    activate_cmd = [env_activate_cmd] if has_env else []
+                activate_cmd = [env_activate_cmd]
+
     # NB: install gunicorn[gevent] from pip rather than from conda because gunicorn is already
     # dependency of mlflow on pip and we expect mlflow to be part of the environment.
     server_deps = ["gunicorn[gevent]"]
```

Resolving patch:
diff --git a/mlflow/models/container/__init__.py b/mlflow/models/container/__init__.py
--- a/mlflow/models/container/__init__.py
+++ b/mlflow/models/container/__init__.py
@@ -94,7 +94,7 @@ def _install_pyfunc_deps(
     dependencies into the environment - MLflow is not installed as it's not available via conda.
     """
     # If model is a pyfunc model, create its conda env (even if it also has mleap flavor)
-    has_env = False
+    activate_cmd = []
     if model_path:
         model_config_path = os.path.join(model_path, MLMODEL_FILE_NAME)
         model = Model.load(model_config_path)
@@ -115,13 +115,13 @@ def _install_pyfunc_deps(
                 conda_create_model_env = "conda env create -n custom_env -f {}".format(env_path_dst)
                 if Popen(["bash", "-c", conda_create_model_env]).wait() != 0:
                     raise Exception("Failed to create model environment.")
-                env_activate_cmd = "source /miniconda/bin/activate custom_env"
+                activate_cmd = ["source /miniconda/bin/activate custom_env"]
             elif env_manager == em.VIRTUALENV:
                 env_activate_cmd = _get_or_create_virtualenv(model_path)
                 path = env_activate_cmd.split(" ")[-1]
                 os.symlink(path, "/opt/activate")
-            has_env = True
-    activate_cmd = [env_activate_cmd] if has_env else []
+                activate_cmd = [env_activate_cmd]
+    
     # NB: install gunicorn[gevent] from pip rather than from conda because gunicorn is already
     # dependency of mlflow on pip and we expect mlflow to be part of the environment.
     server_deps = ["gunicorn[gevent]"]
@@ -132,7 +132,7 @@ def _install_pyfunc_deps(
     if Popen(["bash", "-c", " && ".join(activate_cmd + install_server_deps)]).wait() != 0:
         raise Exception("Failed to install serving dependencies into the model environment.")
 
-    if has_env and install_mlflow:
+    if len(activate_cmd) and install_mlflow:
         install_mlflow_cmd = [
             "pip install /opt/mlflow/."
             if _container_includes_mlflow_source()


Test patch: