Skip to content

Commit

Permalink
Merge pull request #256 from Jberczel/check-local-dependencies
Browse files Browse the repository at this point in the history
Add local dependencies check
  • Loading branch information
dhh authored May 2, 2023
2 parents 8854bb6 + 263a24a commit 4c448f7
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 5 deletions.
24 changes: 23 additions & 1 deletion lib/mrsk/cli/build.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class Mrsk::Cli::Build < Mrsk::Cli::Base
class BuildError < StandardError; end

desc "deliver", "Build app and push app image to registry then pull image on servers"
def deliver
with_lock do
Expand All @@ -14,7 +16,9 @@ def push

run_locally do
begin
MRSK.with_verbosity(:debug) { execute *MRSK.builder.push }
if cli.verify_local_dependencies
MRSK.with_verbosity(:debug) { execute *MRSK.builder.push }
end
rescue SSHKit::Command::Failed => e
if e.message =~ /(no builder)|(no such file or directory)/
error "Missing compatible builder, so creating a new one first"
Expand Down Expand Up @@ -77,4 +81,22 @@ def details
puts capture(*MRSK.builder.info)
end
end


desc "", "" # Really a private method, but needed to be invoked from #push
def verify_local_dependencies
run_locally do
begin
execute *MRSK.builder.ensure_local_dependencies_installed
rescue SSHKit::Command::Failed => e
build_error = e.message =~ /command not found/ ?
"Docker is not installed locally" :
"Docker buildx plugin is not installed locally"

raise BuildError, build_error
end
end

true
end
end
2 changes: 1 addition & 1 deletion lib/mrsk/cli/main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def deploy
invoke_options = deploy_options

runtime = print_runtime do
say "Ensure curl and Docker are installed...", :magenta
say "Ensure curl and Docker are installed on servers...", :magenta
invoke "mrsk:cli:server:bootstrap", [], invoke_options

say "Log into image registry...", :magenta
Expand Down
22 changes: 21 additions & 1 deletion lib/mrsk/commands/builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class Mrsk::Commands::Builder < Mrsk::Commands::Base
delegate :create, :remove, :push, :clean, :pull, :info, to: :target

def name
target.class.to_s.remove("Mrsk::Commands::Builder::").underscore
target.class.to_s.remove("Mrsk::Commands::Builder::").underscore.inquiry
end

def target
Expand Down Expand Up @@ -33,4 +33,24 @@ def multiarch
def multiarch_remote
@multiarch_remote ||= Mrsk::Commands::Builder::Multiarch::Remote.new(config)
end


def ensure_local_dependencies_installed
if name.native?
ensure_local_docker_installed
else
combine \
ensure_local_docker_installed,
ensure_local_buildx_installed
end
end

private
def ensure_local_docker_installed
docker "--version"
end

def ensure_local_buildx_installed
docker :buildx, "version"
end
end
10 changes: 9 additions & 1 deletion lib/mrsk/commands/builder/base.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@

class Mrsk::Commands::Builder::Base < Mrsk::Commands::Base
class BuilderError < StandardError; end

delegate :argumentize, to: Mrsk::Utils

def clean
Expand All @@ -17,6 +20,7 @@ def build_context
context
end


private
def build_tags
[ "-t", config.absolute_image, "-t", config.latest_image ]
Expand All @@ -35,7 +39,11 @@ def build_secrets
end

def build_dockerfile
argumentize "--file", dockerfile
if Pathname.new(File.expand_path(dockerfile)).exist?
argumentize "--file", dockerfile
else
raise BuilderError, "Missing #{dockerfile}"
end
end

def args
Expand Down
19 changes: 19 additions & 0 deletions test/cli/build_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ class CliBuildTest < CliTestCase
end

test "push" do
Mrsk::Cli::Build.any_instance.stubs(:verify_local_dependencies).returns(true)
run_command("push").tap do |output|
assert_match /docker buildx build --push --platform linux\/amd64,linux\/arm64 --builder mrsk-app-multiarch -t dhh\/app:999 -t dhh\/app:latest --label service="app" --file Dockerfile \. as .*@localhost/, output
end
end

test "push without builder" do
stub_locking
Mrsk::Cli::Build.any_instance.stubs(:verify_local_dependencies).returns(true)
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
.with { |arg| arg == :docker }
.raises(SSHKit::Command::Failed.new("no builder"))
Expand Down Expand Up @@ -68,6 +70,23 @@ class CliBuildTest < CliTestCase
end
end

test "verify local dependencies" do
Mrsk::Commands::Builder.any_instance.stubs(:name).returns("remote".inquiry)

run_command("verify_local_dependencies").tap do |output|
assert_match /docker --version && docker buildx version/, output
end
end

test "verify local dependencies with no buildx plugin" do
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
.with(:docker, "--version", "&&", :docker, :buildx, "version")
.raises(SSHKit::Command::Failed.new("no buildx"))

Mrsk::Commands::Builder.any_instance.stubs(:native_and_local?).returns(false)
assert_raises(Mrsk::Cli::Build::BuildError) { run_command("verify_local_dependencies") }
end

private
def run_command(*command)
stdouted { Mrsk::Cli::Build.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) }
Expand Down
9 changes: 9 additions & 0 deletions test/commands/builder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,21 @@ class CommandsBuilderTest < ActiveSupport::TestCase
end

test "build dockerfile" do
Pathname.any_instance.expects(:exist?).returns(true).once
builder = new_builder_command(builder: { "dockerfile" => "Dockerfile.xyz" })
assert_equal \
"-t dhh/app:123 -t dhh/app:latest --label service=\"app\" --file Dockerfile.xyz",
builder.target.build_options.join(" ")
end

test "missing dockerfile" do
Pathname.any_instance.expects(:exist?).returns(false).once
builder = new_builder_command(builder: { "dockerfile" => "Dockerfile.xyz" })
assert_raises(Mrsk::Commands::Builder::Base::BuilderError) do
builder.target.build_options.join(" ")
end
end

test "build context" do
builder = new_builder_command(builder: { "context" => ".." })
assert_equal \
Expand Down
2 changes: 1 addition & 1 deletion test/configuration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class ConfigurationTest < ActiveSupport::TestCase
end

test "role" do
assert_equal "web", @config.role(:web).name
assert @config.role(:web).name.web?
assert_equal "workers", @config_with_roles.role(:workers).name
assert_nil @config.role(:missing)
end
Expand Down

0 comments on commit 4c448f7

Please sign in to comment.