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 ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem "aruba", "~> 0.5"
7
+ gem "coveralls", "~> 0.7", require: false
8
+ gem "rspec", "~> 2.14"
9
+ end
10
+ gem 'git'
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
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/bin/figsify CHANGED
@@ -3,7 +3,9 @@
3
3
  require "figs/install"
4
4
 
5
5
  if ARGV.length > 1
6
- abort "Too many arguments; please specify only the yaml file location/git repo."
6
+ join = ARGV.join(",")
7
+ ARGV.clear
8
+ ARGV.push join
7
9
  end
8
10
 
9
11
  ARGV.push "install[#{ARGV.pop}]"
@@ -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
@@ -0,0 +1,4 @@
1
+ module Figs
2
+ class Error < StandardError; end
3
+ class MissingKey < Error; end
4
+ end
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module Figs
2
+ VERSION = "1.2.1"
3
+ end
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: 0.1.0
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-02-11 00:00:00.000000000 Z
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