Repository: dbt-labs/dbt-core

Issue:
[Bug] dbt hangs when packages have empty values
### Is this a new bug in dbt-core?

- [X] I believe this is a new bug in dbt-core
- [X] I have searched the existing issues, and I could not find an existing issue for this bug

### Current Behavior

When a package is defined as 

```
packages:
    - local: ""  
```

Running `dbt deps` results in dbt hanging.

### Expected Behavior

Get an error that the value is am empty string

### Steps To Reproduce

Define a packages.yml in a dbt project as
```
```
packages:
    - local: ""  
```

run `dbt deps`

### Relevant log output

_No response_

### Environment

```markdown
- OS:
- Python:
- dbt:
```


### Which database adapter are you using with dbt?

_No response_

### Additional Context

_No response_


Discussion:

Resolving patch:
diff --git a/core/dbt/contracts/project.py b/core/dbt/contracts/project.py
--- a/core/dbt/contracts/project.py
+++ b/core/dbt/contracts/project.py
@@ -101,13 +101,26 @@ class PackageConfig(dbtClassMixin):
     @classmethod
     def validate(cls, data):
         for package in data.get("packages", data):
+            # This can happen when the target is a variable that is not filled and results in hangs
+            if isinstance(package, dict):
+                if package.get("package") == "":
+                    raise ValidationError(
+                        "A hub package is missing the value. It is a required property."
+                    )
+                if package.get("local") == "":
+                    raise ValidationError(
+                        "A local package is missing the value. It is a required property."
+                    )
+                if package.get("git") == "":
+                    raise ValidationError(
+                        "A git package is missing the value. It is a required property."
+                    )
             if isinstance(package, dict) and package.get("package"):
                 if not package["version"]:
                     raise ValidationError(
                         f"{package['package']} is missing the version. When installing from the Hub "
                         "package index, version is a required property"
                     )
-
                 if "/" not in package["package"]:
                     raise ValidationError(
                         f"{package['package']} was not found in the package index. Packages on the index "


Test patch:
diff --git a/tests/functional/dependencies/test_simple_dependency.py b/tests/functional/dependencies/test_simple_dependency.py
--- a/tests/functional/dependencies/test_simple_dependency.py
+++ b/tests/functional/dependencies/test_simple_dependency.py
@@ -434,3 +434,44 @@ def test_malformed_tarball_package_causes_exception(self, project):
         ) as e:
             run_dbt(["deps"])
             assert e is not None
+
+
+class TestEmptyDependency:
+    def test_empty_package(self, project):
+        # We have to specify the bad formatted package here because if we do it
+        # in a `packages` fixture, the test will blow up in the setup phase, meaning
+        # we can't appropriately catch it with a `pytest.raises`
+        empty_hub_package = {
+            "packages": [
+                {
+                    "package": "",
+                    "version": "1.0.0",
+                }
+            ]
+        }
+        write_config_file(empty_hub_package, "packages.yml")
+        with pytest.raises(DbtProjectError, match="A hub package is missing the value"):
+            run_dbt(["deps"])
+
+        empty_git_package = {
+            "packages": [
+                {
+                    "git": "",
+                    "revision": "1.0.0",
+                }
+            ]
+        }
+        write_config_file(empty_git_package, "packages.yml")
+        with pytest.raises(DbtProjectError, match="A git package is missing the value"):
+            run_dbt(["deps"])
+
+        empty_local_package = {
+            "packages": [
+                {
+                    "local": "",
+                }
+            ]
+        }
+        write_config_file(empty_local_package, "packages.yml")
+        with pytest.raises(DbtProjectError, match="A local package is missing the value"):
+            run_dbt(["deps"])