kaya 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +26 -0
- data/CHANGELOG +52 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/NOTAS +19 -0
- data/README.md +279 -0
- data/Rakefile +1 -0
- data/bin/kaya +4 -0
- data/documentation/api.md +47 -0
- data/documentation/api_execution_data.md +47 -0
- data/documentation/configuration.md +13 -0
- data/documentation/custom_parameters.md +117 -0
- data/documentation/document_kaya.md +122 -0
- data/documentation/link.md +12 -0
- data/documentation/results.md +119 -0
- data/documentation/start.md +19 -0
- data/documentation/suites.md +60 -0
- data/documentation/test_suite_information.md +9 -0
- data/kaya.gemspec +42 -0
- data/lib/generators/task_rack.rb +160 -0
- data/lib/generators/templates/Gemfile.tt +2 -0
- data/lib/generators/templates/config.ru.tt +2 -0
- data/lib/generators/templates/kaya_conf.tt +49 -0
- data/lib/generators/templates/kaya_log.tt +0 -0
- data/lib/generators/templates/sidekiq_log.tt +0 -0
- data/lib/generators/templates/tasks.kaya.tt +10 -0
- data/lib/generators/templates/unicorn.rb.tt +21 -0
- data/lib/kaya/API/error.rb +17 -0
- data/lib/kaya/API/execution.rb +141 -0
- data/lib/kaya/API/result.rb +49 -0
- data/lib/kaya/API/results.rb +31 -0
- data/lib/kaya/API/suite.rb +42 -0
- data/lib/kaya/API/suites.rb +36 -0
- data/lib/kaya/background_jobs/sidekiq.rb +35 -0
- data/lib/kaya/background_jobs/workers/execution_checker.rb +20 -0
- data/lib/kaya/background_jobs/workers/garbage_cleaner.rb +31 -0
- data/lib/kaya/commands/bye.rb +12 -0
- data/lib/kaya/commands/help.rb +13 -0
- data/lib/kaya/commands/install.rb +27 -0
- data/lib/kaya/commands/reset.rb +39 -0
- data/lib/kaya/commands/reset_suites.rb +40 -0
- data/lib/kaya/commands/restart.rb +9 -0
- data/lib/kaya/commands/start.rb +104 -0
- data/lib/kaya/commands/stop.rb +53 -0
- data/lib/kaya/cuba.rb +287 -0
- data/lib/kaya/cucumber/features.rb +15 -0
- data/lib/kaya/cucumber/task.rb +64 -0
- data/lib/kaya/custom/execution_data.rb +50 -0
- data/lib/kaya/custom/params.rb +34 -0
- data/lib/kaya/database/mongo_connector.rb +285 -0
- data/lib/kaya/error/errors.rb +55 -0
- data/lib/kaya/execution.rb +57 -0
- data/lib/kaya/results/result.rb +493 -0
- data/lib/kaya/results/results.rb +47 -0
- data/lib/kaya/suites/custom/params.rb +151 -0
- data/lib/kaya/suites/suite.rb +177 -0
- data/lib/kaya/suites/suites.rb +130 -0
- data/lib/kaya/support/clean.rb +12 -0
- data/lib/kaya/support/configuration.rb +254 -0
- data/lib/kaya/support/console.rb +11 -0
- data/lib/kaya/support/documentation.rb +34 -0
- data/lib/kaya/support/error_handler_helper.rb +24 -0
- data/lib/kaya/support/files_cleanner.rb +136 -0
- data/lib/kaya/support/git.rb +161 -0
- data/lib/kaya/support/if_config.rb +14 -0
- data/lib/kaya/support/logo.rb +23 -0
- data/lib/kaya/support/logs.rb +37 -0
- data/lib/kaya/support/notification.rb +127 -0
- data/lib/kaya/support/processes.rb +96 -0
- data/lib/kaya/support/query_string.rb +22 -0
- data/lib/kaya/support/request.rb +32 -0
- data/lib/kaya/support/risk.rb +9 -0
- data/lib/kaya/support/time_helper.rb +11 -0
- data/lib/kaya/support/update.rb +65 -0
- data/lib/kaya/version.rb +3 -0
- data/lib/kaya/view/body.mote +60 -0
- data/lib/kaya/view/custom/params/select_list.mote +14 -0
- data/lib/kaya/view/custom/params/text.mote +9 -0
- data/lib/kaya/view/custom/params.mote +9 -0
- data/lib/kaya/view/error_handler.mote +40 -0
- data/lib/kaya/view/features/feature.mote +14 -0
- data/lib/kaya/view/features/features_list.mote +10 -0
- data/lib/kaya/view/features.mote +57 -0
- data/lib/kaya/view/footer.mote +10 -0
- data/lib/kaya/view/git_information.mote +21 -0
- data/lib/kaya/view/help/main.mote +21 -0
- data/lib/kaya/view/help/page.mote +2 -0
- data/lib/kaya/view/help/search_result.mote +29 -0
- data/lib/kaya/view/help.mote +72 -0
- data/lib/kaya/view/javascript.mote +96 -0
- data/lib/kaya/view/logs/log.mote +3 -0
- data/lib/kaya/view/modals.mote +31 -0
- data/lib/kaya/view/navigation_bar.mote +48 -0
- data/lib/kaya/view/not_found.mote +40 -0
- data/lib/kaya/view/parser.rb +79 -0
- data/lib/kaya/view/results/all.mote +59 -0
- data/lib/kaya/view/results/console.mote +106 -0
- data/lib/kaya/view/results/detailed_info.mote +112 -0
- data/lib/kaya/view/results/report.mote +1 -0
- data/lib/kaya/view/results/result.mote +23 -0
- data/lib/kaya/view/results/results.mote +52 -0
- data/lib/kaya/view/screenshot.mote +42 -0
- data/lib/kaya/view/sections.rb +25 -0
- data/lib/kaya/view/styles.mote +58 -0
- data/lib/kaya/view/suites/suite.mote +73 -0
- data/lib/kaya/view/suites/suites.mote +9 -0
- data/lib/kaya/view/view.rb +72 -0
- data/lib/kaya.rb +175 -0
- data/test/features/install.feature +18 -0
- data/test/features/support/env.rb +3 -0
- metadata +395 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
require 'mongo'
|
|
2
|
+
|
|
3
|
+
module Kaya
|
|
4
|
+
module Database
|
|
5
|
+
class MongoConnector
|
|
6
|
+
|
|
7
|
+
include Mongo
|
|
8
|
+
|
|
9
|
+
def initialize(opts={host: "localhost", port: 27017, username: nil, pass: nil})
|
|
10
|
+
|
|
11
|
+
project_name = Dir.pwd.split("/").last
|
|
12
|
+
@@db_name = "#{project_name}_kaya"
|
|
13
|
+
|
|
14
|
+
@@client = MongoClient.new(opts[:host], opts[:port])
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@@db = @@client.db(@@db_name)
|
|
18
|
+
@@auth = @@db.authenticate(opts[:username], opts[:pass]) if opts[:username] and opts[:pass]
|
|
19
|
+
|
|
20
|
+
@@suites = @@db.collection("suites")
|
|
21
|
+
@@suites.ensure_index({"last_result" => 1})
|
|
22
|
+
|
|
23
|
+
@@results = @@db.collection("results")
|
|
24
|
+
@@results.ensure_index({"_id" => 1})
|
|
25
|
+
@@results.ensure_index({"started_at" => 1, "_id" => 1})
|
|
26
|
+
|
|
27
|
+
@@documentation = @@db.collection("documentation")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.connected?
|
|
31
|
+
begin
|
|
32
|
+
@@db and true
|
|
33
|
+
rescue
|
|
34
|
+
false
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Removes all documents of documentation from the DB
|
|
39
|
+
def self.clean_documentation
|
|
40
|
+
@@db.drop_collection("documentation")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Inserts a document of documentation in the DB
|
|
44
|
+
def self.insert_documentation document
|
|
45
|
+
@@documentation.insert(document)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Return an array with all documents of documentation
|
|
49
|
+
def self.get_all_documentation
|
|
50
|
+
@@documentation.find().to_a
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Returns the body html of a page
|
|
54
|
+
def self.help_body page
|
|
55
|
+
result = @@documentation.find({"title" => page}).to_a.first
|
|
56
|
+
result["body"].to_s if result != nil
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Returns the title of a page
|
|
60
|
+
def self.help_title page
|
|
61
|
+
result = @@documentation.find({"title" => page}).to_a.first
|
|
62
|
+
result["title"].to_s.gsub('_', ' ').capitalize if result != nil
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Returns a document from the DB for a certain title
|
|
66
|
+
def self.help_search title
|
|
67
|
+
@@documentation.find({:$or => [{ "title" => /#{title}/ },{ "title" => /#{title.upcase}/ },{ "body" => /#{title}/ }]}).to_a
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self.generate_id
|
|
71
|
+
Time.now.to_f.to_s.gsub( ".","")[0..12].to_i
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Returns a list of collections
|
|
75
|
+
def self.collections
|
|
76
|
+
["suites","results"]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Drops all kaya collections
|
|
80
|
+
def self.drop_collections
|
|
81
|
+
db = self.kaya_db
|
|
82
|
+
collections.each do |collection|
|
|
83
|
+
db.drop_collection(collection) if collection != "documentation"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def self.kaya_db
|
|
88
|
+
MongoClient.new().db(@@db_name)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Update suites collection with suites that comes from cucumber.yml file
|
|
92
|
+
# All given suites will be active. Others will be deactivated
|
|
93
|
+
# @param [Hash] cucumber_yml_suites
|
|
94
|
+
def self.update_suites cucumber_yml_suites
|
|
95
|
+
|
|
96
|
+
existing_suites = self.suites
|
|
97
|
+
|
|
98
|
+
existing_suites_name_list = existing_suites.map{|suite| suite["name"]}
|
|
99
|
+
|
|
100
|
+
cucumber_yml_suites.each_with_index do |cucumber_suite, index|
|
|
101
|
+
|
|
102
|
+
suite_data = existing_suites.select{|suite| suite["name"]==cucumber_suite["name"]}.first
|
|
103
|
+
|
|
104
|
+
# if exist, so update it, else creates a new one
|
|
105
|
+
if suite_data
|
|
106
|
+
#Delete it from list and update it
|
|
107
|
+
existing_suites.delete(suite_data)
|
|
108
|
+
suite_data["command"] = cucumber_suite["command"]
|
|
109
|
+
suite_data["custom"] = cucumber_suite["custom"]
|
|
110
|
+
suite_data["active"] = true
|
|
111
|
+
suite_data["index"] = index
|
|
112
|
+
|
|
113
|
+
# Updates register with new data
|
|
114
|
+
self.update_suite(suite_data)
|
|
115
|
+
print "UPDATED: #{suite_data['_id']}\n\n"
|
|
116
|
+
else
|
|
117
|
+
# Creates a new one
|
|
118
|
+
suite_data = self.suite_data_structure
|
|
119
|
+
suite_data["name"] = cucumber_suite["name"]
|
|
120
|
+
suite_data["command"] = cucumber_suite["command"]
|
|
121
|
+
suite_data["custom"] = cucumber_suite["custom"]
|
|
122
|
+
suite_data["branch"] = Kaya::Support::Git.actual_branch
|
|
123
|
+
|
|
124
|
+
# Saves register with new data
|
|
125
|
+
id = self.insert_suite(suite_data)
|
|
126
|
+
|
|
127
|
+
print "INSERTED: #{id}\n\n"
|
|
128
|
+
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# If at least one existing suite isn't con cucumber yml file, so deactivate them
|
|
135
|
+
unless existing_suites.empty?
|
|
136
|
+
existing_suites.each do |suite|
|
|
137
|
+
|
|
138
|
+
print "DEACTIVATED: #{suite['_id']}\n\n"
|
|
139
|
+
deactivate_suite(suite["_id"])
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# Inserts a suite in suites collection
|
|
146
|
+
# @param [Hash] suite_data (see suite_data_structure method)
|
|
147
|
+
def self.insert_suite suite_data
|
|
148
|
+
@@suites.insert(suite_data)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
# Update record for a given suite
|
|
153
|
+
# @param [Hash] suite_data
|
|
154
|
+
def self.update_suite suite_data
|
|
155
|
+
@@suites.update( {"_id" => suite_data["_id"]}, suite_data)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Returns the entire record for a given suite name
|
|
159
|
+
# @param [String] suite_name
|
|
160
|
+
# @return [Hash] all suite data
|
|
161
|
+
def self.suite_data_for suite_id
|
|
162
|
+
suite_id = suite_id.to_i if suite_id.respond_to? :to_i
|
|
163
|
+
@@suites.find({"_id" => suite_id}).to_a.first
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def self.suite_data_for_name(suite_name)
|
|
167
|
+
id = self.suite_id_for(suite_name)
|
|
168
|
+
@@suites.find({"_id" => id}).to_a.first
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Returns the _id for a given suite name
|
|
172
|
+
# @param [String] suite_name
|
|
173
|
+
# @return [String] _id
|
|
174
|
+
def self.suite_id_for suite_name, active=nil
|
|
175
|
+
criteria = {"name" => suite_name}
|
|
176
|
+
criteria.store("active",true) if active
|
|
177
|
+
result = @@suites.find(criteria).to_a.first
|
|
178
|
+
result.nil? ? nil : result["_id"]
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def self.suites active=true
|
|
182
|
+
criteria ={}
|
|
183
|
+
criteria["active"]=active if active
|
|
184
|
+
@@suites.ensure_index({"last_result" => 1})
|
|
185
|
+
@@suites.find(criteria, :sort => ["last_result", -1]).to_a || []
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Returns all active suites
|
|
189
|
+
def self.all_suites
|
|
190
|
+
@@suites.find({"active" => true}).to_a
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
# RESULTS COLLECTION METHODS
|
|
197
|
+
|
|
198
|
+
# Creates a result data andc
|
|
199
|
+
# returns de id for that register
|
|
200
|
+
# @param [Hash] execution_data
|
|
201
|
+
# @return [String] id for created result
|
|
202
|
+
def self.insert_result(result_data)
|
|
203
|
+
begin
|
|
204
|
+
@@results.insert(result_data)
|
|
205
|
+
true
|
|
206
|
+
rescue
|
|
207
|
+
false
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Returns all results for a given suite_id
|
|
212
|
+
def self.results_for suite_id
|
|
213
|
+
@@results.ensure_index({"started_at" => 1, "_id" => 1})
|
|
214
|
+
res = @@results.find({}, :sort => ["started_at", -1]).to_a
|
|
215
|
+
unless res.empty?
|
|
216
|
+
res.select{|result| result["suite"]["id"]==ensure_int(suite_id)}
|
|
217
|
+
else
|
|
218
|
+
[]
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Updates result register with the given data
|
|
223
|
+
#
|
|
224
|
+
def self.update_result result_data_structure
|
|
225
|
+
begin
|
|
226
|
+
@@results.update( {"_id" => result_data_structure["_id"]}, result_data_structure)
|
|
227
|
+
true
|
|
228
|
+
rescue
|
|
229
|
+
false
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def self.result_data_for_id(result_id)
|
|
234
|
+
@@results.find({"_id" => ensure_int(result_id)}).to_a.first
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# Returns value as Fixnum if it is not
|
|
239
|
+
# @param [Object] value
|
|
240
|
+
# @return [Fixnum]
|
|
241
|
+
def self.ensure_int(value)
|
|
242
|
+
value and value.to_i if value.respond_to? :to_i
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Returns all result
|
|
246
|
+
# @return [Array] results from results coll
|
|
247
|
+
def self.all_results
|
|
248
|
+
@@results.ensure_index({"started_at" => 1, "_id" => 1})
|
|
249
|
+
res = @@results.find({}, :sort => ['_id', -1])
|
|
250
|
+
if res
|
|
251
|
+
res.to_a
|
|
252
|
+
else
|
|
253
|
+
[]
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def self.all_results_ids
|
|
258
|
+
all_results.map{|res| res['_id']}
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def self.find_results_for_key key
|
|
262
|
+
all_actual_results = self.all_results
|
|
263
|
+
if !all_actual_results.empty?
|
|
264
|
+
all_actual_results.select do |result|
|
|
265
|
+
result["suite"]["name"].include?(key) or result["execution_name"].include?(key) or result["summary"].include?(key) or result["command"].include?(key)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def self.find_results_for_status status
|
|
271
|
+
all_actual_results = self.all_results
|
|
272
|
+
if !all_actual_results.empty?
|
|
273
|
+
all_actual_results.select do |result|
|
|
274
|
+
result["summary"].include?(status) or result["status"].include?(status)
|
|
275
|
+
end.map{|result| result["_id"]}
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def self.find_by criteria={}
|
|
280
|
+
search_criteria = {}
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Kaya
|
|
2
|
+
module Error
|
|
3
|
+
# Raised when there is an error related to Suites.
|
|
4
|
+
class Suite < StandardError
|
|
5
|
+
attr_reader :suite_name
|
|
6
|
+
|
|
7
|
+
def initialize(suite_name, message=nil)
|
|
8
|
+
@suite_name = suite_name
|
|
9
|
+
message = message
|
|
10
|
+
super(message)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Raised when there is an error related to Results.
|
|
15
|
+
class Result < StandardError
|
|
16
|
+
attr_reader :id
|
|
17
|
+
|
|
18
|
+
def initialize(id, message=nil)
|
|
19
|
+
@id = id
|
|
20
|
+
message = message
|
|
21
|
+
super(message)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class KayaFile < StandardError
|
|
27
|
+
def initialize file_path
|
|
28
|
+
super("Could not find '#{file_path} file" )
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class KayaDir < StandardError
|
|
33
|
+
def initialize file_path
|
|
34
|
+
super("Could not find '#{file_path}' dir")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Raised when there is an error related to Results
|
|
39
|
+
class CucumberYML < StandardError
|
|
40
|
+
|
|
41
|
+
def initialize()
|
|
42
|
+
super("Could not find cucumber.yml file to get test suites from")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Raised when there is an error related to Help.
|
|
48
|
+
class Help < StandardError
|
|
49
|
+
def initialize(message=nil)
|
|
50
|
+
message = message
|
|
51
|
+
super(message)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Kaya
|
|
2
|
+
class Execution
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# Run/Execute the commmand
|
|
6
|
+
# @param [Hash] execution_data = { :suite_id, :label }
|
|
7
|
+
def self.run! execution_request_data
|
|
8
|
+
|
|
9
|
+
if Kaya::Support::Configuration.use_git?
|
|
10
|
+
Kaya::Support::Git.reset_hard and Kaya::Support::Git.pull
|
|
11
|
+
$K_LOG.debug "Git pulled" if $K_LOG
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
result = Kaya::Results::Result.new(execution_request_data)
|
|
16
|
+
$K_LOG.debug "Result created with id => #{result.id}" if $K_LOG
|
|
17
|
+
|
|
18
|
+
result_id = result.id
|
|
19
|
+
|
|
20
|
+
if execution_request_data["type"] == "cucumber"
|
|
21
|
+
$K_LOG.debug "Execution type: Cucumber" if $K_LOG
|
|
22
|
+
Kaya::Cucumber::Task.run(result)
|
|
23
|
+
|
|
24
|
+
$K_LOG.debug "Task started" if $K_LOG
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if result = Results::Result.get(result_id)
|
|
28
|
+
|
|
29
|
+
result.append_result_to_console_output!
|
|
30
|
+
|
|
31
|
+
result.save_report!
|
|
32
|
+
|
|
33
|
+
result.get_summary!
|
|
34
|
+
|
|
35
|
+
result.get_status!
|
|
36
|
+
|
|
37
|
+
result = nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
result_id
|
|
41
|
+
|
|
42
|
+
else # ANOTHER TYPE OF EXECUTION
|
|
43
|
+
$K_LOG.debug "Execution type: #{execution_request_data[:type]}" if $K_LOG
|
|
44
|
+
puts "TODO: Another type of execution (no cucumber execution)"
|
|
45
|
+
|
|
46
|
+
Time.now.to_i # must return an id number
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|