MRSK hooks

Adds hooks to MRSK. Currently just two hooks, pre-build and post-push.

We could break the build and push into two separate commands if we
found the need for post-build and/or pre-push hooks.

Hooks are stored in `.mrsk/hooks`. Running `mrsk init` will now create
that folder and add sample hook scripts.

Hooks returning non-zero exit codes will abort the current command.

Further potential work here:
- We could replace the audit broadcast command with a
post-deploy/post-rollback hook or similar
- Maybe provide pre-command/post-command hooks that run after every
mrsk invocation
- Also look for hooks in `~/.mrsk/hooks`
This commit is contained in:
Donal McBreen
2023-05-05 15:08:28 +01:00
parent 340ed94fa9
commit 58c1096a90
23 changed files with 292 additions and 51 deletions

View File

@@ -1,24 +1,23 @@
require "time"
class Mrsk::Commands::Auditor < Mrsk::Commands::Base
attr_reader :details
def initialize(config, **details)
super(config)
@details = default_details.merge(details)
@details = details
end
# Runs remotely
def record(line, **details)
append \
[ :echo, *audit_tags(**details), line ],
[ :echo, audit_tags(**details).except(:version).to_s, line ],
audit_log_file
end
# Runs locally
def broadcast(line, **details)
if broadcast_cmd = config.audit_broadcast_cmd
[ broadcast_cmd, *broadcast_args(line, **details), env: env_for(event: line, **details) ]
tags = audit_tags(**details, event: line)
[ broadcast_cmd, "'#{tags.except(:recorded_at, :event, :version)} #{line}'", env: tags.env ]
end
end
@@ -31,29 +30,7 @@ class Mrsk::Commands::Auditor < Mrsk::Commands::Base
[ "mrsk", config.service, config.destination, "audit.log" ].compact.join("-")
end
def default_details
{ recorded_at: Time.now.utc.iso8601,
performer: `whoami`.chomp,
destination: config.destination }
end
def audit_tags(**details)
tags_for **self.details.merge(details)
end
def broadcast_args(line, **details)
"'#{broadcast_tags(**details).join(" ")} #{line}'"
end
def broadcast_tags(**details)
tags_for **self.details.merge(details).except(:recorded_at)
end
def tags_for(**details)
details.compact.values.map { |value| "[#{value}]" }
end
def env_for(**details)
self.details.merge(details).compact.transform_keys { |detail| "MRSK_#{detail.upcase}" }
tags(**self.details, **details)
end
end

View File

@@ -53,5 +53,9 @@ module Mrsk::Commands
def docker(*args)
args.compact.unshift :docker
end
def tags(**details)
Mrsk::Tags.from_config(config, **details)
end
end
end

14
lib/mrsk/commands/hook.rb Normal file
View File

@@ -0,0 +1,14 @@
class Mrsk::Commands::Hook < Mrsk::Commands::Base
def run(hook, **details)
[ ".mrsk/hooks/#{hook}", env: tags(**details).env ]
end
def hook_exists?(hook)
Pathname.new(hook_file(hook)).exist?
end
private
def hook_file(hook)
".mrsk/hooks/#{hook}"
end
end