mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-10-14 12:15:25 +02:00
## Summary `--push-to` always builds (or retags a local `--image`) and pushes, even when the image already exists at the destination. That breaks CI/CD pipelines where the build/push step and the deploy step run in separate jobs: the deploy job has no local copy of the image to retag, and `--image` requires one (it runs `docker image inspect`, which needs the image present in the local Docker daemon). This adds `--image-uri`, which takes a full image reference already in a registry and deploys it directly via `source_revision_config.image_uri`, with no local Docker involvement at all: no inspect, no build, no tag, no push. It gets the same placement behavior as `--push-to` (`--listener-id`/`--k8s-namespace`, or auto-selecting the sole listener) and the same update-in-place semantics, since both produce an `external_docker` deployment and are interchangeable on the same deployment. `--image-uri` requires a digest (`repo@sha256:...`) and rejects empty/blank input. `--push-to` always resolves to a digest after pushing; `--image-uri` has no push step to resolve one from, so a mutable tag (or an unvalidated empty string) could let Kubernetes silently keep running a previously cached image while the CLI reports success. Implementation: `CustomerRegistrySource`'s image-acquisition step is split into two variants, `BuildAndPush` (the existing `--push-to`/`--image` flow, unchanged behavior) and `PublishedImage` (the new flag), so create/update/placement logic stays shared. Also reworded `_ensure_customer_registry_source`'s error, which previously mentioned only `--push-to` even though it's reachable from `--image-uri` too. ## Test plan - [x] `make format && make lint` clean in `libs/cli` - [x] Unit tests in `test_deploy_helpers.py` for `_select_source` selecting `PublishedImage` (by digest, trimmed), requiring no local Docker, carrying placement, and the mutual-exclusivity + validation errors (`--push-to`, `--image`, `--tag`, `--remote`, empty/blank input, missing digest) - [x] CLI-level tests in `test_deploy_command.py`: create and update an external deployment via `--image-uri` with zero Docker calls, listener auto-placement, rejecting a non-external existing deployment (now mentioning both flags), and the conflicting-flag cases end to end - [x] Full `libs/cli` suite: 524 passed, no regressions