Repository: dbt-labs/dbt-core

Issue:
[Feature] Add a private package definition
### Is this your first time submitting a feature request?

- [X] I have read the [expectations for open source contributors](https://docs.getdbt.com/docs/contributing/oss-expectations)
- [X] I have searched the existing issues, and I could not find an existing issue for this feature
- [X] I am requesting a straightforward extension of existing dbt functionality, rather than a Big Idea better suited to a discussion

### Describe the feature

dbt-cloud is adding support to allow users to define private packages in their `dependencies.yml` or `packages.yml`. The format will be similar to git package definition except that the `git` field will be the `private` field and an additional optional provider field. Example:
```
packages:
  - private: dbt-labs/my-awesome-repo
    # optional configs - same as for 'git' packages
    revision: ... # tag, release, branch, or commit SHA
    subdirectory: ...
	provider: github (if there are multiple providers)
```
In dbt-core, when such a package is defined, we should provide clear error message and tell user to use git definition.

### Describe alternatives you've considered

_No response_

### Who will this benefit?

_No response_

### Are you interested in contributing this feature?

_No response_

### Anything else?

_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
@@ -78,6 +78,16 @@ def get_revisions(self) -> List[str]:
             return [str(self.revision)]
 
 
+@dataclass
+class PrivatePackage(Package):
+    private: str
+    provider: Optional[str] = None
+    revision: Optional[RawVersion] = None
+    warn_unpinned: Optional[bool] = field(default=None, metadata={"alias": "warn-unpinned"})
+    subdirectory: Optional[str] = None
+    unrendered: Dict[str, Any] = field(default_factory=dict)
+
+
 @dataclass
 class RegistryPackage(Package):
     package: str
@@ -92,7 +102,7 @@ def get_versions(self) -> List[str]:
             return [str(self.version)]
 
 
-PackageSpec = Union[LocalPackage, TarballPackage, GitPackage, RegistryPackage]
+PackageSpec = Union[LocalPackage, TarballPackage, GitPackage, RegistryPackage, PrivatePackage]
 
 
 @dataclass
diff --git a/core/dbt/deps/resolver.py b/core/dbt/deps/resolver.py
--- a/core/dbt/deps/resolver.py
+++ b/core/dbt/deps/resolver.py
@@ -7,6 +7,7 @@
     GitPackage,
     LocalPackage,
     PackageSpec,
+    PrivatePackage,
     RegistryPackage,
     TarballPackage,
 )
@@ -16,7 +17,7 @@
 from dbt.deps.registry import RegistryUnpinnedPackage
 from dbt.deps.tarball import TarballUnpinnedPackage
 from dbt.exceptions import (
-    DbtInternalError,
+    DependencyError,
     DuplicateDependencyToRootError,
     DuplicateProjectDependencyError,
     MismatchedDependencyTypeError,
@@ -74,10 +75,14 @@ def update_from(self, src: List[PackageSpec]) -> None:
                 pkg = TarballUnpinnedPackage.from_contract(contract)
             elif isinstance(contract, GitPackage):
                 pkg = GitUnpinnedPackage.from_contract(contract)
+            elif isinstance(contract, PrivatePackage):
+                raise DependencyError(
+                    f'Cannot resolve private package {contract.private} because git provider integration is missing. Please use a "git" package instead.'
+                )
             elif isinstance(contract, RegistryPackage):
                 pkg = RegistryUnpinnedPackage.from_contract(contract)
             else:
-                raise DbtInternalError("Invalid package type {}".format(type(contract)))
+                raise DependencyError("Invalid package type {}".format(type(contract)))
             self.incorporate(pkg)
 
     @classmethod


Test patch:
diff --git a/tests/functional/configs/test_custom_node_colors_configs.py b/tests/functional/configs/test_custom_node_colors_configs.py
--- a/tests/functional/configs/test_custom_node_colors_configs.py
+++ b/tests/functional/configs/test_custom_node_colors_configs.py
@@ -1,5 +1,6 @@
 import pytest
 
+from dbt.exceptions import ConfigUpdateError
 from dbt.tests.util import get_manifest, run_dbt
 from dbt_common.dataclass_schema import ValidationError
 
@@ -304,7 +305,7 @@ def test__invalid_color_config_block(
         self,
         project,
     ):
-        with pytest.raises(ValidationError):
+        with pytest.raises((ValidationError, ConfigUpdateError)):
             run_dbt(["compile"])
 
 
diff --git a/tests/unit/test_deps.py b/tests/unit/test_deps.py
--- a/tests/unit/test_deps.py
+++ b/tests/unit/test_deps.py
@@ -791,6 +791,19 @@ def test_dependency_resolution(self):
         self.assertEqual(resolved[1].name, "dbt-labs-test/b")
         self.assertEqual(resolved[1].version, "0.2.1")
 
+    def test_private_package_raise_error(self):
+        package_config = PackageConfig.from_dict(
+            {
+                "packages": [
+                    {"private": "dbt-labs-test/a", "subdirectory": "foo-bar"},
+                ],
+            }
+        )
+        with self.assertRaisesRegex(
+            dbt.exceptions.DependencyError, "Cannot resolve private package"
+        ):
+            resolve_packages(package_config.packages, mock.MagicMock(project_name="test"), {})
+
     def test_dependency_resolution_allow_prerelease(self):
         package_config = PackageConfig.from_dict(
             {