Packages
A typed Elixir wrapper for the Docker CLI with struct-based commands and pipeline composition
Current section
Files
Jump to
Current section
Files
lib/docker/commands/builder/build.ex
defmodule Docker.Commands.Builder.Build do
@moduledoc """
Implements the `Docker.Command` behaviour for `docker buildx build`.
Extended build with multi-platform, cache, and output options.
"""
@behaviour Docker.Command
import Docker.Command, only: [add_flag: 3, add_opt: 3, add_repeat: 3]
@enforce_keys [:context]
defstruct [
:context,
:file,
:target,
:builder,
:output,
:cache_to,
tags: [],
platforms: [],
build_args: [],
labels: [],
cache_from: [],
no_cache: false,
pull: false,
push: false,
load: false,
extra_args: []
]
@type t :: %__MODULE__{}
def new(context), do: %__MODULE__{context: context}
def tag(%__MODULE__{} = cmd, t), do: %{cmd | tags: cmd.tags ++ [t]}
def file(%__MODULE__{} = cmd, f), do: %{cmd | file: f}
def target(%__MODULE__{} = cmd, t), do: %{cmd | target: t}
def builder(%__MODULE__{} = cmd, b), do: %{cmd | builder: b}
def output(%__MODULE__{} = cmd, o), do: %{cmd | output: o}
def cache_to(%__MODULE__{} = cmd, c), do: %{cmd | cache_to: c}
def platform(%__MODULE__{} = cmd, p), do: %{cmd | platforms: cmd.platforms ++ [p]}
def no_cache(%__MODULE__{} = cmd), do: %{cmd | no_cache: true}
def pull(%__MODULE__{} = cmd), do: %{cmd | pull: true}
def push(%__MODULE__{} = cmd), do: %{cmd | push: true}
def load(%__MODULE__{} = cmd), do: %{cmd | load: true}
def build_arg(%__MODULE__{} = cmd, key, value) do
%{cmd | build_args: cmd.build_args ++ [{to_string(key), to_string(value)}]}
end
def label(%__MODULE__{} = cmd, key, value) do
%{cmd | labels: cmd.labels ++ [{to_string(key), to_string(value)}]}
end
def cache_from(%__MODULE__{} = cmd, c), do: %{cmd | cache_from: cmd.cache_from ++ [c]}
def raw(%__MODULE__{} = cmd, args) when is_list(args) do
%{cmd | extra_args: cmd.extra_args ++ args}
end
@impl true
def args(%__MODULE__{} = cmd) do
platform_str =
case cmd.platforms do
[] -> nil
ps -> Enum.join(ps, ",")
end
["buildx", "build"]
|> add_flag(cmd.no_cache, "--no-cache")
|> add_flag(cmd.pull, "--pull")
|> add_flag(cmd.push, "--push")
|> add_flag(cmd.load, "--load")
|> add_opt(cmd.file, "-f")
|> add_opt(cmd.target, "--target")
|> add_opt(cmd.builder, "--builder")
|> add_opt(cmd.output, "--output")
|> add_opt(cmd.cache_to, "--cache-to")
|> add_opt(platform_str, "--platform")
|> add_repeat(cmd.tags, fn t -> ["-t", t] end)
|> add_repeat(cmd.build_args, fn {k, v} -> ["--build-arg", "#{k}=#{v}"] end)
|> add_repeat(cmd.labels, fn {k, v} -> ["--label", "#{k}=#{v}"] end)
|> add_repeat(cmd.cache_from, fn c -> ["--cache-from", c] end)
|> Kernel.++(cmd.extra_args)
|> Kernel.++([cmd.context])
end
@impl true
def parse_output(stdout, 0), do: {:ok, stdout}
def parse_output(stdout, exit_code), do: {:error, {stdout, exit_code}}
end