Module: Addons::Recipe

Defined in:
lib/addons/recipes/recipe.rb,
lib/addons/recipes/instructions.rb

Defined Under Namespace

Modules: Instructions Classes: Commons

Constant Summary collapse

RECIPE_NAME_PLACEHOLDER =
"<RECIPE_NAME_PLACEHOLDER>"
RECIPE_VERSION_PLACEHOLDER =
"<RECIPE_VERSION_PLACEHOLDER>"
RECIPE_HANDLE_PLACEHOLDER =
"<RECIPE_HANDLE_PLACEHOLDER>"
@@step_count =
1
@@no_uncommitted_code_on_start_recipe =
false

Class Method Summary collapse

Class Method Details

.cleanup_git_on_errorObject



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/addons/recipes/recipe.rb', line 32

def self.cleanup_git_on_error
  if @@no_uncommitted_code_on_start_recipe
    # clear any uncommitted code we may have added, ONLY so long as we started with no uncommitted code.
    # NOTE: we definitely don't want to reset a user's own uncommitted code
    instruction = Addons::Recipe::Instructions::Git::GIT_RESET_HARD_HEAD

    result = `#{instruction["command"]}`
    # print the error message if we didnt get the expected result, use result.include? because GIT_RESET_HARD_HEAD uses CONTAINS_STRING
    puts instruction["error_msg"] unless result.include? instruction["expected_result"]["values"][0]
  end
end

.error(instruction, recipe) ⇒ Object



11
12
13
14
15
16
17
18
19
# File 'lib/addons/recipes/recipe.rb', line 11

def self.error(instruction, recipe)
  if instruction["error_msg"]
    print_message(instruction["error_msg"], recipe)
  end
  puts ""

  cleanup_git_on_error
  exit
end

.gsub_recipe_vars(message, recipe) ⇒ Object



29
30
31
# File 'lib/addons/recipes/recipe.rb', line 29

def self.gsub_recipe_vars(message, recipe)
  return message.gsub(RECIPE_VERSION_PLACEHOLDER, recipe["revision"]).gsub(RECIPE_NAME_PLACEHOLDER, recipe["name"]).gsub(RECIPE_HANDLE_PLACEHOLDER, recipe["handle"])
end


26
27
28
# File 'lib/addons/recipes/recipe.rb', line 26

def self.print_message(message, recipe)
  puts gsub_recipe_vars(message, recipe)
end

.process_instruction(instruction, recipe) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/addons/recipes/recipe.rb', line 91

def self.process_instruction(instruction, recipe)
  print_message(instruction["run_msg"], recipe)

  case instruction["type"]

  when InstructionTypes::DIRECTORY_EXISTS
    # check a directory exists
    if Dir.exists?(instruction["command"])
      success(instruction, recipe)
    else
      # exit
      return error(instruction, recipe)
    end
  # end InstructionTypes::DIRECTORY_EXISTS

  when InstructionTypes::DIRECTORY_CREATE
    # check a directory exists
    if Dir.exists?(instruction["command"]) || Dir.mkdir(instruction["command"])
      success(instruction, recipe)
    else
      # exit
      return error(instruction, recipe)
    end
  # end InstructionTypes::DIRECTORY_CREATE

  when InstructionTypes::TERMINAL_COMMAND
    result = `#{gsub_recipe_vars(instruction["command"], recipe)}`

    case instruction["expected_result"]["type"]
    when ResultTypes::NO_EXPECTATION
      success(instruction, recipe)
    when ResultTypes::CONTAINS_STRING
      if result.include? instruction["expected_result"]["values"][0]
        success(instruction, recipe)
      else
        return error(instruction, recipe)
      end
    when ResultTypes::IS_EXACT_STRING
      if instruction["expected_result"]["values"][0] == result
        return success(instruction, recipe)
      else
        return error(instruction, recipe)
      end
    when ResultTypes::DOES_NOT_CONTAIN_STRING
      instruction["expected_result"]["values"].each do |value|
        if result.include?(value)
          return error(instruction, recipe)
        end
      end # end value loop
      success(instruction, recipe)
    end # ResultTypes case
  # end InstructionTypes::TERMINAL_COMMAND

  when InstructionTypes::MODIFY_CODE
    case instruction["command"]["type"]
    when ModifyCodeTypes::ADD_CODE_REPLACE_FILE
      # open the file for appending
      File.open(instruction["command"]["file"], 'w') do |file|
        file.puts instruction["command"]["code"]
      end

      success(instruction, recipe)
    when ModifyCodeTypes::ADD_CODE, ModifyCodeTypes::COMMENT_CODE
      # open the file for editing
      if instruction["command"]["comment_code_if"]
        original_content = File.open(instruction["command"]["file"]).read()
        new_file = original_content
        updated = false

        content_to_comment = original_content.scan(instruction["command"]["comment_code_if"])

        content_to_comment.each do |content|
          replace_with = recipe_tag(recipe, "start_comment")
          replace_with += content.gsub(/^/, "# ")
          replace_with += recipe_tag(recipe, "end_comment")

          new_file = new_file.gsub(content, replace_with)

          updated = true
        end

        if updated
          File.open(instruction["command"]["file"], "w") do |file|
            file.write(new_file)
          end
        end
      end # end comment_code_if

      if instruction["command"]["code"]
        File.open(instruction["command"]["file"], 'a+') do |file|
          file.puts ""
          file.puts recipe_tag(recipe, "start")
          file.puts gsub_recipe_vars(instruction["command"]["code"], recipe)
          file.puts recipe_tag(recipe, "end")
        end
      end

      success(instruction, recipe)

    when ModifyCodeTypes::ADD_CODE_WITHOUT_TAGS
      File.open(instruction["command"]["file"], 'a+') do |file|
        file.puts gsub_recipe_vars(instruction["command"]["code"], recipe)
      end

      success(instruction, recipe)
    end # ModifyCodeTypes case
  # end InstructionTypes::MODIFY_CODE

  when InstructionTypes::SEARCH_AND_COMMENT
    instruction["search_queries"].each_with_index do |query, i|
      search_results = `grep '#{query}' -rI --exclude-dir=\.git ./`

      if search_results && search_results.length > 0
        # get filenames from each search result
        filenames = search_results.scan(/\.\/\/(.*?):/).uniq
        filenames = filenames.map {|inner_array| inner_array[0] }

        filenames.each do |filename|
          # create dynamic instruction with filename and instruction["comment_code_if"]
          dynamic_instruction = {
            "run_msg" => "Commenting #{instruction['comment_code_if'][i]} from #{filename}",
            "type" => InstructionTypes::MODIFY_CODE,
            "command" => {
              "type" => ModifyCodeTypes::COMMENT_CODE,
              "file" => filename,
              "comment_code_if" => instruction["comment_code_if"][i],
            },
            "error_msg" => "Error: Could not comment code in #{filename}"
          }
          # process dynamic instruction
          process_instruction dynamic_instruction, recipe
        end

      end
    end # end search_queries.each
    success(instruction, recipe)
  # end InstructionTypes::SEARCH_AND_COMMENT

  end # InstructionTypes case
