Class: Kamal::Secrets::Dotenv::InlineCommandSubstitution

Inherits:
Object
  • Object
show all
Defined in:
lib/kamal/secrets/dotenv/inline_command_substitution.rb

Constant Summary collapse

INTERPOLATED_SHELL_COMMAND =

Unlike dotenv, this regex does not match escaped parentheses when looking for command substitutions.

/
  (?<backslash>\\)?          # is it escaped with a backslash?
  \$                         # literal $
  (?<cmd>                    # collect command content for eval
    \(                       # require opening paren
    (?:\\.|[^()\\]|\g<cmd>)+ # allow any number of non-parens or escaped
                             # parens (by nesting the <cmd> expression
                             # recursively)
    \)                       # require closing paren
  )
/x

Class Method Summary collapse

Class Method Details

.call(value, env, overwrite: false) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/kamal/secrets/dotenv/inline_command_substitution.rb', line 21

def call(value, env, overwrite: false)
  # Process interpolated shell commands
  value.gsub(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
      command = ::Dotenv::Substitutions::Variable.call(command, env)
      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

.inline_secrets_command(command) ⇒ Object



43
44
45
# File 'lib/kamal/secrets/dotenv/inline_command_substitution.rb', line 43

def inline_secrets_command(command)
  Kamal::Cli::Main.start(command.shellsplit[1..] + [ "--inline" ]).chomp
end

.install!Object



17
18
19
# File 'lib/kamal/secrets/dotenv/inline_command_substitution.rb', line 17

def install!
  ::Dotenv::Parser.substitutions.map! { |sub| sub == ::Dotenv::Substitutions::Command ? self : sub }
end