addons 0.0.9 → 0.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 34d47952c09b18520a6a613dd4f73f73548f924d
4
- data.tar.gz: 91f7fd89e92b1eb2c77e70106cc4911dbf944af2
3
+ metadata.gz: 4b1f48899f1dcbaf1336913a3e4212ee1221bf0a
4
+ data.tar.gz: 6761392fc427226f1466592bf4942effee8b3c5e
5
5
  SHA512:
6
- metadata.gz: 9130ec44b10b49d157ef9137ebd3bb62a3eb20b7a07d8938c802e7cc3d5d7d8ef246152a2f33ac3ff1ac30cebbcdcc38e9d0c0d1e16f4278c1c568779a667fda
7
- data.tar.gz: bb1412197ba4e31355364b844fb351367c4176561fef8523db7b24f467148ead25e62ecdcaae36acbdce98458a4c1872b42938c80ab6881c117f76def7cafa05
6
+ metadata.gz: 2d6ec04265ee6c58aea869d1f88a365079deb94fd68efa7c01bb4b1513eb7962f57955007003fa0dc9cf4f42e132407248ac6fed2193b425ee1518bd8d5d231e
7
+ data.tar.gz: 7f27557fc9550412a72917aa0ed1631e45ae50e7b2a88709e663a382291e4675da5c27a59b6872887697623f48daa33b04cace039ad5e565d77d20b9a823141e
data/Gemfile CHANGED
@@ -2,3 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in addons.gemspec
4
4
  gemspec
5
+
6
+ gem 'rest_client'
7
+ gem 'json'
8
+ gem 'rails'
data/Gemfile.lock CHANGED
@@ -1,39 +1,38 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- addons (0.0.5)
5
- figaro
4
+ addons (0.1.0)
6
5
  json
7
6
 
8
7
  GEM
9
8
  remote: https://rubygems.org/
10
9
  specs:
11
- actionmailer (4.0.1)
12
- actionpack (= 4.0.1)
10
+ actionmailer (4.0.3)
11
+ actionpack (= 4.0.3)
13
12
  mail (~> 2.5.4)
14
- actionpack (4.0.1)
15
- activesupport (= 4.0.1)
13
+ actionpack (4.0.3)
14
+ activesupport (= 4.0.3)
16
15
  builder (~> 3.1.0)
17
16
  erubis (~> 2.7.0)
18
17
  rack (~> 1.5.2)
19
18
  rack-test (~> 0.6.2)
20
- activemodel (4.0.1)
21
- activesupport (= 4.0.1)
19
+ activemodel (4.0.3)
20
+ activesupport (= 4.0.3)
22
21
  builder (~> 3.1.0)
23
- activerecord (4.0.1)
24
- activemodel (= 4.0.1)
22
+ activerecord (4.0.3)
23
+ activemodel (= 4.0.3)
25
24
  activerecord-deprecated_finders (~> 1.0.2)
26
- activesupport (= 4.0.1)
25
+ activesupport (= 4.0.3)
27
26
  arel (~> 4.0.0)
28
27
  activerecord-deprecated_finders (1.0.3)
29
- activesupport (4.0.1)
28
+ activesupport (4.0.3)
30
29
  i18n (~> 0.6, >= 0.6.4)
31
30
  minitest (~> 4.2)
32
31
  multi_json (~> 1.3)
33
32
  thread_safe (~> 0.1)
34
33
  tzinfo (~> 0.3.37)
35
34
  arel (4.0.2)
36
- atomic (1.1.14)
35
+ atomic (1.1.16)
37
36
  builder (3.1.4)
38
37
  diff-lcs (1.2.5)
39
38
  erubis (2.7.0)
@@ -48,25 +47,28 @@ GEM
48
47
  treetop (~> 1.4.8)
49
48
  mime-types (1.25.1)
50
49
  minitest (4.7.5)
51
- multi_json (1.8.4)
52
- polyglot (0.3.3)
50
+ multi_json (1.9.2)
51
+ netrc (0.7.7)
52
+ polyglot (0.3.4)
53
53
  rack (1.5.2)
54
54
  rack-test (0.6.2)
55
55
  rack (>= 1.0)
56
- rails (4.0.1)
57
- actionmailer (= 4.0.1)
58
- actionpack (= 4.0.1)
59
- activerecord (= 4.0.1)
60
- activesupport (= 4.0.1)
56
+ rails (4.0.3)
57
+ actionmailer (= 4.0.3)
58
+ actionpack (= 4.0.3)
59
+ activerecord (= 4.0.3)
60
+ activesupport (= 4.0.3)
61
61
  bundler (>= 1.3.0, < 2.0)
62
- railties (= 4.0.1)
62
+ railties (= 4.0.3)
63
63
  sprockets-rails (~> 2.0.0)
