-
Notifications
You must be signed in to change notification settings - Fork 0
[Feature] Added parallelism to ventis build for speedup #22
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
base: main
Are you sure you want to change the base?
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 |
|---|---|---|
|
|
@@ -19,3 +19,4 @@ AWSCLIV2.pkg | |
| docker_container | ||
| grpc_stubs | ||
| stubs | ||
| tests | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,3 +40,4 @@ docker_container/ | |
| !.env.example | ||
| AWSCLIV2.pkg | ||
| .python-version | ||
| uv.lock | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |
|
|
||
| import argparse | ||
| import glob | ||
| import json | ||
| import logging | ||
| import os | ||
| import shutil | ||
|
|
@@ -60,13 +61,13 @@ def _docker_build_cmd(*args): | |
| return ["docker", "build", "--platform", _docker_platform(), *args] | ||
|
|
||
|
|
||
| def _docker_available(): | ||
| def _docker_available(probe_cmd=("docker", "info")): | ||
| if not shutil.which("docker"): | ||
| return False | ||
|
|
||
| try: | ||
| result = subprocess.run( | ||
| ["docker", "info"], | ||
| list(probe_cmd), | ||
| capture_output=True, | ||
| text=True, | ||
| check=False, | ||
|
|
@@ -77,6 +78,32 @@ def _docker_available(): | |
| return result.returncode == 0 | ||
|
|
||
|
|
||
| def _write_bake_file(bake_targets, bake_file_path, platform): | ||
| """Write a docker-buildx-bake JSON file describing all build targets. | ||
|
|
||
| Context paths are written absolute: `docker buildx bake` resolves relative | ||
| `context` values against the invocation cwd (not the bake file's own | ||
| directory), so an absolute path sidesteps that ambiguity entirely. | ||
| """ | ||
| bake_config = { | ||
| "target": { | ||
| target["name"]: { | ||
| "context": os.path.abspath(target["context"]), | ||
| "dockerfile": "Dockerfile", | ||
| "tags": [target["image_name"]], | ||
| "platforms": [platform], | ||
| "output": ["type=docker"], | ||
| # type=docker could be changed to tarring it up, which would be | ||
| # faster but skipped because that change would alter ventis deploy | ||
| } | ||
| for target in bake_targets | ||
| } | ||
| } | ||
| with open(bake_file_path, "w") as f: | ||
|
Member
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. What is the point of this bake config and what does it do ? How is it configured. |
||
| json.dump(bake_config, f, indent=2) | ||
| return bake_file_path | ||
|
|
||
|
|
||
| def _require_docker_for_ec2(command_name): | ||
| if _docker_available(): | ||
| return | ||
|
|
@@ -218,8 +245,9 @@ def cmd_build(args): | |
| ) | ||
|
|
||
| # -------------------------------------------------------------- # | ||
| # Step 4: Generate Docker contexts and build images # | ||
| # Step 4: Generate Docker contexts # | ||
| # -------------------------------------------------------------- # | ||
| bake_targets = [] | ||
| for agent_cfg in agents: | ||
| agent_name = agent_cfg["name"] | ||
| agent_type = agent_cfg.get("type", "agent") | ||
|
|
@@ -248,12 +276,6 @@ def cmd_build(args): | |
| api_port=agent_cfg.get("api_port", 8080), | ||
| ) | ||
|
|
||
| image_name = f"ventis-{agent_name.lower()}" | ||
| logger.info("Building Docker image: %s", image_name) | ||
| subprocess.run( | ||
| _docker_build_cmd("-t", image_name, docker_context), check=True | ||
| ) | ||
|
|
||
| else: | ||
| # Agent container | ||
| entrypoint = agent_cfg.get("entrypoint") | ||
|
|
@@ -296,10 +318,43 @@ def cmd_build(args): | |
| stub_files=stub_paths, | ||
| ) | ||
|
|
||
| image_name = f"ventis-{agent_name.lower()}" | ||
| logger.info("Building Docker image: %s", image_name) | ||
| bake_targets.append( | ||
| { | ||
| "name": agent_name.lower(), | ||
| "context": docker_context, | ||
| "image_name": f"ventis-{agent_name.lower()}", | ||
| } | ||
| ) | ||
|
|
||
| # -------------------------------------------------------------- # | ||
| # Step 5: Build all Docker images # | ||
| # -------------------------------------------------------------- # | ||
| if not bake_targets: | ||
| logger.info("No Docker images to build.") | ||
| elif _docker_available() and _docker_available(("docker", "buildx", "version")): | ||
| docker_container_dir = os.path.join(project_dir, "docker_container") | ||
| os.makedirs(docker_container_dir, exist_ok=True) | ||
| bake_file_path = os.path.join(docker_container_dir, "docker-bake.json") | ||
| _write_bake_file(bake_targets, bake_file_path, _docker_platform()) | ||
|
|
||
| target_names = [target["name"] for target in bake_targets] | ||
| logger.info( | ||
| "Building %d Docker image(s) via `docker buildx bake`.", | ||
| len(bake_targets), | ||
| ) | ||
| subprocess.run( | ||
| ["docker", "buildx", "bake", "--file", bake_file_path, *target_names], | ||
| check=True, | ||
| ) | ||
| else: | ||
| logger.info( | ||
| "docker buildx unavailable; falling back to sequential `docker build`." | ||
| ) | ||
| for target in bake_targets: | ||
| logger.info("Building Docker image: %s", target["image_name"]) | ||
| subprocess.run( | ||
| _docker_build_cmd("-t", image_name, docker_context), check=True | ||
| _docker_build_cmd("-t", target["image_name"], target["context"]), | ||
| check=True, | ||
| ) | ||
|
Comment on lines
+332
to
358
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. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win The two
🧰 Tools🪛 ast-grep (0.44.1)[error] 354-357: Use of unsanitized data to create processes (os-system-unsanitized-data) [error] 344-347: Command coming from incoming request (subprocess-from-request) [error] 354-357: Command coming from incoming request (subprocess-from-request) 📍 Affects 2 files
🤖 Prompt for AI Agents |
||
|
|
||
| logger.info("Build complete.") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
docker buildx bake target name allowed characters validation💡 Result:
Docker Buildx Bake targets are strictly validated to ensure compatibility across various systems and naming conventions [1]. The allowed characters for a target name are defined by the regular expression
[a-zA-Z0-9_-]+[2][1]. This means a target name must consist only of: - Uppercase and lowercase letters (a-z, A-Z) - Digits (0-9) - Underscores (_) - Hyphens (-) If a target name includes characters outside of this set—such as dots (.)—docker buildx bakewill return an error stating that only those specific characters are allowed [1][3]. In contexts like Docker Compose, where service names might include characters (like dots) that are valid in the Compose specification but invalid for Bake targets, the tooling performs a sanitization step [3][4]. This often involves replacing restricted characters with underscores (e.g., convertingservice.nametoservice_name) to ensure they can be processed as Bake targets [2][4]. When working with matrix strategies that dynamically generate names, you can use thesanitize()function within your HCL configuration to ensure generated names comply with these requirements [5].Citations:
-.json:10,5-19: Invalid name; only "[a-zA-Z0-9_-]+" are alloweddocker/compose#12919🏁 Script executed:
Repository: CanyonCodeCoreAI/canyoncodecore
Length of output: 12162
Sanitize bake target names and enforce uniqueness.
target["name"]is built directly fromagent_name.lower(), while Buildx target names are limited to[A-Za-z0-9_-]; names with spaces or dots will make the generated bake file fail. Case-only differences also become duplicate dict keys, silently dropping one target from the build command path. Normalize to a safe slug and assert that normalized target names are unique before appending targets.🧰 Tools
🪛 ast-grep (0.44.1)
[warning] 101-101: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(bake_file_path, "w")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(open-filename-from-request)
🤖 Prompt for AI Agents