Skip to content

Instantly share code, notes, and snippets.

@vlad-velciov
Created January 13, 2021 08:12
Show Gist options
  • Save vlad-velciov/fb933746e81bca6c46ca4d2346795aa9 to your computer and use it in GitHub Desktop.
Save vlad-velciov/fb933746e81bca6c46ca4d2346795aa9 to your computer and use it in GitHub Desktop.
A small tool to convert a file that has lots of export statements to a normalized .env file
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'digest/md5'
# TODO option to install git hook on pull
# TODO option to uninstall git hook on pull
# TODO option to install files in a .git/info/exclude
TIER_TO_FILENAME={
'dev' => ['.env.development', 'development.env'],
'test' => ['.env.test', 'test.env'],
'aio' => ['.env.aio', 'aio.env']
}.freeze
def source_zshrc
log 'Sourcing ~/.zsrhc...'
`source ~/.zshrc`
end
def convert_environment(environment)
file_with_exports, dot_env_file = TIER_TO_FILENAME[environment]
convert_file(file_with_exports, dot_env_file)
end
def convert_file(file_with_exports, dot_env_file)
report_if_file_was_changed(dot_env_file) do
run_source(file_with_exports)
var_names = get_var_names(file_with_exports)
write_env_vars(var_names, dot_env_file)
end
end
def run_source(file)
log "Sourcing file #{file}..."
source_env_from file
end
# System commands are run in a separate shell which is closed
# after execution. That is why we are printing the environment vars
# and using them afterwards.
def get_sourced_vars(file)
local_envs = "AWS_ACCESS_KEY_ID=#{ENV['AWS_ACCESS_KEY_ID']} AWS_SECRET_ACCESS_KEY=#{ENV['AWS_SECRET_ACCESS_KEY']}"
env = `#{local_envs} source #{file}; printenv`
key_value_array = env
.split(/\n/)
.map {|l| l.split(/=/)}
.map do |l|
if l.length > 2
[l[0], l[1..-1].join('=')]
else
l
end
end
Hash[ key_value_array ]
end
def source_env_from(file)
get_sourced_vars(file).each {|k,v| ENV[k] = v }
end
def get_var_names(file)
log "Getting all variable names..."
var_names = []
text=File.open(file).read
text.gsub!(/\r\n?/, "\n")
text.each_line.with_index do |line, line_num|
next if !line.include?('export')
next if line =~ /^#/
export_part = line.split('=')[0]
var_name = export_part.split(' ')[1]
next unless var_name
var_names << var_name
end
var_names
end
def write_env_vars(var_names, new_file)
log "Writing variables to #{new_file}..."
File.open(new_file, "w+") do |f|
var_names.each do |var_name|
f.puts "#{var_name}=#{ENV[var_name]}"
end
end
end
def get_var_value(var_name)
if default_name = detect_override(var_name)
ENV[var_name] ? ENV[var_name] : ENV[default_name]
else
ENV[var_name]
end
end
# TODO do this
def detect_override(var_name)
value = ENV[var_name]
if value =~ /^\$\{/
true
else
false
end
end
def get_existing_envs
envs = []
['dev', 'test', 'aio'].each do |env|
envs << env if env_file_present?(env)
end
envs
end
def env_file_present?(env)
file, _ = TIER_TO_FILENAME[env]
File.exist?(file)
end
def log(string, level = :debug)
colors = {
debug: 33,
success: 32
}
puts colorize string, colors[level]
end
def colorize(string, color_code)
"\e[#{color_code}m#{string}\e[0m"
end
def report_if_file_was_changed(file)
initial_hahs = file_hash(file)
yield
final_hash = file_hash(file)
if initial_hahs == final_hash
log 'No changes were found. Same file.'
else
log 'Changes were found. New file generated'
end
log "\n"
end
def file_hash(file)
if File.exist? file
Digest::MD5.hexdigest(File.read(file))
else
""
end
end
def main
source_zshrc
existing_envs = get_existing_envs
if existing_envs.empty?
log 'No environmental files(e.g.: .env.development) were found. Goodbye.'
exit
end
existing_envs.each { |environment| convert_environment(environment) }
log 'Done', :success
end
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment