feat: enhance CLI with environment variable handling and Docker configuration

- Added functions to parse .env files and resolve environment variables from configuration.
- Introduced a context manager for temporary Docker configuration using authentication tokens.
- Updated Docker capabilities check to include optional requirements for Docker Compose and Buildx.
- Enhanced the HostBackendClient with new methods for listing and retrieving deployments and revisions.
- Improved the Progress class to display elapsed time during tasks.
This commit is contained in:
David Asamu
2026-03-09 12:10:55 -04:00
committed by hari-dhanushkodi
parent 64cf527af4
commit 72b765ef7f
4 changed files with 550 additions and 165 deletions
+28 -18
View File
@@ -24,9 +24,9 @@ DockerComposeType = Literal["plugin", "standalone"]
class DockerCapabilities(NamedTuple):
version_docker: Version
version_compose: Version
version_compose: Version | None
healthcheck_start_interval: bool
compose_type: DockerComposeType = "plugin"
compose_type: DockerComposeType | None = None
def _parse_version(version: str) -> Version:
@@ -45,7 +45,9 @@ def _parse_version(version: str) -> Version:
)
def check_capabilities(runner) -> DockerCapabilities:
def check_capabilities(
runner, *, require_compose: bool = True, require_buildx: bool = False
) -> DockerCapabilities:
# check docker available
if shutil.which("docker") is None:
raise click.UsageError("Docker not installed") from None
@@ -61,25 +63,33 @@ def check_capabilities(runner) -> DockerCapabilities:
if not info["ServerVersion"]:
raise click.UsageError("Docker not running") from None
compose_type: DockerComposeType
try:
compose = next(
p for p in info["ClientInfo"]["Plugins"] if p["Name"] == "compose"
)
compose_version_str = compose["Version"]
compose_type = "plugin"
except (KeyError, StopIteration):
if shutil.which("docker-compose") is None:
raise click.UsageError("Docker Compose not installed") from None
compose_type: DockerComposeType | None = None
compose_version: Version | None = None
if require_compose:
try:
compose = next(
p for p in info["ClientInfo"]["Plugins"] if p["Name"] == "compose"
)
compose_version_str = compose["Version"]
compose_type = "plugin"
except (KeyError, StopIteration):
if shutil.which("docker-compose") is None:
raise click.UsageError("Docker Compose not installed") from None
compose_version_str, _ = runner.run(
subp_exec("docker-compose", "--version", "--short", collect=True)
)
compose_type = "standalone"
compose_version_str, _ = runner.run(
subp_exec("docker-compose", "--version", "--short", collect=True)
)
compose_type = "standalone"
compose_version = _parse_version(compose_version_str)
if require_buildx:
try:
runner.run(subp_exec("docker", "buildx", "version", collect=True))
except click.exceptions.Exit:
raise click.UsageError("Docker Buildx not installed") from None
# parse versions
docker_version = _parse_version(info["ServerVersion"])
compose_version = _parse_version(compose_version_str)
# check capabilities
return DockerCapabilities(