figs 0.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +10 -0
- data/README.md +62 -0
- data/Rakefile +6 -0
- data/bin/figsify +3 -1
- data/lib/figs/application.rb +124 -0
- data/lib/figs/env.rb +65 -0
- data/lib/figs/error.rb +4 -0
- data/lib/figs/figfile.rb +14 -0
- data/lib/figs/git_handler.rb +49 -0
- data/lib/figs/install.rb +28 -0
- data/lib/figs/tasks/install.rake +34 -0
- data/lib/figs/templates/application.yml +7 -0
- data/lib/figs/version.rb +3 -0
- data/lib/figs.rb +31 -0
- metadata +37 -2
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
## Figs
|
2
|
+
[](http://badge.fury.io/rb/figs)
|
3
|
+
[](https://travis-ci.org/NYULibraries/figs)
|
4
|
+
[](https://codeclimate.com/github/NYULibraries/figs)
|
5
|
+
[](https://coveralls.io/r/NYULibraries/figs)
|
6
|
+
[](https://gemnasium.com/NYULibraries/figs)
|
7
|
+
|
8
|
+
Railsless, herokuless, configurable, barebones figaro with a knack of using git repos for configuration files.
|
9
|
+
|
10
|
+
Simple app configuration
|
11
|
+
|
12
|
+
## What is this for?
|
13
|
+
|
14
|
+
Figs is for configuring apps, especially open source apps, much like Figaro. Whereas Figaro is great in that it works seamlessly with Rails 3 and 4, Figs also works with non Rails apps providing the same great ENV support, although in a slightly different way.
|
15
|
+
|
16
|
+
However, much like Figaro, Figs allows you to Open Source your app while keeping private things private.
|
17
|
+
|
18
|
+
## How does it work?
|
19
|
+
|
20
|
+
Figs is identical to Figaro in every way barring a few key differences. It uses `ENV` to store any string key-value pairs. However, sometimes its necessary to store more complex objects, such as arrays. `ENV` doesn't allow for objects, so we provide a souped-up wrapper called `Figs::Env` for this purpose! All keys are converted to strings and all non-string values are marshalled and stored in `ENV`, you can demarshall them yourself using `ENV` or rely on `Figs::Env.key_name` to do it fast and easy!
|
21
|
+
|
22
|
+
## Example.
|
23
|
+
|
24
|
+
Add Figs to your Gemfile then `bundle` command to install it:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
gem "figs"
|
28
|
+
```
|
29
|
+
|
30
|
+
Then you'll have to figsify your project so Figs can find where you keep your environment variables. If a location is not specified, a template will be created in the root directory as application.yml.
|
31
|
+
|
32
|
+
```
|
33
|
+
figsify
|
34
|
+
```
|
35
|
+
or
|
36
|
+
|
37
|
+
```
|
38
|
+
figsify config/settings1.yml config/settings2.yml config/settings3.yml
|
39
|
+
```
|
40
|
+
And finally
|
41
|
+
|
42
|
+
```
|
43
|
+
figsify git@github.com:GITHUBNAME/REPONAME.git filename1.yml config/filename2.yml
|
44
|
+
```
|
45
|
+
|
46
|
+
Now Figs will know where to find your environment vars!
|
47
|
+
|
48
|
+
__IMPORTANT:__ The order in which you load your files matters, as the environment variables perform a merge on the hashes, the right hand arguments taking precedence.
|
49
|
+
|
50
|
+
Then in ruby
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
Figs.load()
|
54
|
+
|
55
|
+
Settings.secret = ENV["SECRET"]
|
56
|
+
# OR
|
57
|
+
Settings.servers = Figs.env["server"]
|
58
|
+
```
|
59
|
+
|
60
|
+
## Thank you!
|
61
|
+
|
62
|
+
Figs was made possible by the kind folks at [Figaro](https://github.com/laserlemon/figaro)
|
data/Rakefile
ADDED
data/bin/figsify
CHANGED
@@ -0,0 +1,124 @@
|
|
1
|
+
require "erb"
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
require "figs/error"
|
5
|
+
require "figs/env"
|
6
|
+
require "figs/git_handler"
|
7
|
+
|
8
|
+
module Figs
|
9
|
+
class Application
|
10
|
+
FIGS_ENV_PREFIX = "_FIGS_"
|
11
|
+
|
12
|
+
include Enumerable
|
13
|
+
|
14
|
+
attr_writer :stage, :path
|
15
|
+
|
16
|
+
def initialize(options = {})
|
17
|
+
@figfile = options[:file]
|
18
|
+
@stage = options[:stage]
|
19
|
+
load_path
|
20
|
+
end
|
21
|
+
|
22
|
+
def locations
|
23
|
+
figfile["locations"]
|
24
|
+
end
|
25
|
+
|
26
|
+
def load_path
|
27
|
+
if figfile["method"].eql? "git"
|
28
|
+
@path = path_from_git(figfile["repo"], figfile["locations"])
|
29
|
+
else
|
30
|
+
@path = figfile["locations"]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def path_from_git(git_path, filenames = nil)
|
35
|
+
if(locations.is_a?(Array))
|
36
|
+
Figs::GitHandler.location(git_path, filenames)
|
37
|
+
else
|
38
|
+
Figs::GitHandler.location(git_path, @stage)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def figfile
|
43
|
+
(@figfile || default_figfile)
|
44
|
+
end
|
45
|
+
|
46
|
+
def path
|
47
|
+
(@path || default_path)
|
48
|
+
end
|
49
|
+
|
50
|
+
def stage
|
51
|
+
(@stage || default_stage).to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
def configuration
|
55
|
+
global_configuration.merge(stage_configuration)
|
56
|
+
end
|
57
|
+
|
58
|
+
def load
|
59
|
+
each do |key, value|
|
60
|
+
set(key, value) unless skip?(key)
|
61
|
+
end
|
62
|
+
ensure
|
63
|
+
Figs::GitHandler.clear_temp_files
|
64
|
+
end
|
65
|
+
|
66
|
+
def env
|
67
|
+
Figs::ENV
|
68
|
+
end
|
69
|
+
|
70
|
+
def each(&block)
|
71
|
+
configuration.each(&block)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def default_path
|
77
|
+
raise NotImplementedError
|
78
|
+
end
|
79
|
+
|
80
|
+
def default_stage
|
81
|
+
"test"
|
82
|
+
end
|
83
|
+
|
84
|
+
def default_figfile
|
85
|
+
raise NotImplementedError
|
86
|
+
end
|
87
|
+
|
88
|
+
def raw_configuration
|
89
|
+
(@parsed ||= Hash.new { |hash, path| hash[path] = parse(path) })[path]
|
90
|
+
end
|
91
|
+
|
92
|
+
def parse_path(path)
|
93
|
+
File.exist?(path) && YAML.load(ERB.new(File.read(path)).result) || {}
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse(paths)
|
97
|
+
parse = {}
|
98
|
+
paths.is_a?(Array) ? paths.each { |path| parse.merge!(parse_path(path)) } : parse.merge!(parse_path(paths))
|
99
|
+
parse
|
100
|
+
end
|
101
|
+
|
102
|
+
def global_configuration
|
103
|
+
raw_configuration.reject { |key, value| key.to_s.eql?(stage) && value.is_a?(Hash) }
|
104
|
+
end
|
105
|
+
|
106
|
+
def stage_configuration
|
107
|
+
raw_configuration.fetch(stage) { {} }
|
108
|
+
end
|
109
|
+
|
110
|
+
def set(key, value)
|
111
|
+
# FigsFigs::ENV.set_array(key, value) unless !value.is_a?(Array)
|
112
|
+
Figs::ENV[key] = value
|
113
|
+
Figs::ENV[FIGS_ENV_PREFIX + key.to_s] = value
|
114
|
+
end
|
115
|
+
|
116
|
+
def skip?(key)
|
117
|
+
Figs::ENV.key?(key.to_s) && !Figs::ENV.key?(FIGS_ENV_PREFIX + key.to_s)
|
118
|
+
end
|
119
|
+
|
120
|
+
def non_string_configuration!(value)
|
121
|
+
warn "WARNING: Use strings for Fig configuration. #{value.inspect} was converted to #{value.to_s.inspect}."
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/lib/figs/env.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
module Figs
|
3
|
+
module ENV
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def env
|
7
|
+
@env ||= ::ENV
|
8
|
+
end
|
9
|
+
|
10
|
+
def set(key,value)
|
11
|
+
env[key.to_s] = value.is_a?(String) ? value : YAML::dump(value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
return demarshall(env[key.to_s])
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(key,value)
|
19
|
+
set(key, value)
|
20
|
+
end
|
21
|
+
|
22
|
+
def demarshall(value)
|
23
|
+
value.nil? ? nil : YAML::load(value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def method_missing(method, *args, &block)
|
27
|
+
if matches_env?(method) then return env.send(method, *args, &block) end
|
28
|
+
|
29
|
+
key, punctuation = extract_key_from_method(method)
|
30
|
+
_, value = env.detect { |k, _| k.upcase == key }
|
31
|
+
|
32
|
+
value = demarshall(value)
|
33
|
+
|
34
|
+
case punctuation
|
35
|
+
when "!" then value || missing_key!(key)
|
36
|
+
when "?" then !!value
|
37
|
+
when nil then value
|
38
|
+
else super
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def extract_key_from_method(method)
|
43
|
+
method.to_s.upcase.match(/^(.+?)([!?=])?$/).captures
|
44
|
+
end
|
45
|
+
|
46
|
+
def missing_key!(key)
|
47
|
+
raise MissingKey.new("Missing required Figaro configuration key #{key.inspect}.")
|
48
|
+
end
|
49
|
+
|
50
|
+
def respond_to?(method, *)
|
51
|
+
return true if matches_env?(method)
|
52
|
+
key, punctuation = extract_key_from_method(method)
|
53
|
+
|
54
|
+
case punctuation
|
55
|
+
when "!" then env.keys.any? { |k| k.upcase == key } || super
|
56
|
+
when "?", nil then true
|
57
|
+
else super
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def matches_env?(method)
|
62
|
+
env.respond_to?(method)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/figs/error.rb
ADDED
data/lib/figs/figfile.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Figs
|
2
|
+
class Figfile
|
3
|
+
attr_reader :locations, :method, :repo
|
4
|
+
def initialize(*args)
|
5
|
+
@repo = args.shift if args.first.downcase.end_with?(".git")
|
6
|
+
@locations = args
|
7
|
+
@method = @repo.nil? ? "path" : "git"
|
8
|
+
end
|
9
|
+
|
10
|
+
def [](key)
|
11
|
+
send key
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "git"
|
2
|
+
|
3
|
+
module Figs
|
4
|
+
module GitHandler
|
5
|
+
extend self
|
6
|
+
TMP_GIT_DIR = "tmp/figs/"
|
7
|
+
|
8
|
+
def location(gitpath, filenames)
|
9
|
+
@temp_files = []
|
10
|
+
git_clone gitpath
|
11
|
+
temp_filenames(([]<< filenames).flatten)
|
12
|
+
rescue
|
13
|
+
clear_tmp_dir
|
14
|
+
clear_temp_files
|
15
|
+
end
|
16
|
+
|
17
|
+
def clear_temp_files
|
18
|
+
return unless !@temp_files.nil?
|
19
|
+
@temp_files.each { |temp_file| temp_file.close temp_file.unlink }
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def temp_filenames(filenames)
|
25
|
+
temp_files = []
|
26
|
+
filenames.each { |filename| temp_files << copy_to_temp_files(filename) }
|
27
|
+
clear_tmp_dir
|
28
|
+
temp_files
|
29
|
+
end
|
30
|
+
|
31
|
+
def copy_to_temp_files(filename)
|
32
|
+
temp_file = Tempfile.new("#{filename}")
|
33
|
+
temp_file.open
|
34
|
+
temp_file.write(File.open("#{TMP_GIT_DIR}#{filename}").read)
|
35
|
+
temp_file.flush
|
36
|
+
@temp_files << temp_file
|
37
|
+
temp_file.path
|
38
|
+
end
|
39
|
+
|
40
|
+
def git_clone(gitpath)
|
41
|
+
clear_tmp_dir
|
42
|
+
::Git.clone gitpath, TMP_GIT_DIR
|
43
|
+
end
|
44
|
+
|
45
|
+
def clear_tmp_dir
|
46
|
+
FileUtils.rm_rf TMP_GIT_DIR
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/figs/install.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "erb"
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
require "figs/error"
|
5
|
+
require 'rake'
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
module Figs
|
10
|
+
class Install < Rake::Application
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
super
|
14
|
+
|
15
|
+
@name = "figs"
|
16
|
+
@rakefiles = [File.expand_path(File.join(File.dirname(__FILE__),'tasks/install.rake'))]
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
Rake.application = self
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_task_name
|
25
|
+
"install"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'pathname'
|
3
|
+
require 'figs/figfile'
|
4
|
+
desc 'Install Fig'
|
5
|
+
task :install do |task, args|
|
6
|
+
base_dir = Pathname.new('.')
|
7
|
+
locations = args.extras.empty? ? "application.yml" : args.extras
|
8
|
+
figfile = Figs::Figfile.new(*locations)
|
9
|
+
|
10
|
+
create_figfile base_dir, figfile
|
11
|
+
create_non_existent_yaml(figfile.locations) if figfile.method.eql?("path")
|
12
|
+
|
13
|
+
puts "[Done] Enjoy your figs sir!"
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_figfile(base_dir, figfile)
|
17
|
+
puts "Figsifying #{base_dir}/ ..."
|
18
|
+
file = base_dir.join('Figfile')
|
19
|
+
File.open(file, 'w+') do |f|
|
20
|
+
f.write(figfile.to_yaml)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_non_existent_yaml(locations)
|
25
|
+
locations.each do |file|
|
26
|
+
if !File.exists?(file)
|
27
|
+
puts "[Add] #{file} does not exist, creating."
|
28
|
+
application_yml = File.expand_path("../../templates/application.yml", __FILE__)
|
29
|
+
File.open(file, 'w+') do |f|
|
30
|
+
f.write(ERB.new(File.read(application_yml)).result(binding))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Add application configuration variables here, as shown below.
|
2
|
+
#
|
3
|
+
# PUSHER_APP_ID: "2954"
|
4
|
+
# PUSHER_KEY: 7381a978f7dd7f9a1117
|
5
|
+
# PUSHER_SECRET: abdc3b896a0ffb85d373
|
6
|
+
# STRIPE_API_KEY: EdAvEPVEC3LuaTg5Q3z6WbDVqZlcBQ8Z
|
7
|
+
# STRIPE_PUBLIC_KEY: pk_BRgD57O8fHja9HxduJUszhef6jCyS
|
data/lib/figs/version.rb
ADDED
data/lib/figs.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require "figs/application"
|
2
|
+
require "figs/env"
|
3
|
+
require "figs/figfile"
|
4
|
+
|
5
|
+
module Figs
|
6
|
+
extend self
|
7
|
+
|
8
|
+
attr_writer :backend, :application
|
9
|
+
|
10
|
+
def env
|
11
|
+
application.env
|
12
|
+
end
|
13
|
+
|
14
|
+
def backend
|
15
|
+
@backend ||= Figs::Application
|
16
|
+
end
|
17
|
+
|
18
|
+
def application(options = {})
|
19
|
+
@application ||= backend.new({:file => figfile, :stage => options[:stage]})
|
20
|
+
end
|
21
|
+
|
22
|
+
def load(options = {})
|
23
|
+
application({:stage => options[:stage]}).load
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def figfile
|
29
|
+
@figfile ||=YAML.load(ERB.new(File.read('Figfile')).result)
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: figs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-03-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -43,6 +43,22 @@ dependencies:
|
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 2.0.5
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: git
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.2.6
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.2.6
|
46
62
|
description: Simple app configuration using ENV and YAML files
|
47
63
|
email: hab278@nyu.edu
|
48
64
|
executables:
|
@@ -50,7 +66,20 @@ executables:
|
|
50
66
|
extensions: []
|
51
67
|
extra_rdoc_files: []
|
52
68
|
files:
|
69
|
+
- lib/figs/application.rb
|
70
|
+
- lib/figs/env.rb
|
71
|
+
- lib/figs/error.rb
|
72
|
+
- lib/figs/figfile.rb
|
73
|
+
- lib/figs/git_handler.rb
|
74
|
+
- lib/figs/install.rb
|
75
|
+
- lib/figs/tasks/install.rake
|
76
|
+
- lib/figs/templates/application.yml
|
77
|
+
- lib/figs/version.rb
|
78
|
+
- lib/figs.rb
|
53
79
|
- bin/figsify
|
80
|
+
- Rakefile
|
81
|
+
- Gemfile
|
82
|
+
- README.md
|
54
83
|
homepage: https://github.com/NYULibraries/figs
|
55
84
|
licenses:
|
56
85
|
- MIT
|
@@ -64,12 +93,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
64
93
|
- - ! '>='
|
65
94
|
- !ruby/object:Gem::Version
|
66
95
|
version: '0'
|
96
|
+
segments:
|
97
|
+
- 0
|
98
|
+
hash: 4045786731158848396
|
67
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
100
|
none: false
|
69
101
|
requirements:
|
70
102
|
- - ! '>='
|
71
103
|
- !ruby/object:Gem::Version
|
72
104
|
version: '0'
|
105
|
+
segments:
|
106
|
+
- 0
|
107
|
+
hash: 4045786731158848396
|
73
108
|
requirements: []
|
74
109
|
rubyforge_project:
|
75
110
|
rubygems_version: 1.8.23
|