64
- railties (4.0.1)
65
- actionpack (= 4.0.1)
66
- activesupport (= 4.0.1)
64
+ railties (4.0.3)
65
+ actionpack (= 4.0.3)
66
+ activesupport (= 4.0.3)
67
67
  rake (>= 0.8.7)
68
68
  thor (>= 0.18.1, < 2.0)
69
69
  rake (10.1.1)
70
+ rest_client (1.7.2)
71
+ netrc (~> 0.7.7)
70
72
  rspec (2.14.1)
71
73
  rspec-core (~> 2.14.0)
72
74
  rspec-expectations (~> 2.14.0)
@@ -75,7 +77,7 @@ GEM
75
77
  rspec-expectations (2.14.5)
76
78
  diff-lcs (>= 1.1.3, < 2.0)
77
79
  rspec-mocks (2.14.5)
78
- sprockets (2.10.1)
80
+ sprockets (2.11.0)
79
81
  hike (~> 1.2)
80
82
  multi_json (~> 1.0)
81
83
  rack (~> 1.0)
@@ -85,13 +87,13 @@ GEM
85
87
  activesupport (>= 3.0)
86
88
  sprockets (~> 2.8)
87
89
  thor (0.18.1)
88
- thread_safe (0.1.3)
89
- atomic
90
+ thread_safe (0.3.1)
91
+ atomic (>= 1.1.7, < 2)
90
92
  tilt (1.4.1)
91
93
  treetop (1.4.15)
92
94
  polyglot
93
95
  polyglot (>= 0.3.1)
94
- tzinfo (0.3.38)
96
+ tzinfo (0.3.39)
95
97
 
96
98
  PLATFORMS
97
99
  ruby
@@ -99,5 +101,9 @@ PLATFORMS
99
101
  DEPENDENCIES
100
102
  addons!
101
103
  bundler (~> 1.3)
104
+ figaro
105
+ json
106
+ rails
102
107
  rake
108
+ rest_client
103
109
  rspec (~> 2.6)
data/README.md CHANGED
@@ -16,9 +16,55 @@ Or install it yourself as:
16
16
 
17
17
  $ gem install addons
18
18
 
19
- ## Usage
19
+ ## Recipe Runner
20
+
21
+ To run all recipes related to your app, run this in your Terminal:
22
+ ```shell
23
+ rake addons:recipe:run[all]
24
+ ```
25
+
26
+ ### Recipes
27
+
28
+ #### Mailgun SMTP
29
+
30
+ Run the recipe
31
+ ```shell
32
+ rake addons:recipe:run[mailgun_smtp]
33
+ ```
34
+
35
+ Copy and paste this to the rails console to test your email settings
36
+ ```ruby
37
+ class TestMailer < ActionMailer::Base
38
+
39
+ default :from => "info@addonlist.com"
40
+
41
+ def welcome_email
42
+ mail(:to => "youremail@example.com", :subject => "Test Mailgun SMTP mail", :body => "Test Mailgun SMTP mail body")
43
+ end
44
+ end
45
+
46
+ TestMailer.welcome_email.deliver
47
+ ```
48
+
49
+ #### Mailgun HTTP
50
+
51
+ Run the recipe
52
+ ```shell
53
+ rake addons:recipe:run[mailgun_http]
54
+ ```
55
+
56
+ Copy and paste this to the rails console to test your email settings
57
+ ```ruby
58
+ email = {
59
+ to: "youremail@example.com",
60
+ from: "info@addonlist.com",
61
+ subject: "Test Mailgun HTTP mail",
62
+ body: "Test Mailgun HTTP mail body"
63
+ }
64
+
65
+ Addons::Mailgun.send_simple_message(email)
66
+ ```
20
67
 
21
- TODO: Write usage instructions here
22
68
 
23
69
  ## Contributing
24
70
 
data/addons.gemspec CHANGED
@@ -18,9 +18,11 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_dependency "rest_client"
21
22
  spec.add_dependency "json"
22
23
  spec.add_dependency "figaro"
23
24
 
25
+ spec.add_development_dependency "rails"
24
26
  spec.add_development_dependency "bundler", "~> 1.3"
25
27
  spec.add_development_dependency "rake"
26
28
  spec.add_development_dependency "rspec", "~> 2.6"
data/lib/addons.rb CHANGED
@@ -2,5 +2,5 @@ require "addons/version"
2
2
  require "addons/config"
3
3
 
4
4
  module Addons
5
- # Your code goes here...
5
+ require "addons/railtie" if defined?(Rails)
6
6
  end
data/lib/addons/config.rb CHANGED
@@ -2,7 +2,7 @@ require 'net/http'
2
2
  require 'open-uri'
3
3
  require 'json'
4
4
 
5
- BASE_CONFIG_URL = "https://launchbox.herokuapp.com/api/v1/apps/config"
5
+ BASE_CONFIG_URL = "https://launchpack.io/api/v1/apps/config"
6
6
 
