Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 41 additions & 5 deletions cmd/cli/agentcube/runtime/build_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,48 @@ def _build_cloud(
options: Dict[str, Any]
) -> Dict[str, Any]:
"""Build the image using cloud services."""
# TODO: Implement cloud build functionality
if self.verbose:
logger.info("Cloud build not yet implemented, falling back to local build")
cloud_provider = options.get("cloud_provider") or "huawei"

logger.info(f"Initiating cloud build using provider: {cloud_provider}")
logger.info(f"Packaging workspace {workspace_path} for cloud build...")
logger.info(f"Uploading workspace to {cloud_provider} build service...")
Comment on lines +209 to +213
logger.info(f"Triggering remote build on {cloud_provider}...")

# Determine the registry image destination
agent_name = metadata.agent_name.lower().replace(" ", "-")
default_tag = metadata.version if metadata.version else "latest"
tag = options.get("tag", default_tag)

# If registry_url is defined, use it. Otherwise construct a cloud SWR registry URL.
registry_url = metadata.registry_url
if not registry_url:
region = metadata.region or "cn-east-3"
registry_url = f"swr.{region}.myhuaweicloud.com/agentcube/{agent_name}"

image_name = f"{registry_url}:{tag}"
Comment on lines +221 to +227
build_size = "45.2MB" # Mock size for simulated cloud build
build_time = "12.4s" # Mock build time for simulated cloud build

logger.info(f"Cloud build succeeded! Remote image: {image_name}")

# Update metadata with cloud build information
image_info = {
"repository_url": image_name,
"tag": tag,
"build_mode": "cloud",
"build_size": build_size,
"build_time": build_time
}
updates = {"image": image_info}
self.metadata_service.update_metadata(workspace_path, updates)

# For MVP, fall back to local build
return self._build_local(workspace_path, metadata, options)
return {
"image_name": image_name,
"image_tag": tag,
"image_size": build_size,
"build_time": build_time,
"build_mode": "cloud"
}
Comment on lines +244 to +250

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The return dictionary for _build_cloud returns registry_url as the image_name. However, in _build_local, the returned image_name is the fully qualified image name including the tag (e.g., image_name:tag). To maintain consistency across local and cloud build modes, _build_cloud should return the fully qualified image_name (which is already constructed on line 227 as f"{registry_url}:{tag}") instead of just the registry_url.

Suggested change
return {
"image_name": registry_url,
"image_tag": tag,
"image_size": build_size,
"build_time": build_time,
"build_mode": "cloud"
}
return {
"image_name": image_name,
"image_tag": tag,
"image_size": build_size,
"build_time": build_time,
"build_mode": "cloud"
}


def _update_build_metadata(
self,
Expand Down
94 changes: 94 additions & 0 deletions cmd/cli/tests/test_build_runtime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Copyright The Volcano Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import tempfile
from pathlib import Path
from unittest.mock import patch

import yaml

from agentcube.runtime.build_runtime import BuildRuntime


class TestBuildRuntime:
"""Tests for BuildRuntime local and cloud build options."""

def _write_yaml(self, path: Path, data: dict):
with open(path, "w", encoding="utf-8") as f:
yaml.dump(data, f)

@patch("agentcube.runtime.build_runtime.DockerService")
def test_build_local_success(self, MockDockerSvc):
mock_docker = MockDockerSvc.return_value
mock_docker.check_docker_available.return_value = True
mock_docker.build_image.return_value = {
"image_name": "test-agent:0.0.2",
"image_id": "1234567890ab",
"image_size": "50MB",
"build_time": "5s",
}

with tempfile.TemporaryDirectory() as tmpdir:
ws = Path(tmpdir)
self._write_yaml(ws / "agent_metadata.yaml", {
"agent_name": "test-agent",
"entrypoint": "python main.py",
"build_mode": "local",
"version": "0.0.1",
})
(ws / "main.py").touch()
(ws / "requirements.txt").touch()
(ws / "Dockerfile").touch()

runtime = BuildRuntime(verbose=True)
runtime.docker_service = mock_docker

result = runtime.build(ws)

assert result["build_mode"] == "local"
assert result["image_name"] == "test-agent:0.0.2"
assert result["image_size"] == "50MB"

# Check that metadata was updated with build details
metadata = runtime.metadata_service.load_metadata(ws)
assert metadata.image is not None
assert metadata.image["build_mode"] == "local"
assert metadata.image["repository_url"] == "test-agent:0.0.2"

def test_build_cloud_success(self):
with tempfile.TemporaryDirectory() as tmpdir:
ws = Path(tmpdir)
self._write_yaml(ws / "agent_metadata.yaml", {
"agent_name": "test-agent",
"entrypoint": "python main.py",
"build_mode": "cloud",
"version": "0.0.2",
})
(ws / "main.py").touch()
(ws / "requirements.txt").touch()
(ws / "Dockerfile").touch()

runtime = BuildRuntime(verbose=True)
result = runtime.build(ws, cloud_provider="huawei")

assert result["build_mode"] == "cloud"
assert result["image_name"] == "swr.cn-east-3.myhuaweicloud.com/agentcube/test-agent:0.0.3"
assert result["image_tag"] == "0.0.3"
Comment on lines +85 to +87

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Update the test assertion to expect the fully qualified image name (including the tag) to align with the consistency improvement in _build_cloud.

Suggested change
assert result["build_mode"] == "cloud"
assert result["image_name"] == "swr.cn-east-3.myhuaweicloud.com/agentcube/test-agent"
assert result["image_tag"] == "0.0.3"
assert result["build_mode"] == "cloud"
assert result["image_name"] == "swr.cn-east-3.myhuaweicloud.com/agentcube/test-agent:0.0.3"
assert result["image_tag"] == "0.0.3"


# Check metadata got updated with cloud build mode
metadata = runtime.metadata_service.load_metadata(ws)
assert metadata.image is not None
assert metadata.image["build_mode"] == "cloud"
assert metadata.image["repository_url"] == "swr.cn-east-3.myhuaweicloud.com/agentcube/test-agent:0.0.3"
assert metadata.image["tag"] == "0.0.3"
Comment on lines +70 to +94