|
| 1 | +"""Helpers and strategy interface for packaging Docker build contexts. |
| 2 | +
|
| 3 | +This module exposes a small, pluggable abstraction around turning a local |
| 4 | +filesystem directory into a tarball suitable for use as a Docker build |
| 5 | +context, plus a default implementation built on top of |
| 6 | +``lib.context_loader.build_docker_context_tar``. |
| 7 | +""" |
| 8 | + |
| 9 | +from __future__ import annotations |
| 10 | + |
| 11 | +from typing import Optional |
| 12 | +from pathlib import Path |
| 13 | +from dataclasses import dataclass |
| 14 | +from typing_extensions import Protocol |
| 15 | + |
| 16 | +from ..lib.context_loader import build_docker_context_tar |
| 17 | +from ..types.object_create_params import ContentType |
| 18 | + |
| 19 | +__all__ = ["BuildContextArtifact", "BuildContextStrategy", "default_build_context_strategy"] |
| 20 | + |
| 21 | + |
| 22 | +@dataclass(frozen=True) |
| 23 | +class BuildContextArtifact: |
| 24 | + """Result of packaging a build context directory. |
| 25 | +
|
| 26 | + Attributes: |
| 27 | + data: Tarball bytes containing the build context. |
| 28 | + content_type: Logical content type for the object payload. For the |
| 29 | + default implementation this is always ``\"tgz\"``. |
| 30 | + filename: Suggested filename to use when creating the backing Object. |
| 31 | + """ |
| 32 | + |
| 33 | + data: bytes |
| 34 | + content_type: ContentType = "tgz" |
| 35 | + filename: Optional[str] = None |
| 36 | + |
| 37 | + |
| 38 | +class BuildContextStrategy(Protocol): |
| 39 | + """Strategy interface for building Docker contexts. |
| 40 | +
|
| 41 | + Implementations may perform caching, custom compression, or additional |
| 42 | + validation, but must return a fully materialised tarball in memory. |
| 43 | + """ |
| 44 | + |
| 45 | + def __call__( |
| 46 | + self, |
| 47 | + context_root: Path, |
| 48 | + *, |
| 49 | + name: str | None = None, |
| 50 | + dockerignore: Path | None = None, |
| 51 | + ) -> BuildContextArtifact: |
| 52 | + """Package the given directory into a tarball. |
| 53 | +
|
| 54 | + Args: |
| 55 | + context_root: Filesystem path to the Docker build context root. |
| 56 | + name: Optional logical name for the context; may be used to |
| 57 | + derive a filename. |
| 58 | + dockerignore: Optional explicit path to a .dockerignore file. |
| 59 | + When omitted, the default implementation will look for |
| 60 | + ``.dockerignore`` under ``context_root``. |
| 61 | + """ |
| 62 | + |
| 63 | + |
| 64 | +def default_build_context_strategy( |
| 65 | + context_root: Path, |
| 66 | + *, |
| 67 | + name: str | None = None, |
| 68 | + dockerignore: Path | None = None, |
| 69 | +) -> BuildContextArtifact: |
| 70 | + """Default implementation that wraps ``build_docker_context_tar``. |
| 71 | +
|
| 72 | + The tarball is rebuilt on each invocation (no cross-call caching) and |
| 73 | + returned as a :class:`BuildContextArtifact` with ``content_type=\"tgz\"``. |
| 74 | + """ |
| 75 | + |
| 76 | + tar_bytes = build_docker_context_tar( |
| 77 | + context_root, |
| 78 | + dockerignore=dockerignore, |
| 79 | + ) |
| 80 | + |
| 81 | + if name is None: |
| 82 | + base = context_root.name or "context" |
| 83 | + filename = f"{base}.tar.gz" |
| 84 | + else: |
| 85 | + filename = f"{name}.tar.gz" |
| 86 | + |
| 87 | + return BuildContextArtifact( |
| 88 | + data=tar_bytes, |
| 89 | + content_type="tgz", |
| 90 | + filename=filename, |
| 91 | + ) |
0 commit comments