Building directly from a checkout will pull in uncommitted files to or more sneakily files that are git ignored, but not docker ignored. To avoid this, we'll add an option to build from a git archive of HEAD instead. Docker doesn't provide a way to build directly from a git repo, so instead we create a tarball of the current HEAD with git archive and pipe it into the build command. When building from a git archive, we'll still display the warning about uncommitted changes, but we won't add the `_uncommitted_...` suffix to the container name as they won't be included in the build. Perhaps this should be the default, but we'll leave that decision for now.
84 lines
1.9 KiB
Ruby
84 lines
1.9 KiB
Ruby
|
|
class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
class BuilderError < StandardError; end
|
|
|
|
delegate :argumentize, to: Kamal::Utils
|
|
delegate :args, :secrets, :dockerfile, :local_arch, :local_host, :remote_arch, :remote_host, :cache_from, :cache_to, :ssh, :git_archive?, to: :builder_config
|
|
|
|
def clean
|
|
docker :image, :rm, "--force", config.absolute_image
|
|
end
|
|
|
|
def pull
|
|
docker :pull, config.absolute_image
|
|
end
|
|
|
|
def push
|
|
if git_archive?
|
|
pipe \
|
|
git(:archive, "--format=tar", :HEAD),
|
|
build_and_push
|
|
else
|
|
build_and_push
|
|
end
|
|
end
|
|
|
|
def build_options
|
|
[ *build_tags, *build_cache, *build_labels, *build_args, *build_secrets, *build_dockerfile, *build_ssh ]
|
|
end
|
|
|
|
def build_context
|
|
config.builder.context
|
|
end
|
|
|
|
def validate_image
|
|
pipe \
|
|
docker(:inspect, "-f", "'{{ .Config.Labels.service }}'", config.absolute_image),
|
|
any(
|
|
[ :grep, "-x", config.service ],
|
|
"(echo \"Image #{config.absolute_image} is missing the 'service' label\" && exit 1)"
|
|
)
|
|
end
|
|
|
|
|
|
private
|
|
def build_tags
|
|
[ "-t", config.absolute_image, "-t", config.latest_image ]
|
|
end
|
|
|
|
def build_cache
|
|
if cache_to && cache_from
|
|
[ "--cache-to", cache_to,
|
|
"--cache-from", cache_from ]
|
|
end
|
|
end
|
|
|
|
def build_labels
|
|
argumentize "--label", { service: config.service }
|
|
end
|
|
|
|
def build_args
|
|
argumentize "--build-arg", args, sensitive: true
|
|
end
|
|
|
|
def build_secrets
|
|
argumentize "--secret", secrets.collect { |secret| [ "id", secret ] }
|
|
end
|
|
|
|
def build_dockerfile
|
|
if Pathname.new(File.expand_path(dockerfile)).exist?
|
|
argumentize "--file", dockerfile
|
|
else
|
|
raise BuilderError, "Missing #{dockerfile}"
|
|
end
|
|
end
|
|
|
|
def build_ssh
|
|
argumentize "--ssh", ssh if ssh.present?
|
|
end
|
|
|
|
def builder_config
|
|
config.builder
|
|
end
|
|
end
|