tddium-preview 0.9.3 → 0.9.4
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/.gitignore +1 -2
- data/Gemfile.lock +4 -4
- data/features/account_command.feature +11 -0
- data/features/heroku_command.feature +6 -0
- data/features/password_command.feature +46 -0
- data/features/spec_command.feature +15 -0
- data/features/status_command.feature +15 -0
- data/features/step_definitions/git_steps.rb +31 -0
- data/features/step_definitions/login_steps.rb +1 -2
- data/features/step_definitions/password_steps.rb +12 -0
- data/features/step_definitions/suite_steps.rb +4 -26
- data/features/step_definitions/upgrade_steps.rb +4 -0
- data/features/upgrade_required.feature +12 -0
- data/lib/tddium/commands/account.rb +51 -0
- data/lib/tddium/commands/activate.rb +58 -0
- data/lib/tddium/commands/heroku.rb +38 -0
- data/lib/tddium/commands/login.rb +20 -0
- data/lib/tddium/commands/logout.rb +15 -0
- data/lib/tddium/commands/password.rb +32 -0
- data/lib/tddium/commands/spec.rb +127 -0
- data/lib/tddium/commands/status.rb +56 -0
- data/lib/tddium/commands/suite.rb +62 -0
- data/lib/tddium/constant.rb +18 -15
- data/lib/tddium/version.rb +1 -1
- data/lib/tddium.rb +35 -428
- data/tddium.gemspec +1 -1
- metadata +41 -24
@@ -0,0 +1,62 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2011 Solano Labs All Rights Reserved
|
3
|
+
=end
|
4
|
+
|
5
|
+
class Tddium
|
6
|
+
|
7
|
+
desc "suite", "Register the current repo/branch, view/edit CI repos & deploy keys"
|
8
|
+
method_option :edit, :type => :boolean, :default => false
|
9
|
+
method_option :name, :type => :string, :default => nil
|
10
|
+
method_option :pull_url, :type => :string, :default => nil
|
11
|
+
method_option :push_url, :type => :string, :default => nil
|
12
|
+
method_option :test_pattern, :type => :string, :default => nil
|
13
|
+
def suite
|
14
|
+
set_default_environment
|
15
|
+
git_version_ok
|
16
|
+
return unless git_repo? && tddium_settings
|
17
|
+
|
18
|
+
params = {}
|
19
|
+
begin
|
20
|
+
if current_suite_id
|
21
|
+
current_suite = call_api(:get, current_suite_path)["suite"]
|
22
|
+
|
23
|
+
if options[:edit]
|
24
|
+
update_suite(current_suite, options)
|
25
|
+
else
|
26
|
+
say Text::Process::EXISTING_SUITE % format_suite_details(current_suite)
|
27
|
+
end
|
28
|
+
else
|
29
|
+
params[:branch] = current_git_branch
|
30
|
+
default_suite_name = File.basename(Dir.pwd)
|
31
|
+
params[:repo_name] = options[:name] || default_suite_name
|
32
|
+
|
33
|
+
say Text::Process::NO_CONFIGURED_SUITE % [params[:repo_name], params[:branch]]
|
34
|
+
|
35
|
+
use_existing_suite, existing_suite = resolve_suite_name(options, params, default_suite_name)
|
36
|
+
|
37
|
+
if use_existing_suite
|
38
|
+
# Write to file and exit when using the existing suite
|
39
|
+
write_suite(existing_suite)
|
40
|
+
say Text::Status::USING_SUITE % format_suite_details(existing_suite)
|
41
|
+
return
|
42
|
+
end
|
43
|
+
|
44
|
+
prompt_suite_params(options, params)
|
45
|
+
|
46
|
+
params.each do |k,v|
|
47
|
+
params.delete(k) if v == 'disable'
|
48
|
+
end
|
49
|
+
|
50
|
+
# Create new suite if it does not exist yet
|
51
|
+
say Text::Process::CREATING_SUITE % [params[:repo_name], params[:branch]]
|
52
|
+
new_suite = call_api(:post, Api::Path::SUITES, {:suite => params})
|
53
|
+
# Save the created suite
|
54
|
+
write_suite(new_suite["suite"])
|
55
|
+
|
56
|
+
say Text::Process::CREATED_SUITE % format_suite_details(new_suite["suite"])
|
57
|
+
end
|
58
|
+
rescue TddiumClient::Error::Base
|
59
|
+
exit_failure
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/tddium/constant.rb
CHANGED
@@ -40,12 +40,11 @@ module TddiumConstant
|
|
40
40
|
end
|
41
41
|
module ErrorCode
|
42
42
|
INVALID_INVITATION = 2
|
43
|
-
GEM_OUT_OF_DATE = 10000
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
47
46
|
module License
|
48
|
-
FILE_NAME = "LICENSE.txt"
|
47
|
+
FILE_NAME = File.expand_path(File.join("..", "..", "..", "LICENSE.txt"), __FILE__)
|
49
48
|
end
|
50
49
|
|
51
50
|
module Text
|
@@ -148,7 +147,7 @@ with Tddium.
|
|
148
147
|
DETECTED_BRANCH = "Detected branch %s"
|
149
148
|
SETUP_CI_FIRST_TIME =<<EOF;
|
150
149
|
|
151
|
-
Tddium includes a Hosted Continuous Integration
|
150
|
+
Tddium includes a Hosted Continuous Integration srvice that will run a
|
152
151
|
CI build when it's triggered by a POST:
|
153
152
|
|
154
153
|
1. Pull from your git server
|
@@ -208,7 +207,7 @@ EOF
|
|
208
207
|
ACTIVE_SESSIONS = "Your active sessions:"
|
209
208
|
NO_INACTIVE_SESSION = "There are no previous sessions"
|
210
209
|
INACTIVE_SESSIONS = "Your latest sessions:"
|
211
|
-
|
210
|
+
SESSION_DETAIL = " open %s # %8.8s Started: %s"
|
212
211
|
ATTRIBUTE_DETAIL = " %s: %s"
|
213
212
|
SEPARATOR = "====="
|
214
213
|
USING_SUITE = "Using suite...\n\n%s"
|
@@ -217,7 +216,7 @@ EOF
|
|
217
216
|
Username: <%=user["email"]%>
|
218
217
|
Account Created: <%=user["created_at"]%>
|
219
218
|
<% if user["trial_remaining"] && user["trial_remaining"] > 0 %>Trial Period Remaining: <%=user["trial_remaining"]%> days<% end %>
|
220
|
-
<% if user["
|
219
|
+
<% if user["account_url"] %>Account Management URL: <%=user["account_url"]%><% end %>
|
221
220
|
<% if user["heroku"] %>Heroku Account Linked: <%=user["heroku_activation_done"]%><% end %>
|
222
221
|
EOF
|
223
222
|
HEROKU_CONFIG = "
|
@@ -275,8 +274,8 @@ then add the following URL and click "Update Settings":
|
|
275
274
|
|
276
275
|
<%=suite["hook_uri"]%>
|
277
276
|
<% else %>
|
278
|
-
>>> In order for Tddium to know that your repo has changed, you'll need to
|
279
|
-
a post-commit hook in your Git server.
|
277
|
+
>>> In order for Tddium to know that your repo has changed, you'll need to
|
278
|
+
configure a post-commit hook in your Git server.
|
280
279
|
|
281
280
|
In Unix-based Git repositories, find the repository root and look for a shell
|
282
281
|
script in `.git/hooks/post-commit`.
|
@@ -288,13 +287,14 @@ To trigger CI builds, POST to the following URL from a post-commit hook:
|
|
288
287
|
>>> See http://www.tddium.com/support for more information on Tddium CI.
|
289
288
|
<% end %>
|
290
289
|
|
291
|
-
If your tests don't require a database or your app uses pure ActiveRecord
|
292
|
-
all set and can now run tddium spec.
|
290
|
+
If your tests don't require a database or your app uses pure ActiveRecord
|
291
|
+
you're all set and can now run tddium spec.
|
293
292
|
|
294
|
-
If your app needs database-specific features (triggers, stored procedures),
|
295
|
-
you'll need to configure a custom database setup hook.
|
296
|
-
|
297
|
-
|
293
|
+
>>> If your app needs database-specific features (triggers, stored procedures),
|
294
|
+
you'll need to configure a custom database setup hook.
|
295
|
+
|
296
|
+
See http://www.tddium.com/support/reference#setup_hooks to create a Rake
|
297
|
+
task for Tddium to set up your database.
|
298
298
|
|
299
299
|
Run 'tddium suite --edit' to edit suite settings.
|
300
300
|
|
@@ -309,7 +309,8 @@ EOF
|
|
309
309
|
|
310
310
|
The git push to Tddium failed.
|
311
311
|
|
312
|
-
SSH may not be configured to authenticate with the keypair you
|
312
|
+
SSH may not be configured to authenticate with the keypair you
|
313
|
+
provided when you set up your account.
|
313
314
|
|
314
315
|
See this URL for SSH configuration instructions:
|
315
316
|
|
@@ -347,7 +348,9 @@ git details result: #{ $? }
|
|
347
348
|
EOF
|
348
349
|
NO_SUITE_EXISTS = "No suite exists for the branch '%s'. Try running 'tddium suite'"
|
349
350
|
INVALID_INVITATION = "
|
350
|
-
Your invitation token wasn't recognized. If you have a token,
|
351
|
+
Your invitation token wasn't recognized. If you have a token,
|
352
|
+
make sure you enter it correctly.
|
353
|
+
|
351
354
|
If you want an invite, visit this URL to sign up:
|
352
355
|
|
353
356
|
http://www.tddium.com/
|
data/lib/tddium/version.rb
CHANGED
data/lib/tddium.rb
CHANGED
@@ -40,388 +40,15 @@ class Tddium < Thor
|
|
40
40
|
class_option :environment, :type => :string, :default => nil
|
41
41
|
class_option :port, :type => :numeric, :default => nil
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
desc "activate", "Activate an account with an invitation token"
|
56
|
-
method_option :email, :type => :string, :default => nil
|
57
|
-
method_option :password, :type => :string, :default => nil
|
58
|
-
method_option :ssh_key_file, :type => :string, :default => nil
|
59
|
-
def activate
|
60
|
-
set_shell
|
61
|
-
set_default_environment
|
62
|
-
if user_details = user_logged_in?
|
63
|
-
exit_failure Text::Error::ACTIVATE_LOGGED_IN
|
64
|
-
else
|
65
|
-
params = get_user_credentials(options.merge(:invited => true))
|
66
|
-
|
67
|
-
# Prompt for the password confirmation if password is not from command line
|
68
|
-
unless options[:password]
|
69
|
-
password_confirmation = HighLine.ask(Text::Prompt::PASSWORD_CONFIRMATION) { |q| q.echo = "*" }
|
70
|
-
unless password_confirmation == params[:password]
|
71
|
-
exit_failure Text::Process::PASSWORD_CONFIRMATION_INCORRECT
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
begin
|
76
|
-
params[:user_git_pubkey] = prompt_ssh_key(options[:ssh_key_file])
|
77
|
-
rescue TddiumError => e
|
78
|
-
exit_failure e.message
|
79
|
-
end
|
80
|
-
|
81
|
-
# Prompt for accepting license
|
82
|
-
content = File.open(File.join(File.dirname(__FILE__), "..", License::FILE_NAME)) do |file|
|
83
|
-
file.read
|
84
|
-
end
|
85
|
-
say content
|
86
|
-
license_accepted = ask(Text::Prompt::LICENSE_AGREEMENT)
|
87
|
-
exit_failure unless license_accepted.downcase == Text::Prompt::Response::AGREE_TO_LICENSE.downcase
|
88
|
-
|
89
|
-
begin
|
90
|
-
say Text::Process::STARTING_ACCOUNT_CREATION
|
91
|
-
new_user = call_api(:post, Api::Path::USERS, {:user => params}, false, false)
|
92
|
-
write_api_key(new_user["user"]["api_key"])
|
93
|
-
role = new_user["user"]["account_role"]
|
94
|
-
if role.nil? || role == "owner"
|
95
|
-
u = new_user["user"]
|
96
|
-
say Text::Process::ACCOUNT_CREATED % [u["email"], u["trial_remaining"], u["recurly_url"]]
|
97
|
-
else
|
98
|
-
say Text::Process::ACCOUNT_ADDED % [new_user["user"]["email"], new_user["user"]["account_role"], new_user["user"]["account"]]
|
99
|
-
end
|
100
|
-
rescue TddiumClient::Error::API => e
|
101
|
-
exit_failure ((e.status == Api::ErrorCode::INVALID_INVITATION) ? Text::Error::INVALID_INVITATION : e.message)
|
102
|
-
rescue TddiumClient::Error::Base => e
|
103
|
-
exit_failure say e.message
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
desc "account:add [ROLE] [EMAIL]", "Authorize and invite a user to use your account"
|
109
|
-
define_method "account:add" do |role, email|
|
110
|
-
set_shell
|
111
|
-
set_default_environment
|
112
|
-
user_details = user_logged_in?(true, true)
|
113
|
-
exit_failure unless user_details
|
114
|
-
|
115
|
-
params = {:role=>role, :email=>email}
|
116
|
-
begin
|
117
|
-
say Text::Process::ADDING_MEMBER % [params[:email], params[:role]]
|
118
|
-
result = call_api(:post, Api::Path::MEMBERSHIPS, params)
|
119
|
-
say Text::Process::ADDED_MEMBER % email
|
120
|
-
rescue TddiumClient::Error::API => e
|
121
|
-
exit_failure Text::Error::ADD_MEMBER_ERROR % [email, e.message]
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
desc "account:remove [EMAIL]", "Remove a user from your account"
|
126
|
-
define_method "account:remove" do |email|
|
127
|
-
set_shell
|
128
|
-
set_default_environment
|
129
|
-
user_details = user_logged_in?(true, true)
|
130
|
-
exit_failure unless user_details
|
131
|
-
|
132
|
-
begin
|
133
|
-
say Text::Process::REMOVING_MEMBER % email
|
134
|
-
result = call_api(:delete, "#{Api::Path::MEMBERSHIPS}/#{email}")
|
135
|
-
say Text::Process::REMOVED_MEMBER % email
|
136
|
-
rescue TddiumClient::Error::API => e
|
137
|
-
exit_failure Text::Error::REMOVE_MEMBER_ERROR % [email, e.message]
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
desc "heroku", "Connect Heroku account with Tddium"
|
142
|
-
method_option :email, :type => :string, :default => nil
|
143
|
-
method_option :password, :type => :string, :default => nil
|
144
|
-
method_option :ssh_key_file, :type => :string, :default => nil
|
145
|
-
method_option :app, :type => :string, :default => nil
|
146
|
-
def heroku
|
147
|
-
set_shell
|
148
|
-
set_default_environment
|
149
|
-
if user_details = user_logged_in?
|
150
|
-
# User is already logged in, so just display the info
|
151
|
-
show_user_details(user_details)
|
152
|
-
else
|
153
|
-
begin
|
154
|
-
heroku_config = HerokuConfig.read_config(options[:app])
|
155
|
-
# User has logged in to heroku, and TDDIUM environment variables are
|
156
|
-
# present
|
157
|
-
handle_heroku_user(options, heroku_config)
|
158
|
-
rescue HerokuConfig::HerokuNotFound
|
159
|
-
gemlist = `gem list heroku`
|
160
|
-
msg = Text::Error::Heroku::NOT_FOUND % gemlist
|
161
|
-
exit_failure msg
|
162
|
-
rescue HerokuConfig::TddiumNotAdded
|
163
|
-
exit_failure Text::Error::Heroku::NOT_ADDED
|
164
|
-
rescue HerokuConfig::InvalidFormat
|
165
|
-
exit_failure Text::Error::Heroku::INVALID_FORMAT
|
166
|
-
rescue HerokuConfig::NotLoggedIn
|
167
|
-
exit_failure Text::Error::Heroku::NOT_LOGGED_IN
|
168
|
-
rescue HerokuConfig::AppNotFound
|
169
|
-
exit_failure Text::Error::Heroku::APP_NOT_FOUND % options[:app]
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
desc "password", "Change password"
|
175
|
-
map "passwd" => :password
|
176
|
-
def password
|
177
|
-
set_shell
|
178
|
-
set_default_environment
|
179
|
-
return unless tddium_settings
|
180
|
-
user_details = user_logged_in?
|
181
|
-
return unless user_details
|
182
|
-
|
183
|
-
params = {}
|
184
|
-
params[:current_password] = HighLine.ask(Text::Prompt::CURRENT_PASSWORD) { |q| q.echo = "*" }
|
185
|
-
params[:password] = HighLine.ask(Text::Prompt::NEW_PASSWORD) { |q| q.echo = "*" }
|
186
|
-
params[:password_confirmation] = HighLine.ask(Text::Prompt::PASSWORD_CONFIRMATION) { |q| q.echo = "*" }
|
187
|
-
|
188
|
-
begin
|
189
|
-
user_id = user_details["user"]["id"]
|
190
|
-
result = call_api(:put, "#{Api::Path::USERS}/#{user_id}/", {:user=>params},
|
191
|
-
tddium_settings["api_key"], false)
|
192
|
-
say Text::Process::PASSWORD_CHANGED
|
193
|
-
rescue TddiumClient::Error::API => e
|
194
|
-
say Text::Error::PASSWORD_ERROR % e.explanation
|
195
|
-
rescue TddiumClient::Error::Base => e
|
196
|
-
say e.message
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
desc "login", "Log in to tddium using your email address and password"
|
201
|
-
method_option :email, :type => :string, :default => nil
|
202
|
-
method_option :password, :type => :string, :default => nil
|
203
|
-
def login
|
204
|
-
set_shell
|
205
|
-
set_default_environment
|
206
|
-
if user_logged_in?
|
207
|
-
say Text::Process::ALREADY_LOGGED_IN
|
208
|
-
elsif login_user(:params => get_user_credentials(options), :show_error => true)
|
209
|
-
say Text::Process::LOGGED_IN_SUCCESSFULLY
|
210
|
-
else
|
211
|
-
exit_failure
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
desc "logout", "Log out of tddium"
|
216
|
-
def logout
|
217
|
-
set_shell
|
218
|
-
set_default_environment
|
219
|
-
FileUtils.rm(tddium_file_name) if File.exists?(tddium_file_name)
|
220
|
-
say Text::Process::LOGGED_OUT_SUCCESSFULLY
|
221
|
-
end
|
222
|
-
|
223
|
-
map "cucumber" => :spec
|
224
|
-
map "test" => :spec
|
225
|
-
map "run" => :spec
|
226
|
-
desc "spec", "Run the test suite"
|
227
|
-
method_option :user_data_file, :type => :string, :default => nil
|
228
|
-
method_option :max_parallelism, :type => :numeric, :default => nil
|
229
|
-
method_option :test_pattern, :type => :string, :default => nil
|
230
|
-
method_option :force, :type => :boolean, :default => false
|
231
|
-
def spec
|
232
|
-
set_shell
|
233
|
-
set_default_environment
|
234
|
-
git_version_ok
|
235
|
-
if git_changes then
|
236
|
-
exit_failure(Text::Error::GIT_CHANGES_NOT_COMMITTED) if !options[:force]
|
237
|
-
warn(Text::Warning::GIT_CHANGES_NOT_COMMITTED)
|
238
|
-
end
|
239
|
-
exit_failure unless git_repo? && tddium_settings && suite_for_current_branch?
|
240
|
-
|
241
|
-
test_execution_params = {}
|
242
|
-
|
243
|
-
user_data_file_path = get_remembered_option(options, :user_data_file, nil) do |user_data_file_path|
|
244
|
-
if File.exists?(user_data_file_path)
|
245
|
-
user_data = File.open(user_data_file_path) { |file| file.read }
|
246
|
-
test_execution_params[:user_data_text] = Base64.encode64(user_data)
|
247
|
-
test_execution_params[:user_data_filename] = File.basename(user_data_file_path)
|
248
|
-
else
|
249
|
-
exit_failure Text::Error::NO_USER_DATA_FILE % user_data_file_path
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
max_parallelism = get_remembered_option(options, :max_parallelism, nil) do |max_parallelism|
|
254
|
-
test_execution_params[:max_parallelism] = max_parallelism
|
255
|
-
end
|
256
|
-
|
257
|
-
test_pattern = get_remembered_option(options, :test_pattern, nil)
|
258
|
-
|
259
|
-
start_time = Time.now
|
260
|
-
|
261
|
-
# Call the API to get the suite and its tests
|
262
|
-
begin
|
263
|
-
suite_details = call_api(:get, current_suite_path)
|
264
|
-
|
265
|
-
exit_failure Text::Error::GIT_REPO_NOT_READY unless suite_details["suite"]["repoman_current"]
|
266
|
-
|
267
|
-
# Push the latest code to git
|
268
|
-
exit_failure Text::Error::GIT_PUSH_FAILED unless update_git_remote_and_push(suite_details)
|
269
|
-
|
270
|
-
# Create a session
|
271
|
-
new_session = call_api(:post, Api::Path::SESSIONS)
|
272
|
-
session_id = new_session["session"]["id"]
|
273
|
-
|
274
|
-
# Register the tests
|
275
|
-
call_api(:post, "#{Api::Path::SESSIONS}/#{session_id}/#{Api::Path::REGISTER_TEST_EXECUTIONS}", {:suite_id => current_suite_id, :test_pattern => test_pattern})
|
276
|
-
|
277
|
-
# Start the tests
|
278
|
-
start_test_executions = call_api(:post, "#{Api::Path::SESSIONS}/#{session_id}/#{Api::Path::START_TEST_EXECUTIONS}", test_execution_params)
|
279
|
-
|
280
|
-
say Text::Process::STARTING_TEST % start_test_executions["started"]
|
281
|
-
|
282
|
-
tests_not_finished_yet = true
|
283
|
-
finished_tests = {}
|
284
|
-
test_statuses = Hash.new(0)
|
285
|
-
|
286
|
-
say Text::Process::CHECK_TEST_REPORT % start_test_executions["report"]
|
287
|
-
say Text::Process::TERMINATE_INSTRUCTION
|
288
|
-
while tests_not_finished_yet do
|
289
|
-
# Poll the API to check the status
|
290
|
-
current_test_executions = call_api(:get, "#{Api::Path::SESSIONS}/#{session_id}/#{Api::Path::TEST_EXECUTIONS}")
|
291
|
-
|
292
|
-
# Catch Ctrl-C to interrupt the test
|
293
|
-
Signal.trap(:INT) do
|
294
|
-
say Text::Process::INTERRUPT
|
295
|
-
say Text::Process::CHECK_TEST_STATUS
|
296
|
-
tests_not_finished_yet = false
|
297
|
-
end
|
298
|
-
|
299
|
-
# Print out the progress of running tests
|
300
|
-
current_test_executions["tests"].each do |test_name, result_params|
|
301
|
-
test_status = result_params["status"]
|
302
|
-
if result_params["finished"] && !finished_tests[test_name]
|
303
|
-
message = case test_status
|
304
|
-
when "passed" then [".", :green, false]
|
305
|
-
when "failed" then ["F", :red, false]
|
306
|
-
when "error" then ["E", nil, false]
|
307
|
-
when "pending" then ["*", :yellow, false]
|
308
|
-
when "skipped" then [".", :yellow, false]
|
309
|
-
else [".", nil, false]
|
310
|
-
end
|
311
|
-
finished_tests[test_name] = test_status
|
312
|
-
test_statuses[test_status] += 1
|
313
|
-
say *message
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
# If all tests finished, exit the loop else sleep
|
318
|
-
if finished_tests.size == current_test_executions["tests"].size
|
319
|
-
tests_not_finished_yet = false
|
320
|
-
else
|
321
|
-
sleep(Default::SLEEP_TIME_BETWEEN_POLLS)
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
# Print out the result
|
326
|
-
say ""
|
327
|
-
say Text::Process::FINISHED_TEST % (Time.now - start_time)
|
328
|
-
say "#{finished_tests.size} tests, #{test_statuses["failed"]} failures, #{test_statuses["error"]} errors, #{test_statuses["pending"]} pending"
|
329
|
-
|
330
|
-
# Save the spec options
|
331
|
-
write_suite(suite_details["suite"].merge({"id" => current_suite_id}),
|
332
|
-
{"user_data_file" => user_data_file_path,
|
333
|
-
"max_parallelism" => max_parallelism,
|
334
|
-
"test_pattern" => test_pattern})
|
335
|
-
|
336
|
-
exit_failure if test_statuses["failed"] > 0 || test_statuses["error"] > 0
|
337
|
-
rescue TddiumClient::Error::Base
|
338
|
-
exit_failure "Failed due to error communicating with Tddium"
|
339
|
-
rescue RuntimeError => e
|
340
|
-
exit_failure "Failed due to internal error: #{e.inspect} #{e.backtrace}"
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
desc "status", "Display information about this suite, and any open dev sessions"
|
345
|
-
def status
|
346
|
-
set_shell
|
347
|
-
set_default_environment
|
348
|
-
git_version_ok
|
349
|
-
return unless git_repo? && tddium_settings && suite_for_current_branch?
|
350
|
-
|
351
|
-
begin
|
352
|
-
current_suites = call_api(:get, Api::Path::SUITES)
|
353
|
-
if current_suites["suites"].size == 0
|
354
|
-
say Text::Status::NO_SUITE
|
355
|
-
else
|
356
|
-
if current_suite = current_suites["suites"].detect {|suite| suite["id"] == current_suite_id}
|
357
|
-
show_session_details({:active => false, :order => "date", :limit => 10}, Text::Status::NO_INACTIVE_SESSION, Text::Status::INACTIVE_SESSIONS)
|
358
|
-
show_session_details({:active => true}, Text::Status::NO_ACTIVE_SESSION, Text::Status::ACTIVE_SESSIONS)
|
359
|
-
say Text::Status::SEPARATOR
|
360
|
-
say Text::Status::CURRENT_SUITE % current_suite["repo_name"]
|
361
|
-
display_attributes(DisplayedAttributes::SUITE, current_suite)
|
362
|
-
else
|
363
|
-
say Text::Status::CURRENT_SUITE_UNAVAILABLE
|
364
|
-
end
|
365
|
-
end
|
366
|
-
rescue TddiumClient::Error::Base
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
desc "suite", "Register the current repo/branch, view/edit CI repos & deploy keys"
|
371
|
-
method_option :edit, :type => :boolean, :default => false
|
372
|
-
method_option :name, :type => :string, :default => nil
|
373
|
-
method_option :pull_url, :type => :string, :default => nil
|
374
|
-
method_option :push_url, :type => :string, :default => nil
|
375
|
-
method_option :test_pattern, :type => :string, :default => nil
|
376
|
-
def suite
|
377
|
-
set_default_environment
|
378
|
-
git_version_ok
|
379
|
-
return unless git_repo? && tddium_settings
|
380
|
-
|
381
|
-
params = {}
|
382
|
-
begin
|
383
|
-
if current_suite_id
|
384
|
-
current_suite = call_api(:get, current_suite_path)["suite"]
|
385
|
-
|
386
|
-
if options[:edit]
|
387
|
-
update_suite(current_suite, options)
|
388
|
-
else
|
389
|
-
say Text::Process::EXISTING_SUITE % format_suite_details(current_suite)
|
390
|
-
end
|
391
|
-
else
|
392
|
-
params[:branch] = current_git_branch
|
393
|
-
default_suite_name = File.basename(Dir.pwd)
|
394
|
-
params[:repo_name] = options[:name] || default_suite_name
|
395
|
-
|
396
|
-
say Text::Process::NO_CONFIGURED_SUITE % [params[:repo_name], params[:branch]]
|
397
|
-
|
398
|
-
use_existing_suite, existing_suite = resolve_suite_name(options, params, default_suite_name)
|
399
|
-
|
400
|
-
if use_existing_suite
|
401
|
-
# Write to file and exit when using the existing suite
|
402
|
-
write_suite(existing_suite)
|
403
|
-
say Text::Status::USING_SUITE % format_suite_details(existing_suite)
|
404
|
-
return
|
405
|
-
end
|
406
|
-
|
407
|
-
prompt_suite_params(options, params)
|
408
|
-
|
409
|
-
params.each do |k,v|
|
410
|
-
params.delete(k) if v == 'disable'
|
411
|
-
end
|
412
|
-
|
413
|
-
# Create new suite if it does not exist yet
|
414
|
-
say Text::Process::CREATING_SUITE % [params[:repo_name], params[:branch]]
|
415
|
-
new_suite = call_api(:post, Api::Path::SUITES, {:suite => params})
|
416
|
-
# Save the created suite
|
417
|
-
write_suite(new_suite["suite"])
|
418
|
-
|
419
|
-
say Text::Process::CREATED_SUITE % format_suite_details(new_suite["suite"])
|
420
|
-
end
|
421
|
-
rescue TddiumClient::Error::Base
|
422
|
-
exit_failure
|
423
|
-
end
|
424
|
-
end
|
43
|
+
require "tddium/commands/account"
|
44
|
+
require "tddium/commands/activate"
|
45
|
+
require "tddium/commands/heroku"
|
46
|
+
require "tddium/commands/login"
|
47
|
+
require "tddium/commands/logout"
|
48
|
+
require "tddium/commands/password"
|
49
|
+
require "tddium/commands/spec"
|
50
|
+
require "tddium/commands/suite"
|
51
|
+
require "tddium/commands/status"
|
425
52
|
|
426
53
|
map "-v" => :version
|
427
54
|
desc "version", "Print the tddium gem version"
|
@@ -433,13 +60,11 @@ class Tddium < Thor
|
|
433
60
|
|
434
61
|
def call_api(method, api_path, params = {}, api_key = nil, show_error = true)
|
435
62
|
api_key = tddium_settings(:fail_with_message => false)["api_key"] if tddium_settings(:fail_with_message => false) && api_key != false
|
436
|
-
params[:tddium_gem_version] = TddiumVersion::VERSION
|
437
63
|
begin
|
438
64
|
result = tddium_client.call_api(method, api_path, params, api_key)
|
65
|
+
rescue TddiumClient::Error::UpgradeRequired => e
|
66
|
+
exit_failure e.message
|
439
67
|
rescue TddiumClient::Error::Base => e
|
440
|
-
|
441
|
-
exit_failure e.message if e.status == Api::ErrorCode::GEM_OUT_OF_DATE
|
442
|
-
|
443
68
|
say e.message if show_error
|
444
69
|
raise e
|
445
70
|
end
|
@@ -766,24 +391,6 @@ class Tddium < Thor
|
|
766
391
|
end
|
767
392
|
end
|
768
393
|
|
769
|
-
def show_session_details(params, no_session_prompt, all_session_prompt)
|
770
|
-
begin
|
771
|
-
current_sessions = call_api(:get, Api::Path::SESSIONS, params)
|
772
|
-
say Text::Status::SEPARATOR
|
773
|
-
if current_sessions["sessions"].size == 0
|
774
|
-
say no_session_prompt
|
775
|
-
else
|
776
|
-
say all_session_prompt
|
777
|
-
current_sessions["sessions"].reverse_each do |session|
|
778
|
-
session_id = session.delete("id")
|
779
|
-
say Text::Status::SESSION_TITLE % session_id
|
780
|
-
display_attributes(DisplayedAttributes::TEST_EXECUTION, session)
|
781
|
-
end
|
782
|
-
end
|
783
|
-
rescue TddiumClient::Error::Base
|
784
|
-
end
|
785
|
-
end
|
786
|
-
|
787
394
|
def show_user_details(api_response)
|
788
395
|
# Given the user is logged in, she should be able to use "tddium account" to display information about her account:
|
789
396
|
# Email address
|
@@ -791,26 +398,24 @@ class Tddium < Thor
|
|
791
398
|
user = api_response["user"]
|
792
399
|
say ERB.new(Text::Status::USER_DETAILS).result(binding)
|
793
400
|
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
end
|
801
|
-
|
802
|
-
memberships = call_api(:get, Api::Path::MEMBERSHIPS)
|
803
|
-
if memberships["memberships"].length > 1
|
804
|
-
say Text::Status::ACCOUNT_MEMBERS
|
805
|
-
say memberships["memberships"].collect{|x|x['display']}.join("\n")
|
806
|
-
say "\n"
|
807
|
-
end
|
401
|
+
current_suites = call_api(:get, Api::Path::SUITES)
|
402
|
+
if current_suites["suites"].size == 0 then
|
403
|
+
say Text::Status::NO_SUITE
|
404
|
+
else
|
405
|
+
say Text::Status::ALL_SUITES % current_suites["suites"].collect {|suite| "#{suite["repo_name"]}/#{suite["branch"]}"}.join(", ")
|
406
|
+
end
|
808
407
|
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
408
|
+
memberships = call_api(:get, Api::Path::MEMBERSHIPS)
|
409
|
+
if memberships["memberships"].length > 1
|
410
|
+
say Text::Status::ACCOUNT_MEMBERS
|
411
|
+
say memberships["memberships"].collect{|x|x['display']}.join("\n")
|
412
|
+
say "\n"
|
813
413
|
end
|
414
|
+
|
415
|
+
account_usage = call_api(:get, Api::Path::ACCOUNT_USAGE)
|
416
|
+
say account_usage["usage"]
|
417
|
+
rescue TddiumClient::Error::Base => e
|
418
|
+
exit_failure e.message
|
814
419
|
end
|
815
420
|
|
816
421
|
def format_suite_details(suite)
|
@@ -834,7 +439,11 @@ puts "EXN: #{e.inspect}"
|
|
834
439
|
end
|
835
440
|
|
836
441
|
def tddium_client
|
837
|
-
@tddium_client ||=
|
442
|
+
@tddium_client ||= begin
|
443
|
+
c = TddiumClient::Client.new
|
444
|
+
c.caller_version = "tddium-preview-#{TddiumVersion::VERSION}"
|
445
|
+
c
|
446
|
+
end
|
838
447
|
end
|
839
448
|
|
840
449
|
def tddium_config
|
@@ -899,11 +508,9 @@ puts "EXN: #{e.inspect}"
|
|
899
508
|
|
900
509
|
def write_tddium_to_gitignore
|
901
510
|
content = File.exists?(Git::GITIGNORE) ? File.read(Git::GITIGNORE) : ''
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
file.write("#{fn}\n")
|
906
|
-
end
|
511
|
+
unless content.include?(".tddium*\n")
|
512
|
+
File.open(Git::GITIGNORE, "a") do |file|
|
513
|
+
file.write(".tddium*\n")
|
907
514
|
end
|
908
515
|
end
|
909
516
|
end
|
data/tddium.gemspec
CHANGED
@@ -35,7 +35,7 @@ EOF
|
|
35
35
|
s.add_runtime_dependency("thor")
|
36
36
|
s.add_runtime_dependency("highline")
|
37
37
|
s.add_runtime_dependency("json")
|
38
|
-
s.add_runtime_dependency("tddium_client", "
|
38
|
+
s.add_runtime_dependency("tddium_client", "~> 0.1.0")
|
39
39
|
s.add_runtime_dependency("tddium_reporting", ">=0.0.5")
|
40
40
|
s.add_runtime_dependency("bundler")
|
41
41
|
|