Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for creating templates from .env files. #377

Merged
merged 2 commits into from
Jun 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,29 @@ If you use this gem to handle env vars for multiple Rails environments (developm

Credentials should only be accessible on the machines that need access to them. Never commit sensitive information to a repository that is not needed by every development machine and server.


You can use the `-t` or `--template` flag on the dotenv cli to create a template of your `.env` file.
```shell
$ dotenv -t .env
```
A template will be created in your working directory named `{FINAME}.template`. So in the above example, it would create a `.env.template` file.

The template will contain all the environment variables in your `.env` file but with their values set to the variable names.

```shell
# .env
S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
```

Would become

```shell
# .env.template
S3_BUCKET=S3_BUCKET
SECRET_KEY=SECRET_KEY
```

Personally, I prefer to commit the `.env` file with development-only settings. This makes it easy for other developers to get started on the project without compromising credentials for other environments. If you follow this advice, make sure that all the credentials for your development environment are different from your other deployments and that the development credentials do not have access to any confidential data.

### Why is it not overriding existing `ENV` variables?
Expand Down
14 changes: 14 additions & 0 deletions lib/dotenv/cli.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "dotenv"
require "dotenv/version"
require "dotenv/template"
require "optparse"

module Dotenv
Expand Down Expand Up @@ -41,6 +42,7 @@ def add_options(parser, flag_matchers)
add_files_option(parser, flag_matchers)
add_help_option(parser, flag_matchers)
add_version_option(parser, flag_matchers)
add_template_option(parser, flag_matchers)
end

def add_files_option(parser, flag_matchers)
Expand All @@ -66,6 +68,18 @@ def add_version_option(parser, flag_matchers)
end
end

# Take a env file and create a template from it. This will keep the Key
# names but will replace the values. Useful for fat fingers who don't want
# to push env files.
def add_template_option(parser, flag_matchers)
flag_matchers.push("-t \\S+", "--template \\S+")
description = "Create a template of an existing env file"
parser.on("-t", "--template=FILE", description) do |file|
template = Dotenv::EnvTemplate.new(file)
template.create_template
end
end

# Detect dotenv flags vs executable args so we can parse properly and still
# take advantage of OptionParser for dotenv flags
def split_argv(arg_string, matchers)
Expand Down
19 changes: 19 additions & 0 deletions lib/dotenv/template.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Dotenv
# Class for creating a template from a env file
class EnvTemplate
def initialize(env_file)
@env_file = env_file
end

def create_template
File.open(@env_file, "r") do |env_file|
File.open("#{@env_file}.template", "w") do |env_template|
env_file.each do |line|
variable = line.split("=").first
env_template.puts "#{variable}=#{variable}"
end
end
end
end
end
end
18 changes: 18 additions & 0 deletions spec/dotenv/cli_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,24 @@ def run(*args)
expect(cli.exec_args).to eql(["foo", "-f", "something"])
end

it "templates a file specified by -t" do
@buffer = StringIO.new
@input = StringIO.new("FOO=BAR\nFOO2=BAR2")
@origin_filename = "plain.env"
@template_filename = "plain.env.template"
@content = "the content fo the file"
allow(File).to receive(:open).with(@origin_filename, "r").and_yield(@input)
# rubocop:disable LineLength
allow(File).to receive(:open).with(@template_filename, "w").and_yield(@buffer)

# call the function that writes to the file
cli = Dotenv::CLI.new(["-t", "plain.env"])
cli.send(:parse_argv!, cli.argv)

# reading the buffer and checking its content.
expect(@buffer.string).to eq("FOO=FOO\nFOO2=FOO2\n")
end

# Capture output to $stdout and $stderr
def capture_output(&_block)
original_stderr = $stderr
Expand Down