tddium 1.25.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +15 -0
  2. data/bin/tddium +29 -0
  3. data/lib/tddium.rb +19 -0
  4. data/lib/tddium/agent.rb +3 -0
  5. data/lib/tddium/agent/tddium.rb +122 -0
  6. data/lib/tddium/cli.rb +26 -0
  7. data/lib/tddium/cli/api.rb +319 -0
  8. data/lib/tddium/cli/commands/account.rb +49 -0
  9. data/lib/tddium/cli/commands/activate.rb +14 -0
  10. data/lib/tddium/cli/commands/config.rb +55 -0
  11. data/lib/tddium/cli/commands/describe.rb +96 -0
  12. data/lib/tddium/cli/commands/find_failing.rb +62 -0
  13. data/lib/tddium/cli/commands/github.rb +53 -0
  14. data/lib/tddium/cli/commands/heroku.rb +15 -0
  15. data/lib/tddium/cli/commands/hg.rb +48 -0
  16. data/lib/tddium/cli/commands/keys.rb +83 -0
  17. data/lib/tddium/cli/commands/login.rb +37 -0
  18. data/lib/tddium/cli/commands/logout.rb +14 -0
  19. data/lib/tddium/cli/commands/password.rb +26 -0
  20. data/lib/tddium/cli/commands/rerun.rb +50 -0
  21. data/lib/tddium/cli/commands/server.rb +22 -0
  22. data/lib/tddium/cli/commands/spec.rb +306 -0
  23. data/lib/tddium/cli/commands/status.rb +107 -0
  24. data/lib/tddium/cli/commands/stop.rb +19 -0
  25. data/lib/tddium/cli/commands/suite.rb +110 -0
  26. data/lib/tddium/cli/commands/web.rb +22 -0
  27. data/lib/tddium/cli/config.rb +245 -0
  28. data/lib/tddium/cli/params_helper.rb +36 -0
  29. data/lib/tddium/cli/prompt.rb +128 -0
  30. data/lib/tddium/cli/show.rb +122 -0
  31. data/lib/tddium/cli/suite.rb +179 -0
  32. data/lib/tddium/cli/tddium.rb +153 -0
  33. data/lib/tddium/cli/text_helper.rb +16 -0
  34. data/lib/tddium/cli/timeformat.rb +21 -0
  35. data/lib/tddium/cli/util.rb +132 -0
  36. data/lib/tddium/constant.rb +509 -0
  37. data/lib/tddium/scm.rb +8 -0
  38. data/lib/tddium/scm/git.rb +188 -0
  39. data/lib/tddium/scm/git_log_parser.rb +67 -0
  40. data/lib/tddium/scm/hg.rb +160 -0
  41. data/lib/tddium/scm/hg_log_parser.rb +66 -0
  42. data/lib/tddium/scm/scm.rb +20 -0
  43. data/lib/tddium/script.rb +12 -0
  44. data/lib/tddium/script/git-remote-hg +1258 -0
  45. data/lib/tddium/ssh.rb +66 -0
  46. data/lib/tddium/util.rb +35 -0
  47. data/lib/tddium/version.rb +5 -0
  48. metadata +394 -0
