Repository: PrefectHQ/prefect

Issue:
deployments.run_deployment should support idempotency_key
### First check

- [X] I added a descriptive title to this issue.
- [X] I used the GitHub search to find a similar request and didn't find it.
- [X] I searched the Prefect documentation for this feature.

### Prefect Version

2.x

### Describe the current behavior

deployments.run_deployment uses create_flow_run_from_deployment, but does not allow us to set the idempotency _key.
This causes duplicate flow runs for us.

### Describe the proposed behavior

add optional idempotency_key argument to run_deployment and pass it to  create_flow_run_from_deployment.

### Example Use

```  
await run_deployment(
    name=f"{flow_name}/default",
    parameters={'q', 42},
    scheduled_time = my_time,
    flow_run_name = my_run_name,
    timeout = 0,
    idempotency_key = my_external_id
  )
```

### Additional context

_No response_


Discussion:

Resolving patch:
diff --git a/src/prefect/deployments.py b/src/prefect/deployments.py
--- a/src/prefect/deployments.py
+++ b/src/prefect/deployments.py
@@ -7,7 +7,7 @@
 import sys
 from datetime import datetime
 from pathlib import Path
-from typing import Any, Dict, List, Optional
+from typing import Any, Dict, Iterable, List, Optional
 from uuid import UUID
 
 import anyio
@@ -49,6 +49,8 @@ async def run_deployment(
     flow_run_name: str = None,
     timeout: float = None,
     poll_interval: float = 5,
+    tags: Optional[Iterable[str]] = None,
+    idempotency_key: str = None,
 ):
     """
     Create a flow run for a deployment and return it after completion or a timeout.
@@ -115,9 +117,11 @@ async def run_deployment(
 
     flow_run = await client.create_flow_run_from_deployment(
         deployment.id,
-        state=Scheduled(scheduled_time=scheduled_time),
         parameters=parameters,
+        state=Scheduled(scheduled_time=scheduled_time),
         name=flow_run_name,
+        tags=tags,
+        idempotency_key=idempotency_key,
         parent_task_run_id=parent_task_run_id,
     )
 


Test patch:
diff --git a/tests/test_deployments.py b/tests/test_deployments.py
--- a/tests/test_deployments.py
+++ b/tests/test_deployments.py
@@ -738,6 +738,37 @@ def test_custom_flow_run_names(self, test_deployment, use_hosted_orion):
 
         assert flow_run.name == "a custom flow run name"
 
+    def test_accepts_tags(self, test_deployment):
+        d, deployment_id = test_deployment
+
+        flow_run = run_deployment(
+            f"{d.flow_name}/{d.name}",
+            tags=["I", "love", "prefect"],
+            timeout=0,
+            poll_interval=0,
+        )
+
+        assert sorted(flow_run.tags) == ["I", "love", "prefect"]
+
+    def test_accepts_idempotency_key(self, test_deployment):
+        d, deployment_id = test_deployment
+
+        flow_run_a = run_deployment(
+            f"{d.flow_name}/{d.name}",
+            idempotency_key="12345",
+            timeout=0,
+            poll_interval=0,
+        )
+
+        flow_run_b = run_deployment(
+            f"{d.flow_name}/{d.name}",
+            idempotency_key="12345",
+            timeout=0,
+            poll_interval=0,
+        )
+
+        assert flow_run_a.id == flow_run_b.id
+
     async def test_links_to_parent_flow_run_when_used_in_flow(
         self, test_deployment, use_hosted_orion, orion_client: OrionClient
     ):