Repository: meltano/meltano

Issue:
Use default deployment by default
Context:
- https://github.com/meltano/meltano/pull/7718#issuecomment-1570501300

We currently have a `meltano cloud deployment use` command which sets the default deployment to use for future commands. It does this by setting a field in the Cloud CLI config. This setting is not used by anything other than the code which displays whether a deployment is the default. It should be used whenever the `--deployment` CLI option is not provided.


Discussion:

Resolving patch:
diff --git a/src/cloud-cli/meltano/cloud/cli/run.py b/src/cloud-cli/meltano/cloud/cli/run.py
--- a/src/cloud-cli/meltano/cloud/cli/run.py
+++ b/src/cloud-cli/meltano/cloud/cli/run.py
@@ -40,7 +40,6 @@ async def run_project(
 @click.argument("job_or_schedule")
 @click.option(
     "--deployment",
-    required=True,
     help="The name of the Meltano Cloud deployment to run in.",
 )
 @pass_context
@@ -48,9 +47,18 @@ async def run_project(
 async def run(
     context: MeltanoCloudCLIContext,
     job_or_schedule: str,
-    deployment: str,
+    deployment: str | None = None,
 ) -> None:
     """Run a Meltano project in Meltano Cloud."""
+    deployment = (
+        deployment if deployment is not None else context.config.default_deployment_name
+    )
+    if deployment is None:
+        raise click.UsageError(
+            "A deployment name is required. Please specify "
+            "one with the '--deployment' option, or specify a default"
+            "deployment by running 'meltano cloud deployment use'.",
+        )
     click.echo("Running a Meltano project in Meltano Cloud.")
 
     result = await run_project(
diff --git a/src/cloud-cli/meltano/cloud/cli/schedule.py b/src/cloud-cli/meltano/cloud/cli/schedule.py
--- a/src/cloud-cli/meltano/cloud/cli/schedule.py
+++ b/src/cloud-cli/meltano/cloud/cli/schedule.py
@@ -150,8 +150,17 @@ async def _set_enabled_state(
 ):
     if schedule_name is None:
         raise click.UsageError("Missing option '--schedule'")
+    deployment_name = (
+        deployment_name
+        if deployment_name is not None
+        else config.default_deployment_name
+    )
     if deployment_name is None:
-        raise click.UsageError("Missing option '--deployment'")
+        raise click.UsageError(
+            "A deployment name is required. Please specify "
+            "one with the '--deployment' option, or specify a default"
+            "deployment by running 'meltano cloud deployment use'.",
+        )
     async with SchedulesCloudClient(config=config) as client:
         await client.set_schedule_enabled(
             deployment_name=deployment_name,


Test patch:
diff --git a/src/cloud-cli/tests/cli/test_run.py b/src/cloud-cli/tests/cli/test_run.py
--- a/src/cloud-cli/tests/cli/test_run.py
+++ b/src/cloud-cli/tests/cli/test_run.py
@@ -48,3 +48,55 @@ def test_run_ok(
         )
         assert result.exit_code == 0
         assert "Running a Meltano project in Meltano Cloud" in result.output
+
+    def test_run_ok_with_default_deployment(
+        self,
+        tenant_resource_key: str,
+        internal_project_id: str,
+        config: MeltanoCloudConfig,
+        httpserver: HTTPServer,
+    ):
+        deployment = "default-sandbox"
+        job_or_schedule = "daily"
+        path = (
+            f"/run/v1/external/"
+            f"{tenant_resource_key}/{internal_project_id}/"
+            f"{deployment}/{job_or_schedule}"
+        )
+        config.default_deployment_name = deployment
+        config.write_to_file()
+        httpserver.expect_oneshot_request(path).respond_with_data(
+            b"Running a Meltano project in Meltano Cloud",
+        )
+        result = CliRunner().invoke(
+            cli,
+            ["--config-path", config.config_path, "run", job_or_schedule],
+        )
+        assert result.exit_code == 0
+        assert "Running a Meltano project in Meltano Cloud" in result.output
+
+    def test_run_fails_when_missing_deployment(
+        self,
+        tenant_resource_key: str,
+        internal_project_id: str,
+        config: MeltanoCloudConfig,
+        httpserver: HTTPServer,
+    ):
+        deployment = "default-sandbox"
+        job_or_schedule = "daily"
+        path = (
+            f"/run/v1/external/"
+            f"{tenant_resource_key}/{internal_project_id}/"
+            f"{deployment}/{job_or_schedule}"
+        )
+        config.default_deployment_name = None
+        config.write_to_file()
+        httpserver.expect_oneshot_request(path).respond_with_data(
+            b"Running a Meltano project in Meltano Cloud",
+        )
+        result = CliRunner().invoke(
+            cli,
+            ["--config-path", config.config_path, "run", job_or_schedule],
+        )
+        assert result.exit_code == 2
+        assert "A deployment name is required." in result.output
diff --git a/src/cloud-cli/tests/cli/test_schedules.py b/src/cloud-cli/tests/cli/test_schedules.py
--- a/src/cloud-cli/tests/cli/test_schedules.py
+++ b/src/cloud-cli/tests/cli/test_schedules.py
@@ -49,6 +49,64 @@ def test_schedule_enable(
                 assert result.exit_code == 0, result.output
                 assert not result.output
 
+    def test_schedule_enable_with_default_deployment(
+        self,
+        tenant_resource_key: str,
+        internal_project_id: str,
+        config: MeltanoCloudConfig,
+        httpserver: HTTPServer,
+    ):
+        path = (
+            f"/schedules/v1/{tenant_resource_key}/{internal_project_id}"
+            "/test-deployment/daily/enabled"
+        )
+        config.default_deployment_name = "test-deployment"
+        config.write_to_file()
+        runner = CliRunner()
+        for cmd in ("enable", "disable"):
+            httpserver.expect_oneshot_request(path).respond_with_data(status=204)
+            result = runner.invoke(
+                cli,
+                (
+                    "--config-path",
+                    config.config_path,
+                    "schedule",
+                    cmd,
+                    "--schedule=daily",
+                ),
+            )
+            assert result.exit_code == 0, result.output
+            assert not result.output
+
+    def test_schedule_enable_with_missing_deployment(
+        self,
+        tenant_resource_key: str,
+        internal_project_id: str,
+        config: MeltanoCloudConfig,
+        httpserver: HTTPServer,
+    ):
+        path = (
+            f"/schedules/v1/{tenant_resource_key}/{internal_project_id}"
+            "/test-deployment/daily/enabled"
+        )
+        config.default_deployment_name = None
+        config.write_to_file()
+        runner = CliRunner()
+        for cmd in ("enable", "disable"):
+            httpserver.expect_oneshot_request(path).respond_with_data(status=204)
+            result = runner.invoke(
+                cli,
+                (
+                    "--config-path",
+                    config.config_path,
+                    "schedule",
+                    cmd,
+                    "--schedule=daily",
+                ),
+            )
+            assert result.exit_code == 2, result.output
+            assert "A deployment name is required." in result.output
+
     @pytest.fixture()
     def schedules(self) -> list[CloudProjectSchedule]:
         return [