Coverage for src / openenv / docker / builder.py: 100.00%

23 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-25 13:36 +0000

1"""Docker image build helpers.""" 

2 

3from __future__ import annotations 

4 

5import subprocess 

6import tempfile 

7from pathlib import Path 

8 

9from openenv.core.errors import CommandError 

10from openenv.core.utils import slugify_name 

11 

12 

13def default_image_tag(project_name: str, version: str) -> str: 

14 """Compute the default docker tag for a project.""" 

15 return f"openclawenv/{slugify_name(project_name)}:{version}" 

16 

17 

18def build_image(dockerfile_text: str, tag: str) -> None: 

19 """Build a Docker image from a rendered Dockerfile.""" 

20 build_image_with_args(dockerfile_text, tag, build_args=None) 

21 

22 

23def build_image_with_args( 

24 dockerfile_text: str, 

25 tag: str, 

26 *, 

27 build_args: dict[str, str] | None, 

28) -> None: 

29 """Build a Docker image from a rendered Dockerfile with optional build args.""" 

30 with tempfile.TemporaryDirectory(prefix="openclawenv-build-") as temp_dir: 

31 dockerfile_path = Path(temp_dir) / "Dockerfile" 

32 dockerfile_path.write_text(dockerfile_text, encoding="utf-8") 

33 command = [ 

34 "docker", 

35 "build", 

36 "--tag", 

37 tag, 

38 "--file", 

39 str(dockerfile_path), 

40 temp_dir, 

41 ] 

42 for key, value in sorted((build_args or {}).items()): 

43 command.extend(["--build-arg", f"{key}={value}"]) 

44 try: 

45 subprocess.run(command, check=True) 

46 except OSError as exc: 

47 raise CommandError("Docker is not available on PATH.") from exc 

48 except subprocess.CalledProcessError as exc: 

49 raise CommandError( 

50 f"Docker build failed for tag {tag} with exit code {exc.returncode}." 

51 ) from exc