@@ -0,0 +1,153 @@
1
+ # Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
2
+
3
+ module Tddium
4
+ class TddiumCli < Thor
5
+ include TddiumConstant
6
+ extend ParamsHelper
7
+
8
+ attr_reader :scm
9
+ attr_reader :user_details
10
+
11
+ params = self.load_params
12
+
13
+ class_option :host, :type => :string,
14
+ :default => params['host'] || ENV['TDDIUM_CLIENT_HOST'] || "ci.solanolabs.com",
15
+ :desc => "Solano CI app server hostname"
16
+
17
+ class_option :port, :type => :numeric,
18
+ :default => params['port'] || (ENV['TDDIUM_CLIENT_PORT'].nil? ? nil : ENV['TDDIUM_CLIENT_PORT'].to_i),
19
+ :desc => "Solano CI app server port"
20
+
21
+ class_option :proto, :type => :string,
22
+ :default => params['proto'] || ENV['TDDIUM_CLIENT_PROTO'] || "https",
23
+ :desc => "API Protocol"
24
+
25
+ class_option :insecure, :type => :boolean,
26
+ :default => params.key?('insecure') ? params['insecure'] : (ENV['TDDIUM_CLIENT_INSECURE'] != nil),
27
+ :desc => "Don't verify Solano CI app SSL server certificate"
28
+
29
+ def initialize(*args)
30
+ super(*args)
31
+
32
+ # XXX TODO: read host from .tddium file, allow selecting which .tddium "profile" to use
33
+ cli_opts = options[:insecure] ? { :insecure => true } : {}
34
+ @tddium_client = TddiumClient::InternalClient.new(options[:host],
35
+ options[:port],
36
+ options[:proto],
37
+ 1,
38
+ caller_version,
39
+ cli_opts)
40
+
41
+ @scm = Tddium::SCM.configure
42
+
43
+ @api_config = ApiConfig.new(@tddium_client, options[:host], options)
44
+ @repo_config = RepoConfig.new
45
+ @tddium_api = TddiumAPI.new(@api_config, @tddium_client, @scm)
46
+
47
+ # BOTCH: fugly
48
+ @api_config.set_api(@tddium_api)
49
+ end
50
+
51
+
52
+ require "tddium/cli/commands/account"
53
+ require "tddium/cli/commands/activate"
54
+ require "tddium/cli/commands/heroku"
55
+ require "tddium/cli/commands/login"
56
+ require "tddium/cli/commands/logout"
57
+ require "tddium/cli/commands/password"
58
+ require "tddium/cli/commands/rerun"
59
+ require "tddium/cli/commands/find_failing"
60
+ require "tddium/cli/commands/spec"
61
+ require "tddium/cli/commands/stop"
62
+ require "tddium/cli/commands/suite"
63
+ require "tddium/cli/commands/status"
64
+ require "tddium/cli/commands/keys"
65
+ require "tddium/cli/commands/config"
66
+ require 'tddium/cli/commands/describe'
67
+ require "tddium/cli/commands/web"
68
+ require 'tddium/cli/commands/github'
69
+ require 'tddium/cli/commands/hg'
70
+ require 'tddium/cli/commands/server'
71
+
72
+ map "-v" => :version
73
+ desc "version", "Print the tddium gem version"
74
+ def version
75
+ say VERSION
76
+ end
77
+
78
+ # Thor has the wrong default behavior
79
+ def self.exit_on_failure?
80
+ return true
81
+ end
82
+
83
+ # Thor prints a confusing message for the "help" command in case an option
84
+ # follows in the wrong order before the command.
85
+ # This code patch overwrites this behavior and prints a better error message.
86
+ # For Thor version >= 0.18.0, release 2013-03-26.
87
+ if defined? no_commands
88
+ no_commands do
89
+ def invoke_command(command, *args)
90
+ begin
91
+ super
92
+ rescue InvocationError
93
+ if command.name == "help"
94
+ exit_failure Text::Error::CANT_INVOKE_COMMAND
95
+ else
96
+ raise
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ protected
104
+
105
+ def caller_version
106
+ "tddium-#{VERSION}"
107
+ end
108
+
109
+ def configured_test_pattern
110
+ pattern = @repo_config["test_pattern"]
111
+
112
+ return nil if pattern.nil? || pattern.empty?
113
+ return pattern
114
+ end
115
+
116
+ def configured_test_exclude_pattern
117
+ pattern = @repo_config["test_exclude_pattern"]
118
+
119
+ return nil if pattern.nil? || pattern.empty?
120
+ return pattern
121
+ end
122
+
123
+ def tddium_setup(params={})
124
+ params[:scm] = !params.member?(:scm) || params[:scm] == true
125
+ params[:login] = true unless params.member?(:login)
126
+ params[:repo] = params[:repo] == true
127
+ params[:suite] = params[:suite] == true
128
+
129
+ $stdout.sync = true
130
+ $stderr.sync = true
131
+
132
+ set_shell
133
+
134
+ @api_config.load_config
135
+
136
+ user_details = @tddium_api.user_logged_in?(true, params[:login])
137
+ if params[:login] && user_details.nil? then
138
+ exit_failure
139
+ end
140
+
141
+ if params[:repo] && !@scm.repo? then
142
+ say Text::Error::SCM_NOT_A_REPOSITORY
143
+ exit_failure
144
+ end
145
+
146
+ if params[:suite] && !suite_for_current_branch? then
147
+ exit_failure
148
+ end
149
+
150
+ @user_details = user_details
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,16 @@
1
+ # Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
2
+
3
+ module Tddium
4
+ module TextHelper
5
+ # borrowed from rails/ActionView::Helpers
6
+ def pluralize(count, singular, plural = nil)
7
+ word = if (count == 1 || count =~ /^1(\.0+)?$/)
8
+ singular
9
+ else
10
+ plural || "#{singular}s"
11
+ end
12
+
13
+ "#{count || 0} #{word}"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
2
+
3
+ module Tddium
4
+ module TimeFormat
5
+ extend Tddium::TextHelper
6
+
7
+ def self.seconds_to_human_time(seconds)
8
+ return '-' if seconds.nil?
9
+ seconds = seconds.to_time if seconds.respond_to?(:to_time)
10
+ seconds = seconds.abs.round
11
+ return "0 secs" if seconds == 0
12
+ [[60, :sec], [60, :min], [24, :hr], [10000, :day]].map{ |count, name|
13
+ if seconds > 0
14
+ seconds, n = seconds.divmod(count)
15
+ pluralize(n.to_i, name.to_s)
16
+ end
17
+ }.compact.reverse[0..1].join(' ')
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,132 @@
1
+ # Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
2
+
3
+ module Tddium
4
+ class TddiumCli < Thor
5
+ protected
6
+
7
+ def set_shell
8
+ if !$stdout.tty? || !$stderr.tty? then
9
+ @shell = Thor::Shell::Basic.new
10
+ end
11
+ end
12
+
13
+ def tool_cli_populate(options, params)
14
+ if options[:tool].is_a?(Hash) then
15
+ options[:tool].each_pair do |key, value|
16
+ params[key.to_sym] = value
17
+ end
18
+ end
19
+ end
20
+
21
+ def tool_version(tool)
22
+ key = "#{tool}_version".to_sym
23
+ result = @repo_config[key]
24
+
25
+ if result
26
+ say Text::Process::CONFIGURED_VERSION % [tool, result, @repo_config.config_filename]
27
+ return result
28
+ end
29
+
30
+ begin
31
+ result = `#{tool} -v`.strip
32
+ rescue Errno::ENOENT
33
+ exit_failure("#{tool} is not on PATH; please install and try again")
34
+ end
35
+ say Text::Process::DEPENDENCY_VERSION % [tool, result]
36
+ result
37
+ end
38
+
39
+ def sniff_ruby_version_rvmrc(rvmrc)
40
+ ruby_version = nil
41
+ File.open(rvmrc, 'r') do |file|
42
+ file.each_line do |line|
43
+ line.sub!(/^\s+/, '')
44
+ next unless line =~ /^rvm/
45
+ fields = Shellwords.shellsplit(line)
46
+ fields.each do |field|
47
+ if field =~ /^(ree|1[.][89])/ then
48
+ ruby_version = field.sub(/@.*/, '')
49
+ end
50
+ end
51
+ end
52
+ end
53
+ return ruby_version
54
+ end
55
+
56
+ def sniff_ruby_version
57
+ ruby_version = @repo_config["ruby_version"]
58
+ return ruby_version unless ruby_version.nil? || ruby_version.empty?
59
+
60
+ if !options[:machine] then
61
+ scm_root = @scm.root
62
+ if scm_root then
63
+ rvmrc = File.join(scm_root, '.rvmrc')
64
+ ruby_version_path = File.join(scm_root, '.ruby_version')
65
+ if File.exists?(ruby_version_path) then
66
+ ruby_version = sniff_ruby_version_rvmrc(ruby_version)
67
+ elsif File.exists?(rvmrc) then
68
+ ruby_version = sniff_ruby_version_rvmrc(rvmrc)
69
+ warn("Detected ruby #{ruby_version} in .rvmrc; make sure patch level is correct")
70
+ end
71
+ end
72
+ end
73
+ return ruby_version
74
+ end
75
+
76
+ def normalize_bundler_version(bundler_version)
77
+ if !bundler_version.nil? then
78
+ bundler_version.chomp!
79
+ bundler_version =~ /Bundler version (.*)\z/
80
+ bundler_version = $1
81
+ end
82
+ return bundler_version
83
+ end
84
+
85
+ def ssh_key_fingerprint(pubkey)
86
+ tmp = Tempfile.new('ssh-pub')
87
+ tmp.write(pubkey)
88
+ tmp.close
89
+ fingerprint = nil
90
+ IO.popen("ssh-keygen -lf #{tmp.path}") do |io|
91
+ fingerprint = io.read
92
+ # Keep just bits and fingerprint
93
+ if fingerprint then
94
+ fingerprint.chomp!
95
+ fingerprint = fingerprint.split(/\s+/)[0..1].join(' ')
96
+ end
97
+ end
98
+ tmp.unlink
99
+
100
+ return fingerprint
101
+ end
102
+
103
+ def warn(msg='')
104
+ STDERR.puts("WARNING: #{msg}")
105
+ end
106
+
107
+ def exit_failure(msg='')
108
+ abort msg
109
+ end
110
+
111
+ def display_message(message, prefix=' ---> ')
112
+ color = case message["level"]
113
+ when "error" then :red
114
+ when "warn" then :yellow
115
+ else nil
116
+ end
117
+ print prefix
118
+ say message["text"].rstrip, color
119
+ end
120
+
121
+ def display_alerts(messages, level, heading)
122
+ return unless messages
123
+ interest = messages.select{|m| [level].include?(m['level'])}
124
+ if interest.size > 0
125
+ say heading
126
+ interest.each do |m|
127
+ display_message(m, '')
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,509 @@
1
+ # Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
2
+
3
+ module TddiumConstant
4
+
5
+ module Dependency
6
+ VERSION_REGEXP = /([\d\.]+)/
7
+ end
8
+
9
+ module Default
10
+ SLEEP_TIME_BETWEEN_POLLS = 2
11
+
12
+ ENVIRONMENT = "production"
13
+ SSH_FILE = "~/.ssh/id_rsa.pub"
14
+ SUITE_TEST_PATTERN = "features/**.feature, spec/**_spec.rb, spec/features/**.feature, test/**_test.rb"
15
+ SSH_OUTPUT_DIR = "~/.ssh/"
16
+
17
+ GIT_SERVER = "git.solanolabs.com"
18
+ READY_TRIES = 3
19
+ SCM_READY_TRIES = 18
20
+ SCM_READY_SLEEP = 10
21
+ TEST_FINISH_TIMEOUT = 15 * 60 # 15 minutes
22
+
23
+ PARAMS_PATH = "#{ENV['HOME']}/.tddium-server"
24
+ end
25
+
26
+ module Config
27
+ REMOTE_NAME = "tddium"
28
+ HG_IGNORE = ".hgignore"
29
+ GIT_IGNORE = ".gitignore"
30
+ CONFIG_PATHS = ["solano.yml",
31
+ "config/solano.yml"
32
+ ]
33
+ CONFIG_PATHS_DEPRECATED = ["tddium.yml",
34
+ "config/tddium.yml",
35
+ "config/tddium.cfg"
36
+ ]
37
+ EMBEDDED_SCRIPT_PATH = File.expand_path(File.join("..", "script"), __FILE__)
38
+ end
39
+
40
+ module Api
41
+ module Path
42
+ SUITES = "suites"
43
+ SESSIONS = "sessions"
44
+ REPORTS = "reports"
45
+ USERS = "users"
46
+ SIGN_IN = "#{USERS}/sign_in"
47
+ TEST_EXECUTIONS = "test_executions"
48
+ QUERY_TEST_EXECUTIONS = "#{TEST_EXECUTIONS}/query"
49
+ REGISTER_TEST_EXECUTIONS = "#{TEST_EXECUTIONS}/register"
50
+ START_TEST_EXECUTIONS = "#{TEST_EXECUTIONS}/start"
51
+ REPORT_TEST_EXECUTIONS = "#{TEST_EXECUTIONS}/report"
52
+ ACCOUNT_USAGE_BY_ACCOUNT = "accounts/usage_by_account"
53
+ MEMBERSHIPS = "memberships"
54
+ INSTANCES = "instances"
55
+ KEYS = "keys"
56
+ CONFIG = "env"
57
+ ACCOUNTS = "accounts"
58
+ REPOS = "repos"
59
+ end
60
+ end
61
+
62
+ module License
63
+ FILE_NAME = File.expand_path(File.join("..", "..", "..", "LICENSE.txt"), __FILE__)
64
+ end
65
+
66
+ module Text
67
+ module Prompt
68
+ module Response
69
+ YES = "y"
70
+ DISABLE = 'disable'
71
+ end
72
+ SSH_KEY = "Enter your ssh key or press 'Return'. Using '%s' by default:"
73
+ SUITE_NAME = "Enter a repo name or press 'Return'. Using '%s' by default:"
74
+ EMAIL = "Enter your email address: "
75
+ CURRENT_PASSWORD = "Enter your old password: "
76
+ PASSWORD = "Enter password: "
77
+ NEW_PASSWORD = "Enter a new password: "
78
+ PASSWORD_CONFIRMATION = "Confirm your password: "
79
+ INVITATION_TOKEN = "Enter your activation token:"
80
+ TEST_PATTERN = "Enter a pattern or press 'Return'. Using '%s' by default:"
81
+ CI_PULL_URL = "Enter git URL to pull from (default '%s') or enter 'disable':"
82
+ CI_PUSH_URL = "Enter git URL to push to (default '%s') or enter 'disable':"
83
+ CAMPFIRE_ROOM = "Custom Campfire room for this suite (current: '%s') or enter 'disable':"
84
+ HIPCHAT_ROOM = "Custom HipChat room for this suite (current: '%s') or enter 'disable':"
85
+ ACCOUNT = "Enter the organization to create the suite under:"
86
+ ACCOUNT_DEFAULT = "Enter the organization to create the suite under (default: '%s'):"
87
+ end
88
+
89
+ module Warning
90
+ USE_PASSWORD_TOKEN = "If you signed up with Github, use token from web dashboard as password"
91
+ HG_VERSION = "Unsupported hg version: %s"
92
+ HG_PATHS_DEFAULT_NOT_URI = "hg paths default not a URI"
93
+ HG_GIT_MIRROR_MISSING =<<EOF
94
+
95
+ * The hg <-> git mirror is missing.
96
+
97
+ Please run `tddium hg:mirror` to create the mirror for the first time.
98
+
99
+ (Note: it may take several minutes, or even an hour, for hg:mirror to complete,
100
+ depending on how large your repo is. Rest assured, you'll only need to run hg:mirror once.)
101
+
102
+ EOF
103
+ GIT_VERSION = "Unsupported git version: %s"
104
+ SCM_CHANGES_NOT_COMMITTED = "There are uncommitted changes in the local repository"
105
+ SCM_UNABLE_TO_DETECT = "Unable to detect uncommitted changes"
106
+ YAML_PARSE_FAILED = "Unable to parse %s as YAML"
107
+ TEST_CONFIGS_MUST_BE_LIST = "The test_configs section of solano.yml must be a list of configurations"
108
+ NO_SSH_KEY =<<EOF
109
+ You have not set an ssh key for your user. Please add an ssh key using `solano keys:add` or visit http://ci.solanolabs.com/user_settings/ssh_keys
110
+ EOF
111
+ end
112
+
113
+ module Process
114
+ SSH_KEY_NEEDED = "\nIt looks like you haven't authorized an SSH key to use with Solano CI.\n\n"
115
+ DEFAULT_KEY_ADDED = "SSH key authorized."
116
+ NO_KEYS = "No authorized keys."
117
+ ADD_KEYS_ADD = "Adding key '%s'"
118
+ ADD_KEYS_ADD_DONE =<<EOF
119
+ Authorized key '%s'.
120
+
121
+ Assuming your private key is in %s, you can just add the following
122
+ to ~/.ssh/config to use this new key with Solano CI:
123
+
124
+ # Solano CI SSH Config
125
+ Host %s
126
+ IdentityFile %s
127
+ IdentitiesOnly yes
128
+ EOF
129
+ ADD_KEYS_GENERATE = "Generating key '%s'"
130
+ ADD_KEYS_GENERATE_DONE =<<EOF
131
+ Generated and authorized key '%s'.
132
+
133
+ Append the following to ~/.ssh/config to use this new key with Solano CI:
134
+
135
+ # Solano CI SSH Config
136
+ Host %s
137
+ IdentityFile %s
138
+ IdentitiesOnly yes
139
+ EOF
140
+ REMOVE_KEYS = "Removing key '%s'"
141
+ REMOVE_KEYS_DONE = "Removed key '%s'"
142
+
143
+ NO_CONFIG = "No environment variables configured."
144
+ ADD_CONFIG = "Adding config %s=%s to %s"
145
+ ADD_CONFIG_DONE = "Added config %s=%s to %s"
146
+ REMOVE_CONFIG = "Removing config '%s' from %s"
147
+ REMOVE_CONFIG_DONE = "Removed config '%s' from %s"
148
+ CONFIG_EDIT_COMMANDS =<<EOF
149
+
150
+ Use `tddium config:add <scope> <key> <value>` to set a config key.
151
+ Use `tddium config:remove <scope> <key>` to remove a key.
152
+
153
+ EOF
154
+ KEYS_EDIT_COMMANDS =<<EOF
155
+
156
+ Use `tddium keys:add` to generate and authorize a new SSH keypair.
157
+ Use `tddium keys:remove` to remove an authorized key from Solano CI.
158
+
159
+ Use `ssh-keygen -lf <filename>` to print fingerprint of an existing public key.
160
+
161
+ EOF
162
+ TEST_PATTERN_INSTRUCTIONS =<<EOF
163
+
164
+ >>> Solano CI selects tests to run by default (e.g., in CI) by matching against a
165
+ list of Ruby glob patterns. Use "," to join multiple globs.
166
+
167
+ You can instead specify a list of test patterns in config/solano.yml.
168
+
169
+ Read more here: https://docs.solanolabs.com/
170
+
171
+ EOF
172
+ NO_CONFIGURED_SUITE = "Looks like you haven't configured Solano CI on this computer for %s/%s...\n"
173
+ FOUND_EXISTING_SUITE = "Found a suite in Solano CI for\n\n%s\n\n(on branch %s)."
174
+ TERMINATE_INSTRUCTION = ">>> Press Ctrl-C to stop waiting. Tests will continue running.\n"
175
+ INTERRUPT = "Interrupted"
176
+ SCM_PUSH = ">>> Pushing changes to Solano CI..."
177
+ SCM_REPO_WAIT = ">>> Waiting for your repository to be prepared. Sleeping for 10 seconds..."
178
+ STARTING_TEST = ">>> Starting Session with %s tests..."
179
+ CHECK_TEST_STATUS = ">>> Use 'tddium status' to check on pending jobs"
180
+ FINISHED_TEST = "Finished in %s seconds"
181
+ RUN_TDDIUM_WEB = "\n>>> Run `tddium web` to open the latest test results in your browser.\n"
182
+ CHECK_TEST_REPORT = ">>> To view results, visit: %s"
183
+ FAILED_TESTS = "Failed tests:"
184
+ SUMMARY_STATUS = "Final result: %s."
185
+ EXISTING_SUITE = "\nCurrent suite:\n"
186
+ USING_EXISTING_SUITE = "Using suite '%s/%s'."
187
+ CREATING_SUITE = "Creating suite '%s/%s'. This will take a few seconds."
188
+ CREATING_SUITE_CI_DISABLED = "Disabling automatic CI for this new branch."
189
+ CREATED_SUITE = "\nCreated suite.\n"
190
+ PASSWORD_CONFIRMATION_INCORRECT = "Password confirmation incorrect"
191
+ PASSWORD_CHANGED = "Your password has been changed."
192
+ NEXT_STEPS = "
193
+
194
+ Next, you should register your test suite and start tests by running:
195
+
196
+ $ tddium run
197
+
198
+ "
199
+ ALREADY_LOGGED_IN = "You're already logged in"
200
+ LOGGED_IN_SUCCESSFULLY = "Logged in successfully"
201
+ LOGGED_OUT_SUCCESSFULLY = "Logged out successfully"
202
+ USING_SPEC_OPTION = {:max_parallelism => "Max number of tests in parallel = %s",
203
+ :user_data_file => "Sending user data from %s",
204
+ :test_pattern => "Selecting tests that match '%s'",
205
+ :test_exclude_pattern => "Excluding tests that match '%s'"}
206
+ REMEMBERED = " (Remembered value)"
207
+ UPDATED_SUITE = "Updated suite successfully."
208
+ UPDATED_TEST_PATTERN = "Updated test pattern to '%s'"
209
+ UPDATED_TEST_EXCLUDE_PATTERN = "Updated test exclude pattern to '%s'"
210
+ UPDATED_RUBY_VERSION = "Updated ruby version to '%s'"
211
+ UPDATED_BUNDLER_VERSION = "Updated bundler version to '%s'"
212
+ UPDATED_PYTHON_CONFIG = "Updated Python configuration:\n%s"
213
+ UPDATED_TEST_CONFIGS = "Updated test configurations:\n%s"
214
+ DEPENDENCY_VERSION = "... Detected %s %s"
215
+ CONFIGURED_VERSION = "Configured %s %s from %s"
216
+ CONFIGURED_PATTERN =<<EOF;
217
+ ... Configured test pattern from %s:
218
+
219
+ %s
220
+
221
+ >>> To change the pattern:
222
+ 1. Edit %s
223
+ 2. Run `tddium suite --edit` again.
224
+ EOF
225
+ CONFIGURED_EXCLUDE_PATTERN =<<EOF;
226
+ ... Configured test exclude pattern from %s:
227
+
228
+ %s
229
+
230
+ >>> To change the pattern:
231
+ 1. Edit %s
232
+ 2. Run `tddium suite --edit` again.
233
+ EOF
234
+ DETECTED_BRANCH = "... Detected branch %s"
235
+ SETUP_CI=<<EOF;
236
+
237
+ >>> To set up Hosted CI, enter a git URL to pull from.
238
+ You can also set a git URL to push to after tests pass.
239
+
240
+ >>> Set both pull and push URLs to 'disable' to disable hosted CI completely.
241
+
242
+ EOF
243
+ SETUP_CAMPFIRE=<<EOF;
244
+
245
+
246
+ EOF
247
+
248
+ ADDING_MEMBER = "Adding %s as %s..."
249
+ ADDED_MEMBER = "Added %s"
250
+ REMOVING_MEMBER = "Removing %s. This may take a few seconds..."
251
+ REMOVED_MEMBER = "Removed %s"
252
+
253
+ USING_ACCOUNT_FROM_FLAG = "Using organization '%s' (from command line)."
254
+ USING_ACCOUNT = "Using organization '%s'."
255
+
256
+ CONFIRM_DELETE_SUITE = <<EOF.rstrip
257
+ Are you sure you want to delete the suite %s/%s
258
+ in organization %s?
259
+ This will delete all sessions associated with this suite, and cannot be un-done.
260
+ y/[n]:
261
+ EOF
262
+ SUITE_IN_MULTIPLE_ACCOUNTS = "The suite %s/%s exists in multiple organization:"
263
+ SUITE_IN_MULTIPLE_ACCOUNTS_PROMPT = "Which organization do you want to delete it from:"
264
+
265
+ ABORTING = "Aborting."
266
+ DESCRIBE_SESSION =<<EOF
267
+
268
+ Session %d%s
269
+ Showing %s tests
270
+
271
+ EOF
272
+ RERUN_SESSION =<<EOF
273
+
274
+ Re-run failures from a session with `tddium rerun <session_id>`.
275
+ Extract details of a session with `tddium describe <session_id>`.
276
+
277
+ EOF
278
+ OPTIONS_SAVED = 'Options have been successfully saved.'
279
+ NOT_SAVED_OPTIONS = 'There is no server information saved. Run `tddium server:set`.'
280
+ BUILD_CONTINUES = 'Session will continue running.'
281
+ end # Process
282
+
283
+ module Status
284
+ SPEC_WARNINGS = "\n\n>>> Solano CI Warnings:\n\n"
285
+ SPEC_ERRORS = "\n\n>>> Solano CI Errors:\n"
286
+ NO_SUITE = "You currently do not have any suites"
287
+ ALL_SUITES = "Suites:"
288
+ CURRENT_SUITE = "Current suite: %s"
289
+ CURRENT_SUITE_UNAVAILABLE = "Your current suite is unavailable"
290
+ NO_ACTIVE_SESSION = "There are no running sessions for this repo."
291
+ ACTIVE_SESSIONS = "Your active sessions for this repo%s:"
292
+ NO_INACTIVE_SESSION = "There are no recent sessions on this branch."
293
+ INACTIVE_SESSIONS = "Latest sessions on branch %s:"
294
+ SESSION_DETAIL = " %10.10s %s %s in %s, %s"
295
+ ATTRIBUTE_DETAIL = " %s: %s"
296
+ SEPARATOR = "====="
297
+ USING_SUITE = "\nUsing suite:\n"
298
+ USER_DETAILS =<<EOF;
299
+
300
+ Username: <%=user["email"]%>
301
+ User created: <%=user["created_at"]%>
302
+ EOF
303
+ ACCOUNT_DETAILS =<<EOF;
304
+
305
+ Organization: <%=acct["account"]%>
306
+
307
+ Role: <%=acct["account_role"]%>
308
+ Owner: <%=acct["account_owner"]%>
309
+ Plan: <%=acct["plan"]%>
310
+ <% if acct["trial_remaining"] && acct["trial_remaining"] > 0 %> Trial Period Remaining: <%=acct["trial_remaining"]%> days<% end %>
311
+ <% if acct["account_url"] %> Organization Management URL: <%=acct["account_url"]%><% end %>
312
+ <% if acct["heroku"] %> Heroku Account Linked: <%=acct["heroku_activation_done"]%><% end %>
313
+ <% if acct["third_party_pubkey"] %>
314
+ >>> Authorize the following SSH public key to allow Solano CI's test workers to
315
+ install gems from private git repos or communicate via SSH to your servers:
316
+
317
+ <%= acct["third_party_pubkey"] %>
318
+
319
+ <%end%>
320
+ EOF
321
+ USER_THIRD_PARTY_KEY_DETAILS =<<EOF;
322
+ <% if user["third_party_pubkey"] %>
323
+ >>> Authorize the following SSH public key to allow Solano CI's test workers to
324
+ install gems from private git repos or communicate via SSH to your servers:
325
+
326
+ <%= user["third_party_pubkey"] %>
327
+ <%end%>
328
+ EOF
329
+
330
+ SUITE_DETAILS =<<EOF;
331
+ Organization: <%=suite["account"]%>
332
+ Repo: <%=suite["repo_url"]%>
333
+ Scm: <%=suite["scm"]%>
334
+ Branch: <%=suite["branch"]%>
335
+ Default Test Pattern: <%=suite["test_pattern"]%>
336
+ Ruby Version: <%=suite["ruby_version"]%>
337
+ Rubygems Version: <%=suite["rubygems_version"]%>
338
+ Bundler Version: <%=suite["bundler_version"]%>
339
+ <% if suite["ci_enabled"] %>
340
+ Solano CI is enabled with the following parameters:
341
+
342
+ Pull URL: <%=suite["ci_pull_url"]%>
343
+
344
+ Notifications:
345
+
346
+ <%=suite["ci_notifications"]%>
347
+
348
+ <% if suite["ci_pull_url"] =~ /^git@github.com:(.*).git$/ %>
349
+ >>> Solano CI will pull from your Github repository.
350
+
351
+ Visit https://github.com/<%= $1 %>/admin/keys
352
+ then click "Add another deploy key" and copy and paste this key:
353
+
354
+ <%=suite["ci_ssh_pubkey"]%>
355
+ <% else %>
356
+ >>> Authorize the following SSH key to let Solano CI's pulls and pushes through:
357
+
358
+ <%=suite["ci_ssh_pubkey"]%>
359
+ <% end %><% if suite["ci_push_url"] =~ /^git@heroku.com:(.*).git$/ %>
360
+ >>> Solano CI will push to your Heroku application <%= $1 %>.
361
+ To authorize the key, use the following command:
362
+
363
+ heroku keys:add <%= tddium_deploy_key_file_name %> --app <%= $1 %>
364
+ <% end %><% if suite["ci_pull_url"] =~ /^git@github.com:(.*).git$/ %>
365
+ >>> Configure Github to notify Solano CI of your commits with a post-receive hook.
366
+
367
+ Visit https://github.com/<%= $1 %>/admin/hooks#generic_minibucket
368
+ then add the following URL and click "Update Settings":
369
+ <%=suite["hook_uri"]%>
370
+ <% else %>
371
+ >>> In order for Solano CI to know that your repo has changed, you'll need to
372
+ configure a post-commit hook in your Git server.
373
+
374
+ In Unix-based Git repositories, find the repository root and look for
375
+ a shell script in `.git/hooks/post-commit`.
376
+
377
+ To trigger CI builds, POST to the following URL from a post-commit hook:
378
+ <%=suite["hook_uri"]%>
379
+ <% end %>
380
+
381
+ >>> See http://docs.solanolabs.com/ for more information on Solano CI.
382
+ >>> You can enable Campfire and HipChat notifications from your Solano CI Dashboard.
383
+ <% end %>
384
+ >>> Run 'tddium suite --edit' to edit these settings.
385
+ >>> Run 'tddium spec' to run tests in this suite.
386
+ EOF
387
+ ACCOUNT_MEMBERS = "Authorized users:"
388
+ KEYS_DETAILS =<<EOF
389
+
390
+ You have authorized the following SSH public keys to communicate with Solano CI:
391
+
392
+ Name Fingerprint
393
+ ------------------ ------------------------------------------------------------
394
+ EOF
395
+ CONFIG_DETAILS =<<EOF
396
+ The following environment variables are set for this %s:
397
+
398
+ EOF
399
+ SESSION_STATUS =<<EOF
400
+
401
+ Session Details:
402
+
403
+ Commit: %s (%s)
404
+ Status: %s
405
+ Finished: %s
406
+
407
+ EOF
408
+ end
409
+
410
+ module Error
411
+ OPTIONS_NOT_SAVED = 'Options have not been saved.'
412
+ KEY_ALREADY_EXISTS = "Aborting. SSH key already exists: %s"
413
+ KEYGEN_FAILED = "Failed to generate new SSH key for '%s'"
414
+ LIST_KEYS_ERROR = "Error listing SSH keys"
415
+ REMOVE_KEYS_ERROR = "Failed to remove key '%s'"
416
+ ADD_KEYS_DUPLICATE = "You already have a key named '%s'"
417
+ ADD_KEY_CONTENT_DUPLICATE = "You already have a key named '%s' with the same content"
418
+ ADD_KEYS_ERROR = "Failed to add key '%s'"
419
+ LIST_CONFIG_ERROR = "Error listing configuration variables"
420
+ ADD_CONFIG_ERROR = "Error setting configuration variable"
421
+ REMOVE_CONFIG_ERROR = "Error removing configuration variable"
422
+ SCM_NOT_A_REPOSITORY = "Current working directory is not a suitable repository"
423
+ INVALID_CONFIGURED_PATTERN =<<EOF;
424
+ Configuring test pattern from %s...
425
+
426
+ >>> The test_pattern in %s is not properly formatted. It must be a YAML list.
427
+
428
+ You entered:
429
+
430
+ %s
431
+
432
+ >>> Edit %s and rerun `tddium suite --edit`
433
+
434
+ EOF
435
+ SCM_REPO_NOT_READY = "Your repository is being prepped. Try again in a minute."
436
+ SCM_PUSH_FAILED = <<EOF;
437
+
438
+ Attempt to push source to Solano CI failed.
439
+
440
+ If you get a "Permission denied (publickey)" message, ensure that SSH is
441
+ configured to send a key you have authorized with Solano CI (Run `tddium keys` to
442
+ see a list.)
443
+
444
+ For any other error, contact us at: support@solanolabs.com
445
+
446
+
447
+ EOF
448
+ INVALID_SSH_PUBLIC_KEY = '%s does not appear to be a valid SSH public key'
449
+ INACCESSIBLE_SSH_PUBLIC_KEY = '%s is not accessible: %s'
450
+ SCM_CHANGES_NOT_COMMITTED =<<EOF
451
+ There are uncommitted changes in the local repository.
452
+
453
+ Commit changes before running 'tddium spec'.
454
+
455
+ Use 'tddium spec --force' to test with only already-committed changes.
456
+ EOF
457
+ NOT_INITIALIZED = "Solano CI must be initialized. Try 'tddium login'"
458
+ INVALID_TDDIUM_FILE = ".tddium.%s config file is corrupt. Try 'tddium login'"
459
+ SCM_NOT_FOUND = "Solano CI requires git or mercurial which are not on your PATH"
460
+ SCM_NOT_INITIALIZED =<<EOF;
461
+ It doesn't look like you're in a git repo. If you're not, use 'git init' to
462
+ create one.
463
+
464
+ If you are in a git repo and you're still seeing this message,
465
+ you may be using an unsupported version of git.
466
+
467
+ Please email us at support@solanolabs.com with the following trace information:
468
+
469
+ >>>>>>>>>>>>> BEGIN GIT TRACE >>>>>>>>>>>>>>>>>>>>>>>>>
470
+ hg version: #{`hg status 2> /dev/null && hg -q --version 2>&1`}
471
+ git version: #{`git status 2> /dev/null && git --version 2>&1`}
472
+ git status: #{`git status 2> /dev/null && git status 2>&1`}
473
+ git status result: #{ $? }
474
+ git details: #{`git status 2> /dev/null && git status --porcelain 2>&1`}
475
+ git details result: #{ $? }
476
+ >>>>>>>>>>>>> END GIT TRACE >>>>>>>>>>>>>>>>>>>>>>>>>
477
+ EOF
478
+ NO_SESSION_EXISTS = "No session exists for the current branch. Use 'tddium run'"
479
+ NO_SUITE_EXISTS = "No suite exists for the branch '%s'. Try running 'tddium suite'"
480
+ TRY_DEFAULT_BRANCH = "Getting suites for default '%s' branch."
481
+ NO_USER_DATA_FILE = "User data file '%s' does not exist"
482
+ NO_MATCHING_FILES = "No files match '%s'"
483
+ PASSWORD_ERROR = "Error changing password: %s"
484
+ ADD_MEMBER_ERROR = "Error adding %s: %s"
485
+ REMOVE_MEMBER_ERROR = "Error removing %s: %s"
486
+ USE_ACTIVATE = "Visit 'https://ci.solanolabs.com' to activate your account for the first time."
487
+ INVALID_CREDENTIALS = "Your .tddium file has an invalid API key.\nRun `tddium logout` and `tddium login`, and then try again."
488
+ MISSING_ACCOUNT_OPTION = "You must specify an organization by passing the --org option."
489
+ MISSING_ACCOUNT = "You must specify an organization."
490
+ NOT_IN_ACCOUNT = "You aren't a member of organization %s."
491
+ CANT_FIND_SUITE = "Can't find suite for %s/%s"
492
+ INVALID_ACCOUNT_NAME = "Invalid organization name."
493
+ CANT_INVOKE_COMMAND =<<EOF
494
+ ERROR: could not invoke tddium command
495
+ Usage: "tddium COMMAND [ARGS] [OPTIONS]". For available commands, run "tddium help".
496
+ EOF
497
+ CONFIG_PATHS_COLLISION =<<EOF
498
+ You have both solano.yml and tddium.yml in your repo. We don't support merging the configuration from both of these files, so you'll have to pick one. The tddium.yml file will soon be deprecated, so we recommend migrating all of your configuration to solano.yml.
499
+ EOF
500
+ end
501
+ end
502
+
503
+ module DisplayedAttributes
504
+ SUITE = %w{repo_url branch test_pattern
505
+ ruby_version bundler_version rubygems_version
506
+ test_scripts test_executions git_repo_uri}
507
+ TEST_EXECUTION = %w{start_time end_time test_execution_stats report}
508
+ end
509
+ end