Repository navigation
feat(cli): every put names its images <id>__<role>, as a bundle does #70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,7 +28,7 @@ | |
| ) | ||
| from agent_env.store import Filter, LocalSqliteDocumentStore, VersionedEntityStore | ||
| from agent_env.store.base import NotFoundError | ||
| from agent_env.store.ids import fs_safe, key_segment | ||
| from agent_env.store.ids import fs_safe, image_repository, key_segment | ||
| from agent_env.store.routing import LocalNamespaceDocumentStore | ||
| from agent_env.task import Task | ||
| from tst.unit.store.fakes import FakeDocumentStore, FakeImageStore, SigningObjectStore, reattach_for_snapshot | ||
|
|
@@ -261,6 +261,61 @@ def test_under_the_cli_a_bare_id_derived_from_an_local_one_is_refused_before_any | |
| LocalSqliteDocumentStore(str(state_root() / "services.db")).check_id(derived) | ||
|
|
||
|
|
||
| LOCAL_AGENT = "@local/~/bundle/agents/a" | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("module, argv, images", [ | ||
| ("agent_env.cli.a2a_agent.put", ["a2a-agent", "put", "--id", LOCAL_AGENT, "--skip-validation"], | ||
| [f"{LOCAL_AGENT}__agent_image"]), | ||
| ("agent_env.cli.env.mcp_server", ["env", "mcp-server", "put", "--id", LOCAL_ENV, "--environment-name", "items"], | ||
| [f"{LOCAL_ENV}__env_image"]), | ||
| ("agent_env.cli.env.website", ["env", "website", "put", "--id", LOCAL_ENV, "--environment-name", "shop", | ||
| "--skip-validation", "--backend-dockerfile", "{dockerfile}"], | ||
| [f"{LOCAL_ENV}__backend_image", f"{LOCAL_ENV}__frontend_image"]), | ||
| ], ids=["a2a-agent", "mcp-server", "website"]) | ||
| def test_a_put_with_an_local_id_builds_and_writes_its_images_under_ids_derived_from_it( | ||
| local_stores, tmp_path, monkeypatch, module, argv, images, | ||
| ): | ||
| dockerfile = tmp_path / "Dockerfile" | ||
| dockerfile.write_text("FROM scratch\n") | ||
| tags = [] | ||
| monkeypatch.setattr(importlib.import_module(module), "build_image", | ||
| lambda dockerfile, context, tag, **kwargs: tags.append(tag)) | ||
| tarball = local_stores.get_object_store().put("image.tar.gz", b"x") | ||
| monkeypatch.setattr(DockerImageArtifact, "put", classmethod(lambda cls, id, *, description, image_name, **kwargs: ( | ||
| cls.put_tar(id, description=description, image_name=image_name, tar_gz_s3_url=tarball)))) | ||
|
Comment on lines
+285
to
+286
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The new Knowledge Base Used: Container images and composition Prompt To Fix With AIThis is a comment left during a code review.
Path: tst/unit/store/local_id_acceptance_test.py
Line: 285-286
Comment:
**Local put test skips publication**
The new `@local` put test replaces `DockerImageArtifact.put` with `put_tar`, so it skips the image store and registry path this change relies on. It checks build tags and artifact IDs, but not the saved image reference or the registered env or agent. Add checks for those results so a routing or publication mistake cannot pass unnoticed.
**Knowledge Base Used:** [Container images and composition](https://app.greptile.com/scale-ai/-/custom-context/knowledge-base/scaleapi/agentenv-framework/-/docs/container-images-and-composition.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added in c08585c: the test now checks each saved image name and that the registered env or agent names the derived images. The real push to the local registry is covered by an end-to-end run, in the verification comment: the @Local mcp-server and a2a-agent puts write localhost:5000/local/… images, and a bundle deploys both. |
||
| argv = [arg.format(dockerfile=dockerfile) for arg in argv] | ||
| flag = "--frontend-dockerfile" if "--backend-dockerfile" in argv else "--dockerfile" | ||
|
|
||
| result = CliRunner().invoke(cli, [*argv, flag, str(dockerfile)]) | ||
|
|
||
| assert result.exit_code == 0, result.output | ||
| assert tags == [image_repository(image) for image in images] and all(tag.startswith("local/") for tag in tags) | ||
| saved = {d["id"]: d["image_name"] for d in _local().query("artifacts", Filter())} | ||
| assert saved == {image: image_repository(image) for image in images} | ||
| (owner,) = _local().query("a2a_agents" if module.endswith(".put") else "envs", Filter()) | ||
| assert sorted(ref["id"] for ref in owner.values() if isinstance(ref, dict) and "id" in ref) == images | ||
| assert not _documents().path.exists() or _documents().count("artifacts", Filter()) == 0 | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("module, argv", [ | ||
| ("agent_env.cli.a2a_agent.put", ["a2a-agent", "put", "--skip-validation"]), | ||
| ("agent_env.cli.env.mcp_server", ["env", "mcp-server", "put", "--environment-name", "items"]), | ||
| ], ids=["a2a-agent", "mcp-server"]) | ||
| def test_a_put_whose_image_id_would_be_too_long_is_refused_before_it_builds( | ||
| local_stores, tmp_path, monkeypatch, module, argv, | ||
| ): | ||
| dockerfile = tmp_path / "Dockerfile" | ||
| dockerfile.write_text("FROM scratch\n") | ||
| monkeypatch.setattr(importlib.import_module(module), "build_image", lambda *args, **kwargs: pytest.fail("it built")) | ||
| longest = "@local/~/" + "x" * (4096 - len("@local/~/")) # as long as an @local id may be, so a suffix can't fit | ||
|
|
||
| result = CliRunner().invoke(cli, [*argv, "--id", longest, "--dockerfile", str(dockerfile)]) | ||
|
|
||
| assert result.exit_code == 1 and "Error:" in result.output, result.output | ||
| assert not _local().path.exists() or _local().count("artifacts", Filter()) == 0 | ||
|
|
||
|
|
||
| class _Deployable: | ||
| """An env or agent whose deploy records what a deployment does: a state instance naming no | ||
| owner, and an instance of a bare infrastructure env.""" | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.