From c4a5cb4d2f6259600a814d269414dbef896e4154 Mon Sep 17 00:00:00 2001 From: gdibben Date: Wed, 14 Oct 2026 08:58:15 +0100 Subject: [PATCH] Reject --image-pull-secret when a --name lookup finds an existing deployment --image-pull-secret was only guarded against an existing --deployment-id. If --name (or the default name) resolved to an existing deployment instead, CustomerRegistrySource._update silently dropped the secrets: the image pull secret the user intended never reached the control plane and the revision could fail with ImagePullBackOff with no warning. --- libs/cli/langgraph_cli/deploy.py | 7 +++++++ .../tests/unit_tests/cli/test_deploy_command.py | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/libs/cli/langgraph_cli/deploy.py b/libs/cli/langgraph_cli/deploy.py index e992587b5..12908393a 100644 --- a/libs/cli/langgraph_cli/deploy.py +++ b/libs/cli/langgraph_cli/deploy.py @@ -1682,6 +1682,13 @@ class CustomerRegistrySource: ) -> DeployOutcome: _ensure_customer_registry_source(existing) self.requested_placement.ensure_not_requested(existing.id) + if self.image_pull_secrets: + raise click.UsageError( + "Image pull secrets are fixed when a deployment is created. " + f"Deployment {existing.id} already exists, so drop " + "--image-pull-secret, or create a new deployment with a " + "different --name." + ) image_uri, step = self._publish(ctx, step) _log_deploy_step(step, f"Updating deployment {existing.id}") updated = ctx.client.update_deployment( diff --git a/libs/cli/tests/unit_tests/cli/test_deploy_command.py b/libs/cli/tests/unit_tests/cli/test_deploy_command.py index 3aa5e8414..39847fd71 100644 --- a/libs/cli/tests/unit_tests/cli/test_deploy_command.py +++ b/libs/cli/tests/unit_tests/cli/test_deploy_command.py @@ -981,6 +981,23 @@ def test_image_pull_secret_cannot_update_an_existing_deployment( assert deploy_project.timeline == [] +def test_image_pull_secret_cannot_update_a_deployment_found_by_name( + deploy_project: DeployProject, +) -> None: + deploy_project.control_plane.existing_deployments = [ + {"id": "dep-ext", "name": "my-app", "source": "external_docker"} + ] + + result = deploy_project.run( + "--image-uri", EXTERNAL_DIGEST, "--image-pull-secret", "regcred" + ) + + assert result.exit_code != 0 + assert "--image-pull-secret" in result.output + assert deploy_project.docker.verbs() == [] + assert _patch("dep-ext") not in deploy_project.timeline + + def test_updating_a_deployment_never_looks_up_listeners( deploy_project: DeployProject, ) -> None: