figs 0.1.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/figs.png)](http://badge.fury.io/rb/figs)
|
3
|
+
[![Build Status](https://travis-ci.org/NYULibraries/figs.png?branch=master)](https://travis-ci.org/NYULibraries/figs)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/NYULibraries/figs.png)](https://codeclimate.com/github/NYULibraries/figs)
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/NYULibraries/figs/badge.png)](https://coveralls.io/r/NYULibraries/figs)
|
6
|
+
[![Dependency Status](https://gemnasium.com/NYULibraries/figs.png)](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
|