Add a pre-init hook

The hook is run before the environment is loaded or the config is
parsed.

This makes it a bit of a special case - it doesn't have the usual
KAMAL_XYZ environment variables, as we haven't parsed the config.

The use case for this is to do auth checking or setup. So for example
we can confirm you are logged in to a secret manager, and then you
can directly call it to load your secrets in the .kamal/.env file
using .dotenv's
[command substitution](https://github.com/bkeepers/dotenv?tab=readme-ov-file#command-substitution).
This commit is contained in:
Donal McBreen
2024-07-30 16:49:22 +01:00
parent a8837d453c
commit cbb4c87035
12 changed files with 62 additions and 39 deletions

View File

@@ -22,9 +22,21 @@ module Kamal::Cli
class_option :skip_hooks, aliases: "-H", type: :boolean, default: false, desc: "Don't run hooks"
@@ran_pre_init_hook = false
class << self
def ran_pre_init_hook
@@ran_pre_init_hook
end
def ran_pre_init_hook=(value)
@@ran_pre_init_hook = value
end
end
def initialize(*)
super
@original_env = ENV.to_h.dup
run_pre_init_hook
load_env
initialize_commander(options_with_subcommand_class_options)
end
@@ -176,8 +188,23 @@ module Kamal::Cli
end
end
def run_pre_init_hook
unless self.class.ran_pre_init_hook
hook = "pre-init"
if run_hook?(hook)
say "Running the #{hook} hook...", :magenta
run_locally do
execute *Kamal::Hooks.file(hook), verbosity: :debug
rescue SSHKit::Command::Failed => e
raise HookError.new("Hook `#{hook}` failed:\n#{e.message}")
end
end
self.class.ran_pre_init_hook = true
end
end
def run_hook(hook, **extra_details)
if !options[:skip_hooks] && KAMAL.hook.hook_exists?(hook)
if run_hook?(hook)
details = { hosts: KAMAL.hosts.join(","), command: command, subcommand: subcommand }
say "Running the #{hook} hook...", :magenta
@@ -189,6 +216,10 @@ module Kamal::Cli
end
end
def run_hook?(hook)
!options[:skip_hooks] && Kamal::Hooks.exists?(hook)
end
def on(*args, &block)
if !KAMAL.connected?
run_hook "pre-connect"

View File

@@ -1,14 +1,5 @@
class Kamal::Commands::Hook < Kamal::Commands::Base
def run(hook, **details)
[ hook_file(hook), env: tags(**details).env ]
[ Kamal::Hooks.file(hook), env: tags(**details).env ]
end
def hook_exists?(hook)
Pathname.new(hook_file(hook)).exist?
end
private
def hook_file(hook)
File.join(config.hooks_path, hook)
end
end

View File

@@ -7,7 +7,7 @@ require "erb"
require "net/ssh/proxy/jump"
class Kamal::Configuration
delegate :service, :image, :labels, :stop_wait_time, :hooks_path, to: :raw_config, allow_nil: true
delegate :service, :image, :labels, :stop_wait_time, to: :raw_config, allow_nil: true
delegate :argumentize, :optionize, to: Kamal::Utils
attr_reader :destination, :raw_config
@@ -208,10 +208,6 @@ class Kamal::Configuration
end
end
def hooks_path
raw_config.hooks_path || ".kamal/hooks"
end
def asset_path
raw_config.asset_path
end

View File

@@ -74,10 +74,6 @@ env:
# To configure this, set the path to the assets:
asset_path: /path/to/assets
# Path to hooks, defaults to `.kamal/hooks`
# See https://kamal-deploy.org/docs/hooks for more information
hooks_path: /user_home/kamal/hooks
# Require destinations
#
# Whether deployments require a destination to be specified, defaults to `false`