7
7
  module Addons
8
8
  class Config
@@ -44,23 +44,6 @@ module Addons
44
44
 
45
45
  services = JSON.parse(response)
46
46
 
47
- # gitignore config/application.yml so we aren't storing sensitive info in .git
48
- # TODO: replace figaro with figaro-addons and application.yml with addons.yml
49
- gitignore = Rails.root.join('.gitignore')
50
- if File.readlines(gitignore).grep(/config\/application.yml/).size == 0
51
- File.open(gitignore, 'a') do |file|
52
- file.puts 'config/application.yml'
53
- end
54
- end
55
-
56
- figaro = Rails.root.join('Gemfile')
57
- if File.readlines(figaro).grep(/gem 'figaro'/).size == 0
58
- File.open(figaro, 'a') do |file|
59
- file.puts ""
60
- file.puts "gem 'figaro' # Addons dependency"
61
- end
62
- end
63
-
64
47
  # write config/application.yml to load env vars on startup
65
48
  filename = Rails.root.join('config', 'application.yml')
66
49
 
@@ -0,0 +1,10 @@
1
+ require 'addons'
2
+ require 'rails'
3
+
4
+ module Addons
5
+ class Railtie < Rails::Railtie
6
+ rake_tasks do
7
+ load "tasks/addons_recipe.rake"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,133 @@
1
+ module Addons
2
+ module Recipe
3
+ module Instructions
4
+ class Git
5
+ GIT_EXISTS = {
6
+ "run_msg" => "Verifying you're running this recipe in the top level of a Git repository.",
7
+ "type" => InstructionTypes::DIRECTORY_EXISTS,
8
+ "command" => "./.git",
9
+ "error_msg" => "Error: This is not the top level of a git repository. Must exit.",
10
+ }
11
+ GIT_ALL_CODE_COMMITTED = {
12
+ "run_msg" => "Verifying that you have no uncommitted code in Git",
13
+ "type" => InstructionTypes::TERMINAL_COMMAND,
14
+ "command" => "git status",
15
+ "expected_result" => {
16
+ "type" => ResultTypes::DOES_NOT_CONTAIN_STRING,
17
+ "values" => ["Changes not staged for commit", "Changes to be committed"]
18
+ },
19
+ "error_msg" => "Error: You have unstaged files or uncommitted changes in Git. Please commit or stash everything so we can start on a clean slate.",
20
+ }
21
+ GIT_COMMIT_RECIPE = {
22
+ "run_msg" => "Committing changes made by #{Addons::Recipe::RECIPE_NAME_PLACEHOLDER} version: #{Addons::Recipe::RECIPE_VERSION_PLACEHOLDER} Launchpack.io recipe",
23
+ "type" => InstructionTypes::TERMINAL_COMMAND,
24
+ "command" => "git add .; git commit -m \"LAUNCHPACK RECIPE - #{Addons::Recipe::RECIPE_NAME_PLACEHOLDER} version: #{Addons::Recipe::RECIPE_VERSION_PLACEHOLDER}\"",
25
+ "expected_result" => {
26
+ "type" => ResultTypes::NO_EXPECTATION
27
+ },
28
+ "error_msg" => "Error: Git commit for this recipe failed.",
29
+ }
30
+ GIT_RESET_HARD_HEAD = {
31
+ "run_msg" => "There was an error, so we're undoing our changes. If you cannot fix this based on the error message, contact support@addonlist.com.",
32
+ "type" => InstructionTypes::TERMINAL_COMMAND,
33
+ "command" => "git add .; git reset --hard HEAD",
34
+ "expected_result" => {
35
+ "type" => ResultTypes::DOES_NOT_CONTAIN_STRING,
36
+ "values" => ["HEAD is now at"]
37
+ },
38
+ "error_msg" => "Error: we could not reset our work in Git. We hope we cleaned up this recipe, but can't be sure."
39
+ }
40
+ end # class Git
41
+
42
+ class Rails
43
+ RAILS_INITIALIZERS_EXIST = {
44
+ "run_msg" => "Verifying you have a config/initializers directory, per Rails 4",
45
+ "type" => InstructionTypes::DIRECTORY_EXISTS,
46
+ "command" => "./config/initializers",
47
+ "error_msg" => "Error: This does not look like the Rails directory: config/initializers not found"
48
+ }
49
+ RAILS_INITIALIZERS_ADDONS_DIR = {
50
+ "run_msg" => "Creating config/initializers/addons directory",
51
+ "type" => InstructionTypes::DIRECTORY_CREATE,
52
+ "command" => "./config/initializers/addons",
53
+ "error_msg" => "Error: Could not create ./config/initializers/addons directory"
54
+ }
55
+ end # class Rails
56
+
57
+ class Bundler
58
+ BUNDLER_INSTALL = {
59
+ "run_msg" => "running bundle install",
60
+ "type" => InstructionTypes::TERMINAL_COMMAND,
61
+ "command" => "bundle install",
62
+ "expected_result" => {
63
+ "type" => ResultTypes::NO_EXPECTATION
64
+ },
65
+ "error_msg" => "Error: You have unstaged files or uncommitted changes in Git. Please commit or stash everything so we can start on a clean slate."
66
+ }
67
+ end # class Bundler
68
+
69
+ class Addons
70
+ ADDON_RECIPES_INSTALLED_EXISTS = {
71
+ "run_msg" => "Checking for your ./addon_recipes_installed.yml file",
72
+ "type" => InstructionTypes::TERMINAL_COMMAND,
73
+ "command" => "touch ./addon_recipes_installed.yml",
74
+ "expected_result" => {
75
+ "type" => ResultTypes::NO_EXPECTATION
76
+ },
77
+ "error_msg" => "Error: Problem creating addon_recipes_installed.yml to record your installed recipes"
78
+ }
79
+ RECIPE_HASNT_BEEN_RUN_BEFORE = {
80
+ "run_msg" => "Verifying you have not installed this recipe before",
81
+ "type" => InstructionTypes::TERMINAL_COMMAND,
82
+ "command" => "grep '<RECIPE_HANDLE_PLACEHOLDER>' ./addon_recipes_installed.yml",
83
+ "expected_result" => {
84
+ "type" => ResultTypes::IS_EXACT_STRING,
85
+ "values" => [""]
86
+ },
87
+ "error_msg" => "Error: This recipe (<RECIPE_NAME_PLACEHOLDER>) has been run before. It cannot be run again."
88
+ }
89
+ RECORD_RECIPE_INSTALLED = {
90
+ "run_msg" => "Adding \"<RECIPE_HANDLE_PLACEHOLDER>: '<RECIPE_VERSION_PLACEHOLDER>'\" to ./addon_recipes_installed.yml",
91
+ "type" => InstructionTypes::MODIFY_CODE,
92
+ "command" => {
93
+ "type" => ModifyCodeTypes::ADD_CODE_WITHOUT_TAGS,
94
+ "file" => "./addon_recipes_installed.yml",
95
+ "code" => "<RECIPE_HANDLE_PLACEHOLDER>: '<RECIPE_VERSION_PLACEHOLDER>'",
96
+ },
97
+ "error_msg" => "Error: Could not record recipe installation in ./addon_recipes_installed.yml"
98
+ }
99
+ end
100
+
101
+ end # module Instructions
102
+
103
+ class Commons
104
+ GIT_READY_RECIPE = [
105
+ # makes sure user has .git
106
+ Addons::Recipe::Instructions::Git::GIT_EXISTS,
107
+ # make sure no uncommitted code
108
+ Addons::Recipe::Instructions::Git::GIT_ALL_CODE_COMMITTED,
109
+ ]
110
+
111
+ START_RECIPE = [
112
+ # verify config/initializers directory
113
+ Addons::Recipe::Instructions::Rails::RAILS_INITIALIZERS_EXIST,
114
+
115
+ # make sure we're recording recipes that are being run
116
+ Addons::Recipe::Instructions::Addons::ADDON_RECIPES_INSTALLED_EXISTS,
117
+ # make sure this recipe hasn't been run before
118
+ Addons::Recipe::Instructions::Addons::RECIPE_HASNT_BEEN_RUN_BEFORE,
119
+
120
+ # create config/initializers/addons directory
121
+ Addons::Recipe::Instructions::Rails::RAILS_INITIALIZERS_ADDONS_DIR,
122
+ ]
123
+
124
+ END_RECIPE = [
125
+ # log this recipe installed in addon_recipes_installed.yml
126
+ Addons::Recipe::Instructions::Addons::RECORD_RECIPE_INSTALLED,
127
+ # commit changes in Git
128
+ Addons::Recipe::Instructions::Git::GIT_COMMIT_RECIPE,
129
+ ]
130
+ end
131
+
132
+ end # module Recipe
133
+ end # module Addons
@@ -0,0 +1,233 @@
1
+ module Addons
2
+ module Recipe
3
+
4
+ RECIPE_NAME_PLACEHOLDER = "<RECIPE_NAME_PLACEHOLDER>"
5
+ RECIPE_VERSION_PLACEHOLDER = "<RECIPE_VERSION_PLACEHOLDER>"
6
+ RECIPE_HANDLE_PLACEHOLDER = "<RECIPE_HANDLE_PLACEHOLDER>"
7
+
8
+ @@step_count = 1
9
+ @@no_uncommitted_code_on_start_recipe = false
10
+
11
+ def self.error(instruction, recipe)
12
+ if instruction["error_msg"]
13
+ print_message(instruction["error_msg"], recipe)
14
+ end
15
+ puts "✖"
16
+
17
+ cleanup_git_on_error
18
+ exit
19
+ end
20
+ def self.success(instruction, recipe)
21
+ if instruction["success_msg"]
22
+ print_message(instruction["success_msg"], recipe)
23
+ end
24
+ puts "✓"
25
+ end
26
+ def self.print_message(message, recipe)
27
+ puts gsub_recipe_vars(message, recipe)
28
+ end
29
+ def self.gsub_recipe_vars(message, recipe)
30
+ return message.gsub(RECIPE_VERSION_PLACEHOLDER, recipe["revision"]).gsub(RECIPE_NAME_PLACEHOLDER, recipe["name"]).gsub(RECIPE_HANDLE_PLACEHOLDER, recipe["handle"])
31
+ end
32
+ def self.cleanup_git_on_error
33
+ if @@no_uncommitted_code_on_start_recipe
34
+ # clear any uncommitted code we may have added, ONLY so long as we started with no uncommitted code.
35
+ # NOTE: we definitely don't want to reset a user's own uncommitted code
36
+ instruction = Addons::Recipe::Instructions::Git::GIT_RESET_HARD_HEAD
37
+
38
+ result = `#{instruction["command"]}`
39
+ # print the error message if we didnt get the expected result, use result.include? because GIT_RESET_HARD_HEAD uses CONTAINS_STRING
40
+ puts instruction["error_msg"] unless result.include? instruction["expected_result"]["values"][0]
41
+ end
42
+ end
43
+
44
+ def self.run(recipe)
45
+ puts "\r\nRunning Launchpack.io #{recipe["platform"]} recipe for: #{recipe["name"]}\r\n\r\n"
46
+
47
+ Addons::Recipe::Commons::GIT_READY_RECIPE.each do |git_instruction|
48
+ run_instruction(git_instruction, recipe)
49
+
50
+ # if we didn't exit, and we see all code in Git is committed already, we can reset git if we see an error
51
+ @@no_uncommitted_code_on_start_recipe = true if git_instruction == Addons::Recipe::Instructions::Git::GIT_ALL_CODE_COMMITTED
52
+ end
53
+
54
+ Addons::Recipe::Commons::START_RECIPE.each do |start_instruction|
55
+ run_instruction(start_instruction, recipe)
56
+ end
57
+
58
+ recipe["instructions"].each do |instruction|
59
+ run_instruction(instruction, recipe)
60
+ end # do / instruction
61
+
62
+ Addons::Recipe::Commons::END_RECIPE.each do |end_instruction|
63
+ run_instruction(end_instruction, recipe)
64
+ end
65
+
66
+ end # run
67
+
68
+ def self.run_instruction(instruction, recipe)
69
+ puts "### Step #{@@step_count}: ###"
70
+
71
+ process_instruction(instruction, recipe)
72
+
73
+ puts ""
74
+ @@step_count += 1
75
+ end
76
+
77
+ def self.recipe_tag(recipe, type)
78
+ if type == "comment"
79
+ " \# LAUNCHPACK RECIPE - " + recipe["name"] + " version: " + recipe["revision"]
80
+ elsif type == "start_comment"
81
+ "\# LAUNCHPACK RECIPE COMMENT START - " + recipe["name"] + " version: " + recipe["revision"] + "\n"
82
+ elsif type == "end_comment"
83
+ "\n\# LAUNCHPACK RECIPE COMMENT END - " + recipe["name"] + " version: " + recipe["revision"] + "\n"
84
+ elsif type == "start"
85
+ "\# LAUNCHPACK RECIPE CODE START - " + recipe["name"] + " version: " + recipe["revision"]
86
+ elsif type == "end"
87
+ "\# LAUNCHPACK RECIPE CODE END - " + recipe["name"] + " version: " + recipe["revision"]
88
+ end
89
+ end
90
+
91
+ def self.process_instruction(instruction, recipe)
92
+ print_message(instruction["run_msg"], recipe)
93
+
94
+ case instruction["type"]
95
+
96
+ when InstructionTypes::DIRECTORY_EXISTS
97
+ # check a directory exists
98
+ if Dir.exists?(instruction["command"])
99
+ success(instruction, recipe)
100
+ else
101
+ # exit
102
+ return error(instruction, recipe)
103
+ end
104
+ # end InstructionTypes::DIRECTORY_EXISTS
105
+
106
+ when InstructionTypes::DIRECTORY_CREATE
107
+ # check a directory exists
108
+ if Dir.exists?(instruction["command"]) || Dir.mkdir(instruction["command"])
109
+ success(instruction, recipe)
110
+ else
111
+ # exit
112
+ return error(instruction, recipe)
113
+ end
114
+ # end InstructionTypes::DIRECTORY_CREATE
115
+
116
+ when InstructionTypes::TERMINAL_COMMAND
117
+ result = `#{gsub_recipe_vars(instruction["command"], recipe)}`
118
+
119
+ case instruction["expected_result"]["type"]
120
+ when ResultTypes::NO_EXPECTATION
121
+ success(instruction, recipe)
122
+ when ResultTypes::CONTAINS_STRING
123
+ if result.include? instruction["expected_result"]["values"][0]
124
+ success(instruction, recipe)
125
+ else
126
+ return error(instruction, recipe)
127
+ end
128
+ when ResultTypes::IS_EXACT_STRING
129
+ if instruction["expected_result"]["values"][0] == result
130
+ return success(instruction, recipe)
131
+ else
132
+ return error(instruction, recipe)
133
+ end
134
+ when ResultTypes::DOES_NOT_CONTAIN_STRING
135
+ instruction["expected_result"]["values"].each do |value|
136
+ if result.include?(value)
137
+ return error(instruction, recipe)
138
+ end
139
+ end # end value loop
140
+ success(instruction, recipe)
141
+ end # ResultTypes case
142
+ # end InstructionTypes::TERMINAL_COMMAND
143
+
144
+ when InstructionTypes::MODIFY_CODE
145
+ case instruction["command"]["type"]
146
+ when ModifyCodeTypes::ADD_CODE_REPLACE_FILE
147
+ # open the file for appending
148
+ File.open(instruction["command"]["file"], 'w') do |file|
149
+ file.puts instruction["command"]["code"]
150
+ end
151
+
152
+ success(instruction, recipe)
153
+ when ModifyCodeTypes::ADD_CODE, ModifyCodeTypes::COMMENT_CODE
154
+ # open the file for editing
155
+ if instruction["command"]["comment_code_if"]
156
+ original_content = File.open(instruction["command"]["file"]).read()
157
+ new_file = original_content
158
+ updated = false
159
+
160
+ content_to_comment = original_content.scan(instruction["command"]["comment_code_if"])
161
+
162
+ content_to_comment.each do |content|
163
+ replace_with = recipe_tag(recipe, "start_comment")
164
+ replace_with += content.gsub(/^/, "# ")
165
+ replace_with += recipe_tag(recipe, "end_comment")
166
+
167
+ new_file = new_file.gsub(content, replace_with)
168
+
169
+ updated = true
170
+ end
171
+
172
+ if updated
173
+ File.open(instruction["command"]["file"], "w") do |file|
174
+ file.write(new_file)
175
+ end
176
+ end
177
+ end # end comment_code_if
178
+
179
+ if instruction["command"]["code"]
180
+ File.open(instruction["command"]["file"], 'a+') do |file|
181
+ file.puts ""
182
+ file.puts recipe_tag(recipe, "start")
183
+ file.puts gsub_recipe_vars(instruction["command"]["code"], recipe)
184
+ file.puts recipe_tag(recipe, "end")
185
+ end
186
+ end
187
+
188
+ success(instruction, recipe)
189
+
190
+ when ModifyCodeTypes::ADD_CODE_WITHOUT_TAGS
191
+ File.open(instruction["command"]["file"], 'a+') do |file|
192
+ file.puts gsub_recipe_vars(instruction["command"]["code"], recipe)
193
+ end
194
+
195
+ success(instruction, recipe)
196
+ end # ModifyCodeTypes case
197
+ # end InstructionTypes::MODIFY_CODE
198
+
199
+ when InstructionTypes::SEARCH_AND_COMMENT
200
+ instruction["search_queries"].each_with_index do |query, i|
201
+ search_results = `grep '#{query}' -rI --exclude-dir=\.git ./`
202
+
203
+ if search_results && search_results.length > 0
204
+ # get filenames from each search result
205
+ filenames = search_results.scan(/\.\/\/(.*?):/).uniq
206
+ filenames = filenames.map {|inner_array| inner_array[0] }
207
+
208
+ filenames.each do |filename|
209
+ # create dynamic instruction with filename and instruction["comment_code_if"]
210
+ dynamic_instruction = {
211
+ "run_msg" => "Commenting #{instruction['comment_code_if'][i]} from #{filename}",
212
+ "type" => InstructionTypes::MODIFY_CODE,
213
+ "command" => {
214
+ "type" => ModifyCodeTypes::COMMENT_CODE,
215
+ "file" => filename,
216
+ "comment_code_if" => instruction["comment_code_if"][i],
217
+ },
218
+ "error_msg" => "Error: Could not comment code in #{filename}"
219
+ }
220
+ # process dynamic instruction
221
+ process_instruction dynamic_instruction, recipe
222
+ end
223
+
224
+ end
225
+ end # end search_queries.each
226
+ success(instruction, recipe)
227
+ # end InstructionTypes::SEARCH_AND_COMMENT
228
+
229
+ end # InstructionTypes case
230
+ end # process_instruction
231
+
232
+ end # Recipe
233
+ end # Addons
@@ -0,0 +1,91 @@
1
+ static_recipes = [
2
+ {
3
+ name: "Mailgun SMTP",
4
+ handle: "mailgun_smtp",
5
+ version: "1",
6
+ platform: "Rails 4",
7
+ instructions: [
8
+ # search for existing smtp_settings and comment them out
9
+ {
10
+ run_msg: "Comment exsiting ActionMailer settings throughout the codebase",
11
+ type: InstructionTypes::SEARCH_AND_COMMENT,
12
+ search_queries: ["ActionMailer::Base.delivery_method", "ActionMailer::Base.smtp_settings"],
13
+ comment_code_if: [/ActionMailer::Base.delivery_method\s*=.*$/, /ActionMailer::Base.smtp_settings\s*=\s*{.*}/m],
14
+ error_msg: "Error: Please remove existing ActionMailer::Base.smtp_settings\n(found with: \"grep 'ActionMailer::Base.smtp_settings' -rI --exclude-dir=\.git ./\")"
15
+ },
16
+ # add config/initializers/mailgun.rb
17
+ {
18
+ run_msg: "Adding config/initializers/addons/mailgun_smtp.rb to configure ActiveMailer for Mailgun SMTP",
19
+ type: InstructionTypes::MODIFY_CODE,
20
+ command: {
21
+ type: ModifyCodeTypes::ADD_CODE_REPLACE_FILE,
22
+ file: "config/initializers/addons/mailgun_smtp.rb",
23
+ code: "\
24
+ ActionMailer::Base.smtp_settings = {\n\
25
+ :port => ENV['MAILGUN_SMTP_PORT'],\n\
26
+ :address => ENV['MAILGUN_SMTP_SERVER'],\n\
27
+ :user_name => ENV['MAILGUN_SMTP_LOGIN'],\n\
28
+ :password => ENV['MAILGUN_SMTP_PASSWORD'],\n\
29
+ :domain => 'example.com',\n\
30
+ :authentication => :plain,\n\
31
+ }\n\
32
+ ActionMailer::Base.delivery_method = :smtp\n\
33
+ "
34
+ },
35
+ error_msg: "There was a problem adding Addons::Mailgun.send_simple_email",
36
+ },
37
+ ]
38
+ },
39
+ {
40
+ name: "Mailgun HTTP",
41
+ handle: "mailgun_http",
42
+ version: "1",
43
+ platform: "Rails 4",
44
+ instructions: [
45
+ # install gem rest_client with Gemfile and run from terminal
46
+ {
47
+ run_msg: "Adding gem 'rest_client' to Gemfile",
48
+ type: InstructionTypes::MODIFY_CODE,
49
+ command: {
50
+ type: ModifyCodeTypes::ADD_CODE,
51
+ file: "Gemfile",
52
+ code: "gem 'rest_client'",
53
+ comment_code_if: /rest_client/,
54
+ },
55
+ error_msg: "Error: Could not add gem 'rest_client' to Gemfile"
56
+ },
57
+ Addons::Recipe::Instructions::Bundler::BUNDLER_INSTALL,
58
+ # add Addons::Mailgun.send_simple_email(email) code
59
+ {
60
+ run_msg: "Adding Addons::Mailgun.send_simple_email for sending simple emails",
61
+ type: InstructionTypes::MODIFY_CODE,
62
+ command: {
63
+ type: ModifyCodeTypes::ADD_CODE_REPLACE_FILE,
64
+ file: "config/initializers/addons/mailgun_http.rb",
65
+ code: "\
66
+ require 'rest_client'\n\
67
+ \n\
68
+ module Addons\n\
69
+ class Mailgun\n\
70
+ def self.send_simple_message(email)\n\
71
+ from = email[:from] || email[\"from\"] || email.from\n\
72
+ to = email[:to] || email[\"to\"] || email.to\n\
73
+ subject = email[:subject] || email[\"subject\"] || email.subject\n\
74
+ body = email[:body] || email[\"body\"] || email.body\n\
75
+ \n\
76
+ RestClient.post \"https://api:\#{ENV['MAILGUN_API_KEY']}\"\\\n\
77
+ \"@api.mailgun.net/v2/\#{ENV['MAILGUN_SMTP_LOGIN'].match(/@(.*)$/)[1]}/messages\",\n\
78
+ :from => from,\n\
79
+ :to => to,\n\
80
+ :subject => subject,\n\
81
+ :text => body\n\
82
+ end\n\
83
+ end # Mailgun\n\
84
+ end # Addons\n\
85
+ "
86
+ },
87
+ error_msg: "There was a problem adding Addons::Mailgun.send_simple_email",
88
+ },
89
+ ]
90
+ }, # end Mailgun HTTP
91
+ ]
@@ -0,0 +1,23 @@
1
+ class InstructionTypes
2
+ DIRECTORY_EXISTS = 0
3
+ DIRECTORY_CREATE = 1
4
+ TERMINAL_COMMAND = 2
5
+ MODIFY_CODE = 3
6
+ SEARCH_AND_COMMENT = 4
7
+ end
8
+
9
+ class ResultTypes
10
+ DOES_NOT_CONTAIN_STRING = 0
11
+ NO_EXPECTATION = 1
12
+ IS_EXACT_STRING = 2
13
+ CONTAINS_STRING = 3
14
+ end
15
+
16
+ class ModifyCodeTypes
17
+ COMMENT_CODE = 0
18
+ ADD_CODE = 1
19
+ REMOVE_CODE = 2
20
+ REPLACE_CODE = 3
21
+ ADD_CODE_REPLACE_FILE = 4
22
+ ADD_CODE_WITHOUT_TAGS = 5
23
+ end
@@ -1,3 +1,3 @@
1
1
  module Addons
2
- VERSION = "0.0.9"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -26,6 +26,30 @@ module Addons
26
26
  create_file "config/initializers/addons.rb", "# Addons initializer content\nAddons::Config.init()"
27
27
  end
28
28
 
29
+ def add_application_yml_to_gitignore
30
+ # gitignore config/application.yml so we aren't storing sensitive info in .git
31
+ # TODO: replace figaro with figaro-addons and application.yml with addons.yml
32
+ gitignore = Rails.root.join('.gitignore')
33
+ if File.readlines(gitignore).grep(/config\/application.yml/).size == 0
34
+ File.open(gitignore, 'a') do |file|
35
+ file.puts 'config/application.yml'
36
+ end
37
+ end
38
+ end
39
+
40
+ def add_figaro_gem
41
+ figaro = Rails.root.join('Gemfile')
42
+ if File.readlines(figaro).grep(/gem 'figaro'/).size == 0
43
+ File.open(figaro, 'a') do |file|
44
+ file.puts ""
45
+ file.puts "gem 'figaro' # Addons dependency"
46
+ end
47
+ end
48
+
49
+ # bundle install
50
+ result = `bundle install`
51
+ end
52
+
29
53
  def bootstrap_app_id_and_token
30
54
  # write config/application.yml to load env vars on startup
31
55
  filename = Rails.root.join('config', 'application.yml')
@@ -0,0 +1,44 @@
1
+ require 'rest_client'
2
+ require 'json'
3
+
4
+ require 'addons/recipes/types'
5
+ require 'addons/recipes/recipe'
6
+ require 'addons/recipes/instructions'
7
+
8
+ namespace :addons do
9
+ namespace :recipe do
10
+
11
+ desc "Run a recipe by name"
12
+ task :run, :recipe_handle do |t, args|
13
+ recipes = nil
14
+ recipeUrl = "https://launchpack.io/api/v1/apps/recipes?app_id=#{ENV['ADDONS_APP_ID']}&app_token=#{ENV['ADDONS_APP_TOKEN']}"
15
+
16
+ response = RestClient.get recipeUrl
17
+ recipes = JSON.parse response.body
18
+
19
+ # parse instructions into ruby
20
+ recipes.each { |recipe| recipe["instructions"] = JSON.parse(recipe["instructions"]) }
21
+
22
+ @run = false
23
+ if "all" == args[:recipe_handle]
24
+ puts "Running all your Launchpack.io recipes"
25
+
26
+ recipes.each do |recipe|
27
+ Addons::Recipe.run recipe
28
+ end
29
+ elsif handle = args[:recipe_handle]
30
+ recipes.each do |recipe|
31
+ # run recipe if it's the correct one
32
+ if handle == recipe["handle"]
33
+ @run = true
34
+ Addons::Recipe.run recipe
35
+ end
36
+ end
37
+ puts "Error: Recipe not found." unless @run
38
+ else
39
+ puts "Error: Incorrect usage. Expecting: `rake addons:recipe:run[recipe_handle]`"
40
+ end
41
+ end # end task: run
42
+
43
+ end # end namespace: recipe
44
+ end # end namespace: addons
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: addons
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Addonlist
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-08 00:00:00.000000000 Z
11
+ date: 2014-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest_client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: json
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +52,20 @@ dependencies:
38
52
  - - '>='
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: bundler
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -96,8 +124,14 @@ files:
96
124
  - addons.gemspec
97
125
  - lib/addons.rb
98
126
  - lib/addons/config.rb
127
+ - lib/addons/railtie.rb
128
+ - lib/addons/recipes/instructions.rb
129
+ - lib/addons/recipes/recipe.rb
130
+ - lib/addons/recipes/recipes.rb
131
+ - lib/addons/recipes/types.rb
99
132
  - lib/addons/version.rb
100
133
  - lib/generators/addons/install_generator.rb
134
+ - lib/tasks/addons_recipe.rake
101
135
  - spec/addons_spec.rb
102
136
  homepage: ''
103
137
  licenses: