dot_example 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4f28ab67ad6f4d690e46f49d7f5c4c876021fd63
4
+ data.tar.gz: aa7c2ab482e6795f143486b38b6c9eacbbc09788
5
+ SHA512:
6
+ metadata.gz: d1d13c541460c0846bf93b1774bf788484c4e7e3bcbe089c46c94822faf14a2bc15b7e3d06341b5b3b9d49b0c1eb712a844c6b2417ff1f2b3703111a251a57ea
7
+ data.tar.gz: 5aa94b267cd9c1641db8ce427744ba08f6cbaf314f4126c083f5aea7e9d8dd9871a4f964410b060e97b5037b877e7067c9b732eb2be7821ca197a6c6e8c3cd44
@@ -0,0 +1,81 @@
1
+ # DotExample
2
+ It's become common practice to use a tool like the `dotenv` gem to manage environment variables locally, keeping all environment variables in a key value store in a dotfile (`.env`) and then leaving this file out of version control. However when working on a team it's easy to lose track of the latest variables that need to be added to `.env`. Often it isn't obvious when one is needed until a problem arises. Adding the keys to the README and/or to a `.env.example` file is one way to share the ENV variables needed with the rest of the team, but like many kinds of documentation it is easy for these files to get out of date.
3
+
4
+ Enter `dot_example`, a simple tool for automatically documenting the environment variables in use across the team and alerting team members when a new variable has been added. This is accomplished through the use of a `.env.example` file and setting up git hooks.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'dot_example'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install dot_example
21
+
22
+ ## Quick Start
23
+ Most of the time you should only need to manually run one command
24
+
25
+ ```
26
+ dot_example setup
27
+ ```
28
+
29
+ And you're done. That was easy!
30
+
31
+ Running this setup script will do the following:
32
+ 1. Create a new pre-commit git hook that will add the keys from your `.env` file to a `.env.example` file whenever you create a new commit.
33
+ 2. Create a new post-checkout git hook that will check for new variables in the `.env.example` whenever you checkout a branch.
34
+ 3. Create or add to a bin/setup file so that this setup script will be run automatically whenever anyone runs `./bin/setup`
35
+
36
+ Now for anyone else who joins the project all they have to do is run `./bin/setup` and `dot_example` will get setup along with the rest of the app. They won't even need to know that it's there!
37
+
38
+ ## Usage
39
+
40
+ dot_example ships with three commands `setup`, `sync` and `check`
41
+
42
+ ### Setup
43
+
44
+ ```
45
+ $ dot_example setup
46
+ ```
47
+
48
+ Sets up the githooks that will cause sync and check to run automatically. Assuming this works without a hitch this should keep you from having to manually run anything ever. You can even put a line in the bin/setup script to call this command:
49
+
50
+ and then you won't even have to manually run `setup` just have everyone run `./bin/setup` when they start the project. In case you do need to run the commands for whatever reason you can run the other two commands are as follows:
51
+
52
+ ### Sync
53
+ ```
54
+ $ dot_example snyc
55
+ ```
56
+ sync will take the keys to the ENV variables are in your `.env` file and write them to a `.env.example` file. By keeping _this_ file in source control rather than the actual `.env` file you can make sure that other team members are always up to date on which ENV variables they are missing.
57
+
58
+ ### Check
59
+
60
+ ```
61
+ $ dot_example check
62
+ ```
63
+
64
+ `check` will look at the ENV variables you currently have defined in your `.env` file and ensure they are up to date with the keys in the latest `.env.example`. This doesn't guarantee that their _values_ are correct but at least you'll receive a warning if you're missing keys and you'll know to ask someone for the ENV variables you're missing.
65
+
66
+ After running `dot_example setup` the `check` command will be run whenever you checkout code. This could easily be changed though if you'd rather the check happen in a different common task such as running tests with rake. All you'd need to do then is add `dot_example check` to your rake task.
67
+
68
+ ## Development
69
+
70
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
71
+
72
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
73
+
74
+ ## Contributing
75
+
76
+ Bug reports and pull requests are welcome on GitHub at https://github.com/smcabrera/dot_example. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
77
+
78
+ ## License
79
+
80
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
81
+
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "dot_example"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ require "pry"
10
+ Pry.start
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'commander/import'
5
+ require_relative '../lib/dot_example'
6
+
7
+ program :name, 'dot_example'
8
+ program :version, DotExample::VERSION
9
+ program :description, DotExample::SUMMARY
10
+ program :help, 'Author', 'Stephen Mariano Cabrera <smcabrera.github.io>'
11
+ program :help, 'Version', "#{DotExample::VERSION} #{DotExample::DATE}"
12
+
13
+ command :setup do |c|
14
+ c.syntax = 'dot_example setup [options]'
15
+ c.summary = 'Setup the githooks to automate the dot_example tasks'
16
+ c.description = 'Setup the githooks to automate the dot_example tasks'
17
+ #c.example 'description', 'command example'
18
+ #c.option '--some-switch', 'Some switch that does something'
19
+ c.action do |args, options|
20
+ dot_env_dot_example = DotEnvDotExample.new
21
+ DotExample.add_pre_commit_hook(dot_env_dot_example)
22
+ DotExample.add_post_checkout_hook
23
+ end
24
+ end
25
+
26
+ command :sync do |c|
27
+ c.syntax = 'dot_example sync [options]'
28
+ c.summary = 'Creates a new .env.example file with the keys from .env.'
29
+ c.description = 'Creates a new .env.example file with the keys from .env.'
30
+ #c.example 'dot_example sync', 'command example'
31
+ c.option '--dot-env-path FILEPATH', String, 'path to the .env file if different than current directory'
32
+ c.option '--dot-example-path FILEPATH', String, 'path to the .env.example file if different than current directory'
33
+ #c.option '--suffix STRING', String, 'Adds a suffix to bar'
34
+ c.action do |args, options|
35
+ dot_env = DotEnv.new(options.dot_env_path)
36
+ dot_env_dot_example = DotEnvDotExample.new(dot_env: dot_env, filename: options.dot_example_path)
37
+ dot_env_dot_example.write!
38
+ end
39
+ end
40
+
41
+ command :check do |c|
42
+ c.syntax = 'dot_example check_vars [options]'
43
+ c.summary = 'Checks ENV keys to make sure they are up to date with those found in .env.example'
44
+ c.description = ''
45
+ c.option '--dot-env-path FILEPATH', String, 'path to the .env file if different than current directory'
46
+ c.option '--dot-example-path FILEPATH', String, 'path to the .env.example file if different than current directory'
47
+ #c.example 'description', 'command example'
48
+ #c.option '--some-switch', 'Some switch that does something'
49
+ c.action do |args, options|
50
+ dot_env = DotEnv.new(options.dot_env_path)
51
+ dot_env_dot_example = DotEnvDotExample.new(dot_env: dot_env, filename: options.dot_example_path)
52
+ dot_env_dot_example.print_missing_keys_message
53
+ end
54
+ end
55
+
56
+ default_command :help
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,18 @@
1
+ require_relative "dot_example/version"
2
+ require_relative "dot_example/dot_env"
3
+ require_relative "dot_example/dot_env_dot_example"
4
+ require_relative "dot_example/pre_commit_hook"
5
+ require_relative "dot_example/post_checkout_hook"
6
+ require_relative "dot_example/hook"
7
+
8
+ module DotExample
9
+ def self.add_pre_commit_hook(dot_env_dot_example)
10
+ pre_commit_hook = PreCommitHook.find_or_create
11
+ pre_commit_hook.write!
12
+ end
13
+
14
+ def self.add_post_checkout_hook
15
+ post_checkout_hook = PostCheckoutHook.find_or_create
16
+ post_checkout_hook.write!
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ class DotEnv
2
+ def initialize(filename = nil)
3
+ @filename = filename || ".env"
4
+ end
5
+
6
+ attr_reader :filename
7
+
8
+ def key_lines
9
+ keys.map { |key| key + "=" }.join("\n")
10
+ end
11
+
12
+ def lint!
13
+ unless line.match(/^[^=\s]*=[^=\s]*$/)
14
+ # TODO: Don't know if this is the best error message
15
+ raise "Invalid Environment variable defintion"
16
+ end
17
+ end
18
+
19
+ def keys
20
+ lines.map do |line|
21
+ line.split("=")[0]
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def lines
28
+ File.readlines(filename)
29
+ end
30
+ end
@@ -0,0 +1,65 @@
1
+ class DotEnvDotExample
2
+ def initialize( options = {} )
3
+ @filename = options[:filename] || ".env.example"
4
+ @dot_env = options[:dot_env] || DotEnv.new
5
+ end
6
+
7
+ attr_reader :filename, :dot_env
8
+
9
+ def write!
10
+ if keys_new_to_example.any?
11
+ print_new_keys_message
12
+ File.open(filename, "a") do |file|
13
+ file.puts keys_new_to_example
14
+ end
15
+ end
16
+ end
17
+
18
+ def keys_new_to_example
19
+ dot_env.keys - keys
20
+ end
21
+
22
+ def print_new_keys_message
23
+ puts "*" * 60
24
+ puts "New variables added to #{filename}"
25
+ puts keys_new_to_example
26
+ puts "*" * 60
27
+ end
28
+
29
+ def missing_keys
30
+ keys.reject do |key|
31
+ dot_env.keys.include?(key)
32
+ end
33
+ end
34
+
35
+ def print_missing_keys_message
36
+ if missing_keys.any?
37
+ puts "*" * 60
38
+ puts "missing ENV variables from #{dot_env.filename}"
39
+ puts missing_keys
40
+ puts "*" * 60
41
+ end
42
+ end
43
+
44
+ def pre_commit_hook
45
+ # TODO: Make it possible to put .env and .env.example files somewhere else?
46
+ # Maybe later if people actually want this feature
47
+ [
48
+ "dot_example sync",
49
+ "git add .env.example"
50
+ ].join("\n")
51
+ end
52
+
53
+ private
54
+
55
+ def keys
56
+ lines.map{ |line| line.split("=")[0] }
57
+ end
58
+
59
+ def lines
60
+ unless Dir.glob(filename).any?
61
+ `touch #{filename}`
62
+ end
63
+ File.readlines(filename)
64
+ end
65
+ end
@@ -0,0 +1,2 @@
1
+ class Hook
2
+ end
@@ -0,0 +1,53 @@
1
+ class PostCheckoutHook < Hook
2
+ FILEPATH = File.join(".git", "hooks", "post-checkout")
3
+
4
+ def initialize(dot_env_dot_example = nil)
5
+ @dot_env_dot_example = dot_env_dot_example || DotEnvDotExample.new
6
+ @name = "post-checkout"
7
+ end
8
+
9
+ attr_reader :dot_env_dot_example, :name
10
+
11
+ def self.find_or_create
12
+ unless Dir.glob(FILEPATH).any?
13
+ %x[ touch #{FILEPATH} ]
14
+ %x[ chmod +x #{FILEPATH} ]
15
+ self.print_new_hook_message
16
+ end
17
+ new
18
+ end
19
+
20
+ def write!
21
+ unless contains_steps?
22
+ File.open(FILEPATH, "a") do |file|
23
+ file.puts steps
24
+ end
25
+ print_new_steps_message
26
+ end
27
+ end
28
+
29
+ def self.print_new_hook_message
30
+ puts "*" * 60
31
+ puts "New #{name} hook created"
32
+ puts "*" * 60
33
+ end
34
+
35
+ def print_new_steps_message
36
+ puts "*" * 60
37
+ puts "New steps added to #{name} hook"
38
+ puts steps
39
+ puts "*" * 60
40
+ end
41
+
42
+ def contains_steps?
43
+ contents.include?(steps)
44
+ end
45
+
46
+ def contents
47
+ File.read(FILEPATH)
48
+ end
49
+
50
+ def steps
51
+ "dot_example check"
52
+ end
53
+ end
@@ -0,0 +1,49 @@
1
+ require_relative './hook'
2
+
3
+ class PreCommitHook < Hook
4
+ FILEPATH = File.join(".git", "hooks", "pre-commit")
5
+
6
+ def initialize(dot_env_dot_example = nil)
7
+ @dot_env_dot_example = dot_env_dot_example || DotEnvDotExample.new
8
+ end
9
+
10
+ attr_reader :dot_env_dot_example
11
+
12
+ def self.find_or_create
13
+ unless Dir.glob(FILEPATH).any?
14
+ %x[ touch #{FILEPATH} ]
15
+ %x[ chmod +x #{FILEPATH} ]
16
+ self.print_new_pre_commit_hook_message
17
+ end
18
+ new
19
+ end
20
+
21
+ def self.print_new_pre_commit_hook_message
22
+ puts "*" * 60
23
+ puts "New pre-commit hook created"
24
+ puts "*" * 60
25
+ end
26
+
27
+ def write!
28
+ unless contains_dot_example_steps?
29
+ File.open(FILEPATH, "a") do |file|
30
+ file.puts dot_env_dot_example.pre_commit_hook
31
+ end
32
+ end
33
+ end
34
+
35
+ def print_new_steps_message
36
+ puts "*" * 60
37
+ puts "New steps added to pre-commit hook"
38
+ puts dot_env_dot_example.pre_commit_hook
39
+ puts "*" * 60
40
+ end
41
+
42
+ def contents
43
+ File.read(FILEPATH)
44
+ end
45
+
46
+ def contains_dot_example_steps?
47
+ contents.include?(dot_env_dot_example.pre_commit_hook)
48
+ end
49
+ end
@@ -0,0 +1,5 @@
1
+ module DotExample
2
+ VERSION = "1.0.0.pre"
3
+ SUMMARY = %q(Keep your project's environment variables in snyc across your team.)
4
+ DATE = %q{2016-9-21}
5
+ end
@@ -0,0 +1,17 @@
1
+ # TODO: Figure out whether it makes more sense to use rake tasks or just custom commands using commander.
2
+ namespace :dot_example do
3
+ desc "Setup the githooks to automate the dot_example tasks"
4
+ task :setup => :environment do
5
+ # Call other classes and do stuff
6
+ end
7
+
8
+ desc "Creates a new .env.example file with the keys from .env."
9
+ task :sync => :environment do
10
+ end
11
+
12
+ desc "Checks ENV keys to make sure they are up to date with those found in .env.example"
13
+ task :check => :environment do
14
+ # Call other classes and do stuff
15
+ end
16
+
17
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dot_example
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.pre
5
+ platform: ruby
6
+ authors:
7
+ - Stephen Mariano Cabrera
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-09-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: commander
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: dotenv
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.1'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 2.1.1
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '2.1'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.1.1
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.12'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.12'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '10.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '10.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: jazz_fingers
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '4.0'
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: 4.0.1
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: '4.0'
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: 4.0.1
109
+ description: Keep your project's environment variables in snyc across your team.
110
+ email:
111
+ - stephen.m.cabrera@gmail.com
112
+ executables:
113
+ - dot_example
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - README.md
118
+ - bin/console
119
+ - bin/dot_example
120
+ - bin/setup
121
+ - lib/dot_example.rb
122
+ - lib/dot_example/dot_env.rb
123
+ - lib/dot_example/dot_env_dot_example.rb
124
+ - lib/dot_example/hook.rb
125
+ - lib/dot_example/post_checkout_hook.rb
126
+ - lib/dot_example/pre_commit_hook.rb
127
+ - lib/dot_example/version.rb
128
+ - lib/tasks/dot_example.rake
129
+ homepage: https://www.github.com/smcabrera/dot_example
130
+ licenses:
131
+ - MIT
132
+ metadata: {}
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">"
145
+ - !ruby/object:Gem::Version
146
+ version: 1.3.1
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 2.4.8
150
+ signing_key:
151
+ specification_version: 4
152
+ summary: Keep your project's environment variables in snyc across your team.
153
+ test_files: []