Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved deploy lock acquisition #202

Merged
merged 1 commit into from
Apr 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/mrsk/cli.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module Mrsk::Cli
class LockError < StandardError; end
end

# SSHKit uses instance eval, so we need a global const for ergonomics
Expand Down
12 changes: 7 additions & 5 deletions lib/mrsk/cli/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ module Mrsk::Cli
class Base < Thor
include SSHKit::DSL

class LockError < StandardError; end

def self.exit_on_failure?() true end

class_option :verbose, type: :boolean, aliases: "-v", desc: "Detailed logging"
Expand Down Expand Up @@ -82,8 +80,11 @@ def with_lock
acquire_lock

yield
ensure

release_lock
rescue
error " \e[31mDeploy lock was not released\e[0m" if MRSK.lock_count > 0
raise
end

def acquire_lock
Expand All @@ -95,9 +96,10 @@ def acquire_lock
rescue SSHKit::Runner::ExecuteError => e
if e.message =~ /cannot create directory/
invoke "mrsk:cli:lock:status", []
raise LockError, "Deploy lock found"
else
raise e
end

raise LockError, "Deploy lock found"
end

def release_lock
Expand Down
4 changes: 2 additions & 2 deletions lib/mrsk/cli/lock.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ def acquire
message = options[:message]
handle_missing_lock do
on(MRSK.primary_host) { execute *MRSK.lock.acquire(message, MRSK.config.version) }
say "Set the deploy lock"
say "Acquired the deploy lock"
end
end

desc "release", "Release the deploy lock"
def release
handle_missing_lock do
on(MRSK.primary_host) { execute *MRSK.lock.release }
say "Removed the deploy lock"
say "Released the deploy lock"
end
end

Expand Down
6 changes: 5 additions & 1 deletion test/cli/cli_test_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ class CliTestCase < ActiveSupport::TestCase
def stdouted
capture(:stdout) { yield }.strip
end
end

def stderred
capture(:stderr) { yield }.strip
end
end
40 changes: 40 additions & 0 deletions test/cli/main_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,46 @@ class CliMainTest < CliTestCase
end
end

test "deploy when locked" do
Thread.report_on_exception = false

SSHKit::Backend::Abstract.any_instance.stubs(:execute)
.with { |*arg| arg[0..1] == [:mkdir, :mrsk_lock] }
.raises(RuntimeError, "mkdir: cannot create directory ‘mrsk_lock’: File exists")

Mrsk::Cli::Base.any_instance.expects(:invoke).with("mrsk:cli:lock:status", [])

assert_raises(Mrsk::Cli::LockError) do
run_command("deploy")
end
end

test "deploy error when locking" do
Thread.report_on_exception = false

SSHKit::Backend::Abstract.any_instance.stubs(:execute)
.with { |*arg| arg[0..1] == [:mkdir, :mrsk_lock] }
.raises(SocketError, "getaddrinfo: nodename nor servname provided, or not known")

assert_raises(SSHKit::Runner::ExecuteError) do
run_command("deploy")
end
end

test "deploy errors leave lock in place" do
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "skip_broadcast" => false, "version" => "999" }

Mrsk::Cli::Main.any_instance.expects(:invoke)
.with("mrsk:cli:server:bootstrap", [], invoke_options)
.raises(RuntimeError)

assert_equal 0, MRSK.lock_count
assert_raises(RuntimeError) do
stderred { run_command("deploy") }
end
assert_equal 1, MRSK.lock_count
end

test "redeploy" do
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "skip_broadcast" => false, "version" => "999" }

Expand Down