Rather than redirecting the global $stdout, which is not never clever in a threaded program, we'll make the secrets commands aware they are being inlined, so they return the value instead of printing it. Additionally we no longer need to interrupt the parent process on error as we've inlined the command - exit 1 is enough.
33 lines
1.0 KiB
Ruby
33 lines
1.0 KiB
Ruby
class Kamal::Secrets::Dotenv::InlineCommandSubstitution
|
|
class << self
|
|
def install!
|
|
::Dotenv::Parser.substitutions.map! { |sub| sub == ::Dotenv::Substitutions::Command ? self : sub }
|
|
end
|
|
|
|
def call(value, _env, overwrite: false)
|
|
# Process interpolated shell commands
|
|
value.gsub(Dotenv::Substitutions::Command.singleton_class::INTERPOLATED_SHELL_COMMAND) do |*|
|
|
# Eliminate opening and closing parentheses
|
|
command = $LAST_MATCH_INFO[:cmd][1..-2]
|
|
|
|
if $LAST_MATCH_INFO[:backslash]
|
|
# Command is escaped, don't replace it.
|
|
$LAST_MATCH_INFO[0][1..]
|
|
else
|
|
if command =~ /\A\s*kamal\s*secrets\s+/
|
|
# Inline the command
|
|
inline_secrets_command(command)
|
|
else
|
|
# Execute the command and return the value
|
|
`#{command}`.chomp
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def inline_secrets_command(command)
|
|
Kamal::Cli::Main.start(command.shellsplit[1..] + [ "--inline" ]).chomp
|
|
end
|
|
end
|
|
end
|