Compare commits

..
Author SHA1 Message Date
Parker Rule 502053a050 refactor(cli): simplify single-layer Dockerfile generation 2026-08-27 21:15:18 -04:00
Parker Rule 58273fde86 feat(cli): support layer mode from environment 2026-08-25 22:36:09 -04:00
Parker Rule aeb9cdfef1 feat(cli): support single-layer user builds 2026-08-25 22:31:15 -04:00
John KennedyGitHublangsmith-fleet[bot] <langsmith-fleet[bot]@users.noreply.github.com>
38031739e5 docs: add Corridor agent instructions (#8677)
Add a repository-wide `<corridor>` block to `AGENTS.md` requiring agents
to plan first and run Corridor `analyzePlan` before generating or
modifying code. The tags are explicit and balanced so Corridor-specific
guidance remains scoped.

Validation: `git diff --check` and a tag-balance assertion.

---------

Co-authored-by: langsmith-fleet[bot] <langsmith-fleet[bot]@users.noreply.github.com>
2026-08-24 14:42:27 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
f09cfe8ffc chore(deps): bump langgraph-checkpoint-postgres from 3.0.5 to 3.1.1 in /libs/cli/uv-examples/monorepo in the uv group across 1 directory (#8646)
Bumps the uv group with 1 update in the /libs/cli/uv-examples/monorepo
directory:
[langgraph-checkpoint-postgres](https://github.com/langchain-ai/langgraph).

Updates `langgraph-checkpoint-postgres` from 3.0.5 to 3.1.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/langchain-ai/langgraph/releases">langgraph-checkpoint-postgres's
releases</a>.</em></p>
<blockquote>
<h2>langgraph-checkpoint-postgres==3.1.1</h2>
<p>Changes since checkpointpostgres==3.1.0</p>
<ul>
<li>release(checkpoint-postgres): 3.1.1 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8480">#8480</a>)</li>
<li>fix(checkpoint-postgres,checkpoint-sqlite): scope namespace matching
to segment boundaries (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8478">#8478</a>)</li>
<li>feat(checkpoint,checkpoint-postgres): add opt-in omit_expired to
skip expired rows on read (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8354">#8354</a>)</li>
<li>chore(deps): bump the minor-and-patch group in
/libs/checkpoint-postgres with 5 updates (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8250">#8250</a>)</li>
<li>chore(deps): bump langsmith from 0.8.0 to 0.8.18 in
/libs/checkpoint-postgres (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8171">#8171</a>)</li>
<li>docs: standardize package <code>README.md</code> structure (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8064">#8064</a>)</li>
<li>chore: migrate Python type checking to ty (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8002">#8002</a>)</li>
<li>chore(deps): bump the minor-and-patch group in
/libs/checkpoint-postgres with 7 updates (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7965">#7965</a>)</li>
<li>release(checkpoint): 4.1.1 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7890">#7890</a>)</li>
<li>chore(deps): bump idna from 3.11 to 3.15 in
/libs/checkpoint-postgres (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7861">#7861</a>)</li>
<li>chore(deps): bump langsmith from 0.7.31 to 0.8.0 in
/libs/checkpoint-postgres (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7785">#7785</a>)</li>
</ul>
<h2>langgraph-checkpoint-sqlite==3.1.1</h2>
<p>Changes since checkpointsqlite==3.1.0</p>
<ul>
<li>release(checkpoint-sqlite): 3.1.1 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8481">#8481</a>)</li>
<li>fix(checkpoint-postgres,checkpoint-sqlite): scope namespace matching
to segment boundaries (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8478">#8478</a>)</li>
<li>chore(deps): bump the minor-and-patch group in
/libs/checkpoint-sqlite with 4 updates (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8249">#8249</a>)</li>
<li>chore(deps): bump langsmith from 0.8.0 to 0.8.18 in
/libs/checkpoint-sqlite (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8177">#8177</a>)</li>
<li>docs: standardize package <code>README.md</code> structure (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8064">#8064</a>)</li>
<li>chore: migrate Python type checking to ty (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8002">#8002</a>)</li>
<li>chore(deps): bump the minor-and-patch group in
/libs/checkpoint-sqlite with 3 updates (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7961">#7961</a>)</li>
<li>release(checkpoint): 4.1.1 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7890">#7890</a>)</li>
<li>chore(deps): bump langsmith from 0.7.31 to 0.8.0 in
/libs/checkpoint-sqlite (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7786">#7786</a>)</li>
<li>chore(deps): bump idna from 3.11 to 3.15 in /libs/checkpoint-sqlite
(<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7862">#7862</a>)</li>
</ul>
<h2>langgraph-checkpoint-postgres==3.1.0</h2>
<p>Changes since checkpointpostgres==3.1.0a4</p>
<ul>
<li>release: bump alpha packages to official versions (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7775">#7775</a>)</li>
<li>chore(deps): bump urllib3 from 2.6.3 to 2.7.0 in
/libs/checkpoint-postgres (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7761">#7761</a>)</li>
<li>chore(deps): bump langchain-core from 1.3.2 to 1.3.3 in
/libs/checkpoint-postgres (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7754">#7754</a>)</li>
<li>fix(checkpoint-postgres): add column aliases to seed-blob branch of
delta stage-2 UNION ALL (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7728">#7728</a>)</li>
</ul>
<h2>langgraph-checkpoint-sqlite==3.1.0</h2>
<p>Changes since checkpointsqlite==3.1.0a1</p>
<ul>
<li>release: bump alpha packages to official versions (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7775">#7775</a>)</li>
<li>chore(deps): bump urllib3 from 2.6.3 to 2.7.0 in
/libs/checkpoint-sqlite (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7760">#7760</a>)</li>
<li>chore(deps): bump langchain-core from 1.2.28 to 1.3.3 in
/libs/checkpoint-sqlite (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7751">#7751</a>)</li>
<li>chore: remove keepset helper (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7745">#7745</a>)</li>
<li>chore(langgraph): add guide/conformance for delta channel
checkpointer (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7736">#7736</a>)</li>
</ul>
<h2>langgraph-checkpoint-postgres==3.1.0a4</h2>
<p>Changes since checkpointpostgres==3.1.0a3</p>
<ul>
<li>release: alpha bump (a4) for langgraph, checkpoint,
checkpoint-postgres (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/7701">#7701</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/b2926a0ff9589c28c7e01fe7cdbb337b86d5a4b4"><code>b2926a0</code></a>
release(checkpoint-sqlite): 3.1.1 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8481">#8481</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/fcdf520938469c8e0992ca2075d6a9582c33260f"><code>fcdf520</code></a>
release(checkpoint-postgres): 3.1.1 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8480">#8480</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/66ebe1a0da921e73f0f9f879ba105d314c079f7c"><code>66ebe1a</code></a>
fix(checkpoint-postgres,checkpoint-sqlite): scope namespace matching to
segme...</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/41341457342327166d72fc11952ab28fb61ec0bf"><code>4134145</code></a>
release(langgraph): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8462">#8462</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/30c4d58db86455128e42ddec96b1ba53c553ba22"><code>30c4d58</code></a>
chore(deps): bump jupyterlab from 4.5.9 to 4.5.10 in /libs/langgraph (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8440">#8440</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/1f2f88b2b74aa4e26c6a8be877dcb95bad2cef48"><code>1f2f88b</code></a>
chore(deps): bump js-yaml from 4.2.0 to 4.3.0 in
/libs/cli/js-monorepo-exampl...</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/270820363d56cf8a8e594d2d3b19d543230337fb"><code>2708203</code></a>
chore(deps): bump setuptools from 82.0.1 to 83.0.0 in /libs/cli (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8434">#8434</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/9f1e40bfeea28dee2155b4a57f5babd0a53534cf"><code>9f1e40b</code></a>
chore(deps): bump setuptools from 80.9.0 to 83.0.0 in /libs/langgraph
(<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8435">#8435</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/1e1ca88dad9c7e708263257fa9fc27a3fbdfff68"><code>1e1ca88</code></a>
feat(langgraph): type v3 stream_events return and native projections (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8389">#8389</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/31f90df3e6b0268fa77fd2d118a917d420b84a68"><code>31f90df</code></a>
revert(langgraph): delete TracePolicy (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8403">#8403</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langgraph/compare/checkpointpostgres==3.0.5...checkpointsqlite==3.1.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=langgraph-checkpoint-postgres&package-manager=uv&previous-version=3.0.5&new-version=3.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-20 07:02:48 +00:00
10 changed files with 219 additions and 21 deletions
+1 -1
View File
@@ -58,7 +58,7 @@ jobs:
if: (steps.changed-files.outputs.all || github.event_name == 'workflow_dispatch')
working-directory: ${{ matrix.example.workdir }}
run: |
langgraph build -t ${{ matrix.example.tag }}
langgraph build --single-user-layer -t ${{ matrix.example.tag }}
- name: Test service ${{ matrix.example.name }}
if: ${{ (steps.changed-files.outputs.all || github.event_name == 'workflow_dispatch') &&env.HAS_LANGSMITH_API_KEY == 'true' }}
working-directory: ${{ matrix.example.workdir }}
+1
View File
@@ -76,6 +76,7 @@ __pypackages__/
# Environments
.env
.env.*
.envrc
*.crt
*.key
+8
View File
@@ -2,6 +2,14 @@
This repository is a monorepo. Each library lives in a subdirectory under `libs/`.
<corridor>
## Corridor security analysis
When Corridor's `analyzePlan` tool is available, create a plan and use the tool to analyze it before generating or modifying code. Apply the resulting security guidance before writing code.
</corridor>
When you modify code in any library, run the following commands in that library's directory before creating a pull request:
- `make format` run code formatters
+8
View File
@@ -2,6 +2,14 @@
This repository is a monorepo. Each library lives in a subdirectory under `libs/`.
<corridor>
## Corridor security analysis
Before generating or modifying code, create a plan and use Corridor's `analyzePlan` tool to analyze it. Apply the resulting security guidance before writing code.
</corridor>
When you modify code in any library, run the following commands in that library's directory before creating a pull request:
- `make format` run code formatters
+8
View File
@@ -408,6 +408,12 @@ For production use, requires a license key in env var LANGGRAPH_CLOUD_LICENSE_KE
"--build-command",
help="Custom build command to run from the langgraph.json directory. If not provided, uses default build process.",
)
@click.option(
"--single-user-layer",
is_flag=True,
envvar="LANGGRAPH_CLI_SINGLE_USER_LAYER",
help="Combine generated Python build steps into one image layer when supported.",
)
@click.argument("docker_build_args", nargs=-1, type=click.UNPROCESSED)
@cli.command(
help="📦 Build LangGraph API server Docker image.",
@@ -426,6 +432,7 @@ def build(
tag: str,
install_command: str | None,
build_command: str | None,
single_user_layer: bool,
):
if install_command and langgraph_cli.config.has_disallowed_build_command_content(
install_command
@@ -461,6 +468,7 @@ def build(
docker_build_args,
install_command,
build_command,
single_user_layer=single_user_layer,
)
+137 -14
View File
@@ -1162,6 +1162,107 @@ def _build_runtime_env_vars(config: Config) -> list[str]:
return env_vars
def _supports_single_user_layer(
config: Config, local_deps: LocalDeps, escape_variables: bool
) -> bool:
return not (
config["dockerfile_lines"]
or local_deps.additional_contexts
or config.get("ui")
or config.get("node_version")
or escape_variables
)
def _faux_package_pyproject_command(package_name: str) -> str:
pyproject_path = shlex.quote(f"/deps/outer-{package_name}/pyproject.toml")
return f"""cat > {pyproject_path} <<'PYPROJECT'
[project]
name = {json.dumps(package_name)}
version = "0.1"
[tool.setuptools.package-data]
"*" = ["**/*"]
[build-system]
requires = ["setuptools>=61"]
build-backend = "setuptools.build_meta"
PYPROJECT"""
def _build_single_user_layer_dockerfile(
config_path: pathlib.Path,
config: Config,
local_deps: LocalDeps,
pypi_deps: list[str],
local_reqs_pip_install: str,
local_deps_install_command: str,
pip_cleanup: str,
image: str,
env_vars: list[str],
) -> str:
context = pathlib.PurePosixPath("/__build_context")
commands = ["set -eu"]
if pip_config_file := config.get("pip_config_file"):
source = shlex.quote(str(context / pip_config_file))
commands.append(f"cp {source} /pipconfig.txt")
if pypi_deps:
commands.append(f"{local_reqs_pip_install} {' '.join(pypi_deps)}")
for reqpath, destination in local_deps.pip_reqs:
source = context / reqpath.relative_to(config_path.parent)
destination_parent = pathlib.PurePosixPath(destination).parent
commands.extend(
[
f"mkdir -p {shlex.quote(str(destination_parent))}",
f"cp {shlex.quote(str(source))} {shlex.quote(destination)}",
]
)
if local_deps.pip_reqs:
requirements = " ".join(
f"-r {destination}" for _, destination in local_deps.pip_reqs
)
commands.append(f"{local_reqs_pip_install} {requirements}")
for _, (relative_path, name) in local_deps.real_pkgs.items():
source = f"{context / relative_path}/."
destination = f"/deps/{name}"
commands.extend(
[
f"mkdir -p {shlex.quote(destination)}",
f"cp -a {shlex.quote(source)} {shlex.quote(destination)}/",
]
)
for full_path, (relative_path, destination) in local_deps.faux_pkgs.items():
source = f"{context / relative_path}/."
commands.extend(
[
f"mkdir -p {shlex.quote(destination)}",
f"cp -a {shlex.quote(source)} {shlex.quote(destination)}/",
_faux_package_pyproject_command(full_path.name),
]
)
commands.append(local_deps_install_command)
commands.extend(
line.removeprefix("RUN ")
for line in pip_cleanup.splitlines()
if line and not line.startswith("#")
)
return os.linesep.join(
[
"# syntax=docker/dockerfile:1.7",
f"FROM {image}",
"RUN --mount=type=bind,target=/__build_context,readonly <<'USER_LAYER'",
*commands,
"USER_LAYER",
*env_vars,
f"WORKDIR {local_deps.working_dir}" if local_deps.working_dir else "",
]
)
def _get_node_pm_install_cmd(project_dir: pathlib.Path) -> str:
def test_file(file_name):
full_path = project_dir / file_name
@@ -1267,6 +1368,7 @@ def python_config_to_docker(
api_version: str | None = None,
*,
escape_variables: bool = False,
single_user_layer: bool = False,
) -> tuple[str, dict[str, str]]:
"""Generate a Dockerfile from the configuration."""
source_kind = _get_source_kind(config)
@@ -1428,6 +1530,37 @@ ADD {relpath} /deps/{name}
]
)
image_str = docker_tag(config, base_image, api_version)
dep_vname = "$$dep" if escape_variables else "$dep"
local_deps_install_command = f"""for dep in /deps/*; do \
echo "Installing {dep_vname}"; \
if [ -d "{dep_vname}" ]; then \
echo "Installing {dep_vname}"; \
(cd "{dep_vname}" && {global_reqs_pip_install} -e .); \
fi; \
done"""
pip_cleanup = _get_pip_cleanup_lines(
install_cmd=install_cmd,
to_uninstall=build_tools_to_uninstall,
pip_installer=pip_installer,
)
if single_user_layer and _supports_single_user_layer(
config, local_deps, escape_variables
):
return (
_build_single_user_layer_dockerfile(
config_path=config_path,
config=config,
local_deps=local_deps,
pypi_deps=pypi_deps,
local_reqs_pip_install=local_reqs_pip_install,
local_deps_install_command=local_deps_install_command,
pip_cleanup=pip_cleanup,
image=image_str,
env_vars=env_vars,
),
additional_contexts,
)
# Prepare docker file contents
docker_file_contents = []
@@ -1442,14 +1575,6 @@ ADD {relpath} /deps/{name}
)
# Add main dockerfile content
dep_vname = "$$dep" if escape_variables else "$dep"
local_deps_install_str = f"""RUN for dep in /deps/*; do \
echo "Installing {dep_vname}"; \
if [ -d "{dep_vname}" ]; then \
echo "Installing {dep_vname}"; \
(cd "{dep_vname}" && {global_reqs_pip_install} -e .); \
fi; \
done"""
docker_file_contents.extend(
[
f"FROM {image_str}",
@@ -1459,18 +1584,14 @@ ADD {relpath} /deps/{name}
installs,
"",
"# -- Installing all local dependencies --",
local_deps_install_str,
f"RUN {local_deps_install_command}",
"# -- End of local dependencies install --",
os.linesep.join(env_vars),
"",
js_inst_str,
"",
# Add pip cleanup after all installations are complete
_get_pip_cleanup_lines(
install_cmd=install_cmd,
to_uninstall=build_tools_to_uninstall,
pip_installer=pip_installer,
),
pip_cleanup,
"",
f"WORKDIR {local_deps.working_dir}" if local_deps.working_dir else "",
]
@@ -1625,6 +1746,7 @@ def config_to_docker(
build_command: str | None = None,
build_context: str | None = None,
escape_variables: bool = False,
single_user_layer: bool = False,
) -> tuple[str, dict[str, str]]:
base_image = base_image or default_base_image(config)
@@ -1645,6 +1767,7 @@ def config_to_docker(
base_image=base_image,
api_version=api_version,
escape_variables=escape_variables,
single_user_layer=single_user_layer,
)
+2
View File
@@ -345,6 +345,7 @@ def build_docker_image(
docker_command: Sequence[str] | None = None,
extra_flags: Sequence[str] = (),
verbose: bool = True,
single_user_layer: bool = False,
):
"""Build a Docker image from a LangGraph config."""
# pull latest images
@@ -387,6 +388,7 @@ def build_docker_image(
install_command=install_command,
build_command=build_command,
build_context=build_context,
single_user_layer=single_user_layer,
)
# add additional_contexts
if additional_contexts:
+16
View File
@@ -970,6 +970,22 @@ def python_config_to_docker_uv_lock(
f"{uv_export_project_dir}/uv.lock",
)
)
for package_root in sorted(
plan.all_workspace_roots,
key=lambda root: root.as_posix(),
):
if package_root == plan.project_root:
continue
package_relative_path = pathlib.PurePosixPath(
package_root.relative_to(plan.project_root).as_posix()
)
package_pyproject_path = package_relative_path / "pyproject.toml"
docker_plan.add_raw(
copy_from_project_root(
package_pyproject_path,
f"{uv_export_project_dir}/{package_pyproject_path.as_posix()}",
)
)
docker_plan.add_instruction("WORKDIR", uv_export_project_dir)
docker_plan.add_instruction(
"RUN",
+32
View File
@@ -723,6 +723,25 @@ WORKDIR /deps/outer-unit_tests/unit_tests\
}
def test_config_to_docker_single_user_layer():
dockerfile, additional_contexts = config_to_docker(
PATH_TO_CONFIG,
validate_config(
{"dependencies": ["."], "graphs": {"agent": "./agent.py:graph"}}
),
base_image="langchain/langgraph-api",
single_user_layer=True,
)
assert additional_contexts == {}
assert dockerfile.count("\nRUN ") == 1
assert "--mount=type=bind" in dockerfile
assert "cp -a /__build_context/. /deps/outer-unit_tests/unit_tests/" in dockerfile
assert "cat > /deps/outer-unit_tests/pyproject.toml <<'PYPROJECT'" in dockerfile
assert '[tool.setuptools.package-data]\n"*" = ["**/*"]' in dockerfile
assert dockerfile.endswith("WORKDIR /deps/outer-unit_tests/unit_tests")
def test_config_to_docker_outside_path():
graphs = {"agent": "./agent.py:graph"}
actual_docker_stdin, additional_contexts = config_to_docker(
@@ -1403,6 +1422,19 @@ def test_config_to_docker_uv_lock():
"COPY --from=uv-workspace-root uv.lock /tmp/uv_export/project/uv.lock"
in docker
)
workspace_pyprojects = [
"apps/agent/pyproject.toml",
"libs/extra/pyproject.toml",
"libs/shared/pyproject.toml",
]
export_instruction = "RUN uv export --package agent"
for pyproject_path in workspace_pyprojects:
copy_instruction = (
"COPY --from=uv-workspace-root "
f"{pyproject_path} /tmp/uv_export/project/{pyproject_path}"
)
assert copy_instruction in docker
assert docker.index(copy_instruction) < docker.index(export_instruction)
assert additional_contexts == {"uv-workspace-root": str(project_root.resolve())}
assert (
+6 -6
View File
@@ -266,20 +266,20 @@ wheels = [
[[package]]
name = "langgraph-checkpoint"
version = "4.0.1"
version = "4.2.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "langchain-core" },
{ name = "ormsgpack" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b1/44/a8df45d1e8b4637e29789fa8bae1db022c953cc7ac80093cfc52e923547e/langgraph_checkpoint-4.0.1.tar.gz", hash = "sha256:b433123735df11ade28829e40ce25b9be614930cd50245ff2af60629234befd9", size = 158135, upload-time = "2026-02-27T21:06:16.092Z" }
sdist = { url = "https://files.pythonhosted.org/packages/dc/e1/089c4c9e0a2fec7f883f82ae8e6a727138d50074cfeb6644bc2d13b1019b/langgraph_checkpoint-4.2.0.tar.gz", hash = "sha256:51a593b6bee684b0818e5d6e58e28ab340c6db7794575056ce7bd1b746a84ed7", size = 180239, upload-time = "2026-08-07T20:05:03.756Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/65/4c/09a4a0c42f5d2fc38d6c4d67884788eff7fd2cfdf367fdf7033de908b4c0/langgraph_checkpoint-4.0.1-py3-none-any.whl", hash = "sha256:e3adcd7a0e0166f3b48b8cf508ce0ea366e7420b5a73aa81289888727769b034", size = 50453, upload-time = "2026-02-27T21:06:14.293Z" },
{ url = "https://files.pythonhosted.org/packages/05/71/3b475f09bd57d3a5649792c66353312b4432afd843f301739dfcebd157f0/langgraph_checkpoint-4.2.0-py3-none-any.whl", hash = "sha256:0547fd228935a0b758865de3a3d6d7a2537c308895d0f9ab092ce9151b5da942", size = 56833, upload-time = "2026-08-07T20:05:02.655Z" },
]
[[package]]
name = "langgraph-checkpoint-postgres"
version = "3.0.5"
version = "3.1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "langgraph-checkpoint" },
@@ -287,9 +287,9 @@ dependencies = [
{ name = "psycopg" },
{ name = "psycopg-pool" },
]
sdist = { url = "https://files.pythonhosted.org/packages/95/7a/8f439966643d32111248a225e6cb33a182d07c90de780c4dbfc1e0377832/langgraph_checkpoint_postgres-3.0.5.tar.gz", hash = "sha256:a8fd7278a63f4f849b5cbc7884a15ca8f41e7d5f7467d0a66b31e8c24492f7eb", size = 127856, upload-time = "2026-03-18T21:25:29.785Z" }
sdist = { url = "https://files.pythonhosted.org/packages/06/92/1e8959f8cd1b56e672fde3227f6fd642be85af6c5fd662d73921074aa39d/langgraph_checkpoint_postgres-3.1.1.tar.gz", hash = "sha256:d320e147ddad8c374cd546df0b52b532dd54d0541dd9fd23fc738cbd5de76f41", size = 150413, upload-time = "2026-07-30T19:15:39.014Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e8/87/b0f98b33a67204bca9d5619bcd9574222f6b025cf3c125eedcec9a50ecbc/langgraph_checkpoint_postgres-3.0.5-py3-none-any.whl", hash = "sha256:86d7040a88fd70087eaafb72251d796696a0a2d856168f5c11ef620771411552", size = 42907, upload-time = "2026-03-18T21:25:28.75Z" },
{ url = "https://files.pythonhosted.org/packages/03/32/ba457698a48a0e18d786caa770033067049fbe36d6846f8e50f13b594b51/langgraph_checkpoint_postgres-3.1.1-py3-none-any.whl", hash = "sha256:6e353aecd8150de144fef8e51a49076f58b7d6830d4cf51392b7ad4d79832ba7", size = 50778, upload-time = "2026-07-30T19:15:37.405Z" },
]
[[package]]