Repository: PrefectHQ/prefect

Issue:
Deployment name with slashes get truncated
### First check

- [X] I added a descriptive title to this issue.
- [X] I used the GitHub search to find a similar issue and didn't find it.
- [X] I searched the Prefect documentation for this issue.
- [X] I checked that this issue is related to Prefect and not one of its dependencies.

### Bug summary

Deployment names containing slashes don't behave quite as you expect. For example, `foo/bar` will simply get truncated to `bar`, however it will still render as `foo/bar` during creation. Slashes should either be disallowed by validation, or kept intact.

### Reproduction

```python3
from prefect import flow

hello = flow.from_source(
    source="https://gist.github.com/12fdaec39c8af9437a2c529857bd5388.git",
    entrypoint="hello.py:hello"
)

hello.deploy(
    name="foo/bar",
    work_pool_name="managed"
)
```


### Error

```python3
(default) ➜  github python slash.py 
Successfully created/updated all deployments!

           Deployments           
┏━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
┃ Name      ┃ Status  ┃ Details ┃
┡━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━┩
│ hello/bar │ applied │         │
└───────────┴─────────┴─────────┘

To schedule a run for this deployment, use the following command:

        $ prefect deployment run 'hello/foo/bar'


You can also run your flow via the Prefect UI: 
https://app.prefect.cloud/account/9b649228-0419-40e1-9e0d-44954b5c0ab6/workspace/6d2a6913-f3a5-4f76-9d91-8f9d674f2c53/deployments/deployment/e291daa8-d015-44ed-93
7d-ce2a98c48be3

(default) ➜  github prefect deployments ls 
                                           Deployments                                           
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Name                                                   ┃ ID                                   ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ hello/bar                                              │ e291daa8-d015-44ed-937d-ce2a98c48be3 │
└────────────────────────────────────────────────────────┴──────────────────────────────────────┘

(default) ➜  github prefect deployments inspect 'hello/bar'
{
    'id': 'e291daa8-d015-44ed-937d-ce2a98c48be3',
    'created': '2023-12-27T13:00:12.524041+00:00',
    'updated': '2023-12-27T13:01:44.070007+00:00',
    'name': 'bar',
    'version': 'e04753db84d94a5a20a3b60f1ba8a4a1',
    'description': None,
    'flow_id': '556dc344-a889-40b2-aede-edfbf82800a8',
    'schedule': None,
    'is_schedule_active': True,
    'infra_overrides': {},
    'parameters': {},
    'tags': [],
    'work_queue_name': 'default',
    'last_polled': None,
    'parameter_openapi_schema': {
        'type': 'object',
        'title': 'Parameters',
        'properties': {'name': {'type': 'string', 'title': 'name', 'default': 'Marvin', 'position': 0}}
    },
    'path': None,
    'pull_steps': [{'prefect.deployments.steps.git_clone': {'branch': None, 'repository': 'https://gist.github.com/12fdaec39c8af9437a2c529857bd5388.git'}}],
    'entrypoint': 'hello.py:hello',
    'manifest_path': None,
    'storage_document_id': None,
    'infrastructure_document_id': None,
    'created_by': {'id': '<USER_ID>', 'type': 'USER', 'display_value': 'emilrex'},
    'updated_by': {'id': '<USER_ID>', 'type': 'USER', 'display_value': 'emilrex'},
    'work_pool_name': 'managed',
    'status': 'READY',
    'enforce_parameter_schema': False,
    'automations': []
}

(default) ➜  github prefect deployments inspect 'hello/foo/bar'
Deployment 'hello/foo/bar' not found!

(default) ➜  github prefect deployment run 'hello/foo/bar'
Deployment 'hello/foo/bar' not found!
```


### Versions

```Text
Version:             2.14.12
API version:         0.8.4
Python version:      3.9.18
Git commit:          5a2482d0
Built:               Wed, Dec 20, 2023 4:58 PM
OS/Arch:             darwin/arm64
Profile:             personal
Server type:         cloud
```


### Additional context

_No response_


Discussion:

Resolving patch:
diff --git a/src/prefect/flows.py b/src/prefect/flows.py
--- a/src/prefect/flows.py
+++ b/src/prefect/flows.py
@@ -623,6 +623,12 @@ def my_other_flow(name):
         """
         from prefect.deployments.runner import RunnerDeployment
 
+        if "/" in name and not name.endswith(".py"):
+            raise ValueError(
+                f"Invalid deployment name {name!r}. Deployment names cannot contain"
+                " forward slashes."
+            )
+
         if self._storage and self._entrypoint:
             return await RunnerDeployment.from_storage(
                 storage=self._storage,


Test patch:
diff --git a/tests/test_flows.py b/tests/test_flows.py
--- a/tests/test_flows.py
+++ b/tests/test_flows.py
@@ -3255,6 +3255,15 @@ async def test_to_deployment_accepts_rrule(self):
 
         assert deployment.schedule == RRuleSchedule(rrule="FREQ=MINUTELY")
 
+    async def test_to_deployment_fails_forward_slash(self):
+        name = "test/deployment"
+        expected_message = (
+            f"Invalid deployment name {name!r}. Deployment names cannot contain"
+            " forward slashes."
+        )
+        with pytest.raises(ValueError, match=expected_message):
+            await test_flow.to_deployment(name)
+
     @pytest.mark.parametrize(
         "kwargs",
         [