end

.recipe_tag(recipe, type) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/addons/recipes/recipe.rb', line 77

def self.recipe_tag(recipe, type)
  if type == "comment"
    " \# LAUNCHPACK RECIPE - " + recipe["name"] + " version: " + recipe["revision"]
  elsif type == "start_comment"
    "\# LAUNCHPACK RECIPE COMMENT START - " + recipe["name"] + " version: " + recipe["revision"] + "\n"
  elsif type == "end_comment"
    "\n\# LAUNCHPACK RECIPE COMMENT END - " + recipe["name"] + " version: " + recipe["revision"] + "\n"
  elsif type == "start"
    "\# LAUNCHPACK RECIPE CODE START - " + recipe["name"] + " version: " + recipe["revision"]
  elsif type == "end"
    "\# LAUNCHPACK RECIPE CODE END - " + recipe["name"] + " version: " + recipe["revision"]
  end
end

.run(recipe) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/addons/recipes/recipe.rb', line 44

def self.run(recipe)
  puts "\r\nRunning Launchpack.io #{recipe["platform"]} recipe for: #{recipe["name"]}\r\n\r\n"

  Addons::Recipe::Commons::GIT_READY_RECIPE.each do |git_instruction|
    run_instruction(git_instruction, recipe)

    # if we didn't exit, and we see all code in Git is committed already, we can reset git if we see an error
    @@no_uncommitted_code_on_start_recipe = true if git_instruction == Addons::Recipe::Instructions::Git::GIT_ALL_CODE_COMMITTED
  end

  Addons::Recipe::Commons::START_RECIPE.each do |start_instruction|
    run_instruction(start_instruction, recipe)
  end

  recipe["instructions"].each do |instruction|
    run_instruction(instruction, recipe)
  end # do / instruction

  Addons::Recipe::Commons::END_RECIPE.each do |end_instruction|
    run_instruction(end_instruction, recipe)
  end

end

.run_instruction(instruction, recipe) ⇒ Object

run



68
69
70
71
72
73
74
75
# File 'lib/addons/recipes/recipe.rb', line 68

def self.run_instruction(instruction, recipe)
  puts "### Step #{@@step_count}: ###"

  process_instruction(instruction, recipe)

  puts ""
  @@step_count += 1
end

.success(instruction, recipe) ⇒ Object



20
21
22
23
24
25
# File 'lib/addons/recipes/recipe.rb', line 20

def self.success(instruction, recipe)
  if instruction["success_msg"]
    print_message(instruction["success_msg"], recipe)
  end
  puts ""
end