From 897b3b4e4628337e06f3e8a797a7df62ba3e0ee1 Mon Sep 17 00:00:00 2001 From: Nick Hammond Date: Tue, 27 Aug 2024 22:25:56 -0700 Subject: [PATCH] Add a pack option to the builder options --- lib/kamal/commands/base.rb | 4 ++++ lib/kamal/commands/builder.rb | 5 +++++ lib/kamal/commands/builder/base.rb | 2 +- lib/kamal/commands/builder/native/pack.rb | 26 +++++++++++++++++++++++ lib/kamal/configuration/builder.rb | 16 ++++++++++++++ lib/kamal/configuration/docs/builder.yml | 10 +++++++++ test/commands/builder_test.rb | 8 +++++++ test/configuration/builder_test.rb | 18 ++++++++++++++++ 8 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 lib/kamal/commands/builder/native/pack.rb diff --git a/lib/kamal/commands/base.rb b/lib/kamal/commands/base.rb index 2173d064..731e543f 100644 --- a/lib/kamal/commands/base.rb +++ b/lib/kamal/commands/base.rb @@ -77,6 +77,10 @@ module Kamal::Commands args.compact.unshift :docker end + def pack(*args) + args.compact.unshift :pack + end + def git(*args, path: nil) [ :git, *([ "-C", path ] if path), *args.compact ] end diff --git a/lib/kamal/commands/builder.rb b/lib/kamal/commands/builder.rb index 13c3d829..41f07dc2 100644 --- a/lib/kamal/commands/builder.rb +++ b/lib/kamal/commands/builder.rb @@ -18,6 +18,8 @@ class Kamal::Commands::Builder < Kamal::Commands::Base else native_remote end + elsif config.builder.pack? + pack else multiarch end @@ -50,6 +52,9 @@ class Kamal::Commands::Builder < Kamal::Commands::Base @multiarch_remote ||= Kamal::Commands::Builder::Multiarch::Remote.new(config) end + def pack + @pack ||= Kamal::Commands::Builder::Native::Pack.new(config) + end def ensure_local_dependencies_installed if name.native? diff --git a/lib/kamal/commands/builder/base.rb b/lib/kamal/commands/builder/base.rb index cedfeadf..fa095f60 100644 --- a/lib/kamal/commands/builder/base.rb +++ b/lib/kamal/commands/builder/base.rb @@ -5,7 +5,7 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base ENDPOINT_DOCKER_HOST_INSPECT = "'{{.Endpoints.docker.Host}}'" delegate :argumentize, to: Kamal::Utils - delegate :args, :secrets, :dockerfile, :target, :local_arch, :local_host, :remote_arch, :remote_host, :cache_from, :cache_to, :ssh, to: :builder_config + delegate :args, :secrets, :dockerfile, :target, :local_arch, :local_host, :pack_arch, :pack_builder, :pack_buildpacks, :remote_arch, :remote_host, :cache_from, :cache_to, :ssh, to: :builder_config def clean docker :image, :rm, "--force", config.absolute_image diff --git a/lib/kamal/commands/builder/native/pack.rb b/lib/kamal/commands/builder/native/pack.rb new file mode 100644 index 00000000..d4ca1931 --- /dev/null +++ b/lib/kamal/commands/builder/native/pack.rb @@ -0,0 +1,26 @@ +class Kamal::Commands::Builder::Native::Pack < Kamal::Commands::Builder::Native + def push + combine \ + pack(:build, + config.absolute_image, + "--platform", platform, + "--builder", pack_builder, + buildpacks, + "-t", config.absolute_image, + "-t", config.latest_image, + "--env", "BP_IMAGE_LABELS=service=#{config.service}", + secrets.map { |secret| ["--env", Kamal::Utils.sensitive(ENV[secret])] }, + "--path", build_context), + docker(:push, config.absolute_image), + docker(:push, config.latest_image) + end + + private + def platform + "linux/#{pack_arch}" + end + + def buildpacks + (pack_buildpacks << "paketo-buildpacks/image-labels").map { |buildpack| ["--buildpack", buildpack] } + end +end diff --git a/lib/kamal/configuration/builder.rb b/lib/kamal/configuration/builder.rb index 74c8d1c6..634b1846 100644 --- a/lib/kamal/configuration/builder.rb +++ b/lib/kamal/configuration/builder.rb @@ -35,6 +35,10 @@ class Kamal::Configuration::Builder !!builder_config["cache"] end + def pack? + !!builder_config["pack"] + end + def args builder_config["args"] || {} end @@ -63,6 +67,18 @@ class Kamal::Configuration::Builder builder_config["local"]["host"] if local? end + def pack_arch + builder_config["pack"]["arch"] if pack? + end + + def pack_builder + builder_config["pack"]["builder"] if pack? + end + + def pack_buildpacks + builder_config["pack"]["buildpacks"] if pack? + end + def remote_arch builder_config["remote"]["arch"] if remote? end diff --git a/lib/kamal/configuration/docs/builder.yml b/lib/kamal/configuration/docs/builder.yml index b1071105..706fe83c 100644 --- a/lib/kamal/configuration/docs/builder.yml +++ b/lib/kamal/configuration/docs/builder.yml @@ -37,6 +37,16 @@ builder: arch: arm64 host: ssh://docker@docker-builder + # Buildpack configuration + # + # The build configuration for using pack to build a Cloud Native Buildpack image. + pack: + builder: heroku/builder:24 + arch: amd64 + buildpacks: + - heroku/ruby + - heroku/procfile + # Builder cache # # The type must be either 'gha' or 'registry' diff --git a/test/commands/builder_test.rb b/test/commands/builder_test.rb index f3faa5f6..29c65703 100644 --- a/test/commands/builder_test.rb +++ b/test/commands/builder_test.rb @@ -53,6 +53,14 @@ class CommandsBuilderTest < ActiveSupport::TestCase builder.push.join(" ") end + test "target pack when pack is set" do + builder = new_builder_command(builder: { "pack" => { "arch" => "amd64" , "builder" => "heroku/builder:24", "buildpacks" => [ "heroku/ruby", "heroku/procfile" ] }}) + assert_equal "native/pack", builder.name + assert_equal \ + "pack build dhh/app:123 --platform linux/amd64 --builder heroku/builder:24 --buildpack heroku/ruby --buildpack heroku/procfile --buildpack paketo-buildpacks/image-labels -t dhh/app:123 -t dhh/app:latest --env BP_IMAGE_LABELS=service=app --path . && docker push dhh/app:123 && docker push dhh/app:latest", + builder.push.join(" ") + end + test "build args" do builder = new_builder_command(builder: { "args" => { "a" => 1, "b" => 2 } }) assert_equal \ diff --git a/test/configuration/builder_test.rb b/test/configuration/builder_test.rb index 4b37b5e8..8576e06a 100644 --- a/test/configuration/builder_test.rb +++ b/test/configuration/builder_test.rb @@ -32,6 +32,24 @@ class ConfigurationBuilderTest < ActiveSupport::TestCase assert_equal false, config.builder.remote? end + test "pack?" do + refute config.builder.pack? + end + + test "pack? with pack builder" do + @deploy[:builder] = { "pack" => {"builder" => "heroku/builder:24"} } + + assert config.builder.pack? + end + + test "pack details" do + @deploy[:builder] = { "pack" => {"arch" => "amd64", "builder" => "heroku/builder:24", "buildpacks" => ["heroku/ruby", "heroku/procfile"]} } + + assert_equal "amd64", config.builder.pack_arch + assert_equal "heroku/builder:24", config.builder.pack_builder + assert_equal ["heroku/ruby", "heroku/procfile"], config.builder.pack_buildpacks + end + test "remote_arch" do assert_nil config.builder.remote_arch end