strata-cli 0.1.4.beta → 0.1.5.beta

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/lib/strata/cli/api/client.rb +4 -4
  4. data/lib/strata/cli/api/connection_error_handler.rb +1 -1
  5. data/lib/strata/cli/configuration.rb +3 -1
  6. data/lib/strata/cli/credentials.rb +2 -0
  7. data/lib/strata/cli/descriptions/create/migration.txt +10 -0
  8. data/lib/strata/cli/descriptions/create/relation.txt +6 -0
  9. data/lib/strata/cli/descriptions/create/table.txt +13 -0
  10. data/lib/strata/cli/descriptions/datasource/add.txt +6 -0
  11. data/lib/strata/cli/descriptions/datasource/meta.txt +5 -0
  12. data/lib/strata/cli/descriptions/datasource/tables.txt +6 -0
  13. data/lib/strata/cli/descriptions/datasource/test.txt +5 -0
  14. data/lib/strata/cli/descriptions/deploy/deploy.txt +13 -0
  15. data/lib/strata/cli/descriptions/deploy/status.txt +3 -0
  16. data/lib/strata/cli/descriptions/init.txt +6 -0
  17. data/lib/strata/cli/error_reporter.rb +70 -0
  18. data/lib/strata/cli/generators/datasource.rb +4 -1
  19. data/lib/strata/cli/generators/group.rb +14 -8
  20. data/lib/strata/cli/generators/migration.rb +1 -1
  21. data/lib/strata/cli/generators/project.rb +146 -130
  22. data/lib/strata/cli/generators/table.rb +1 -3
  23. data/lib/strata/cli/guard.rb +2 -0
  24. data/lib/strata/cli/helpers/command_context.rb +23 -4
  25. data/lib/strata/cli/helpers/datasource_helper.rb +17 -1
  26. data/lib/strata/cli/helpers/description_helper.rb +2 -0
  27. data/lib/strata/cli/helpers/prompts.rb +2 -0
  28. data/lib/strata/cli/main.rb +5 -1
  29. data/lib/strata/cli/sub_commands/audit.rb +19 -5
  30. data/lib/strata/cli/sub_commands/create.rb +41 -19
  31. data/lib/strata/cli/sub_commands/datasource.rb +9 -3
  32. data/lib/strata/cli/sub_commands/deploy.rb +40 -26
  33. data/lib/strata/cli/sub_commands/project.rb +4 -6
  34. data/lib/strata/cli/sub_commands/table.rb +1 -1
  35. data/lib/strata/cli/terminal.rb +2 -0
  36. data/lib/strata/cli/ui/autocomplete.rb +2 -0
  37. data/lib/strata/cli/ui/field_editor.rb +2 -0
  38. data/lib/strata/cli/utils/archive.rb +1 -3
  39. data/lib/strata/cli/utils/deployment_monitor.rb +26 -24
  40. data/lib/strata/cli/utils/git.rb +10 -7
  41. data/lib/strata/cli/utils/import_manager.rb +21 -23
  42. data/lib/strata/cli/utils/test_reporter.rb +16 -25
  43. data/lib/strata/cli/utils/version_checker.rb +4 -6
  44. data/lib/strata/cli/utils/yaml_import_resolver.rb +5 -2
  45. data/lib/strata/cli/utils.rb +2 -0
  46. data/lib/strata/cli/version.rb +1 -1
  47. data/lib/strata/cli.rb +8 -0
  48. metadata +29 -27
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "../guard"
2
4
  require_relative "../credentials"
3
5
  require_relative "../terminal"
@@ -19,7 +21,7 @@ module Strata
19
21
  desc "adapters", "Lists supported data warehouse adapters"
20
22
  def adapters
21
23
  say "\n\tSupported Adapters\n\n", :yellow
22
- DWH.adapters.keys.each do
24
+ DWH.adapters.each_key do
23
25
  say "\t\t● #{it}", :magenta
24
26
  end
25
27
  end
@@ -197,7 +199,7 @@ module Strata
197
199
  def meta(ds_key, table_name)
198
200
  say "\n● Schema for table: #{table_name} (#{ds_key}):\n", :yellow
199
201
  adapter = create_adapter(ds_key)
200
- md = adapter.metadata(table_name, **options.transform_keys { it.to_sym })
202
+ md = adapter.metadata(table_name, **options.transform_keys(&:to_sym))
201
203
 
202
204
  headings = md.columns.first.to_h.keys
203
205
  rows = md.columns.map(&:to_h).map(&:values)
@@ -255,6 +257,7 @@ module Strata
255
257
  unless expanded.start_with?(project_root)
256
258
  raise Strata::CommandError, "File path must be within project directory"
257
259
  end
260
+
258
261
  expanded
259
262
  end
260
263
 
@@ -370,7 +373,10 @@ module Strata
370
373
  strata_file = Configuration::STRATA_CONFIG_FILE
371
374
  File.chmod(0o600, strata_file) if File.exist?(strata_file)
372
375
 
373
- Utils::Git.commit_file(Configuration::STRATA_CONFIG_FILE, "[Strata-CLI] Add AI config to .strata", Dir.pwd) if Utils::Git.git_repo?
376
+ if Utils::Git.git_repo?
377
+ Utils::Git.commit_file(Configuration::STRATA_CONFIG_FILE, "[Strata-CLI] Add AI config to .strata",
378
+ Dir.pwd)
379
+ end
374
380
 
375
381
  say "\n✔ AI configured with #{provider}", :green
376
382
  say " Note: API key is stored securely in .strata (not committed to repo)", :cyan
@@ -58,7 +58,9 @@ module Strata
58
58
  import_commit_hash = Utils::ImportManager.generate_import_commit_hash(project_path)
59
59
  say "\nExternal imports change found. Proceeding with deployment", ColorHelper.info
60
60
  metadata[:commit] = "imports-#{import_commit_hash}"
61
- metadata[:commit_message] = "External imports updated: #{refreshed_imports.map { |c| File.basename(c[:source]) }.join(", ")}"
61
+ metadata[:commit_message] = "External imports updated: #{refreshed_imports.map do |c|
62
+ File.basename(c[:source])
63
+ end.join(", ")}"
62
64
  end
63
65
 
64
66
  archive_path = create_and_upload_archive(last_deployment_commit, refreshed_imports: refreshed_imports)
@@ -90,13 +92,14 @@ module Strata
90
92
 
91
93
  deployment_id = deployment["id"]
92
94
  has_tests = test_files_exist?
93
- monitor = Utils::DeploymentMonitor.new(client, config["project_id"], branch_id, deployment_id, has_tests: has_tests)
95
+ monitor = Utils::DeploymentMonitor.new(client, config["project_id"], branch_id, deployment_id,
96
+ has_tests: has_tests)
94
97
 
95
98
  # Show current status
96
99
  result = monitor.display_status
97
100
 
98
101
  # Continue monitoring if deployment is in progress, or if tests are expected but not yet available
99
- should_continue_monitoring = if result && !["succeeded", "failed"].include?(result["status"])
102
+ should_continue_monitoring = if result && !%w[succeeded failed].include?(result["status"])
100
103
  true
101
104
  elsif result && result["status"] == "succeeded" && result["stage"] == "finished"
102
105
  # Check if tests are expected but not yet available
@@ -128,7 +131,9 @@ module Strata
128
131
  end
129
132
 
130
133
  def ensure_api_key(config)
131
- return if config["api_key"] && !config["api_key"].to_s.strip.empty? && config["api_key"] != "YOUR_STRATA_API_KEY"
134
+ if config["api_key"] && !config["api_key"].to_s.strip.empty? && config["api_key"] != "YOUR_STRATA_API_KEY"
135
+ return
136
+ end
132
137
 
133
138
  config["api_key"] = collect_api_key_interactively
134
139
  end
@@ -162,7 +167,10 @@ module Strata
162
167
  def save_server_to_project_yml(server)
163
168
  Helpers::ProjectHelper.persist_server_to_project_yml(server, project_yml_path: File.join(project_path, Configuration::PROJECT_CONFIG_FILE))
164
169
  CLI.config.reload!
165
- Utils::Git.commit_file(Configuration::PROJECT_CONFIG_FILE, "[Strata-CLI] Add server URL to project.yml", project_path) if Utils::Git.git_repo?
170
+ return unless Utils::Git.git_repo?
171
+
172
+ Utils::Git.commit_file(Configuration::PROJECT_CONFIG_FILE, "[Strata-CLI] Add server URL to project.yml",
173
+ project_path)
166
174
  end
167
175
 
168
176
  def ensure_git_url_populated
@@ -170,13 +178,13 @@ module Strata
170
178
 
171
179
  CLI.config.reload!
172
180
 
173
- if Utils::Git.git_repo?
174
- Utils::Git.commit_file(
175
- Configuration::PROJECT_CONFIG_FILE,
176
- "[Strata-CLI] Auto-populate git URL from remote",
177
- project_path
178
- )
179
- end
181
+ return unless Utils::Git.git_repo?
182
+
183
+ Utils::Git.commit_file(
184
+ Configuration::PROJECT_CONFIG_FILE,
185
+ "[Strata-CLI] Auto-populate git URL from remote",
186
+ project_path
187
+ )
180
188
  end
181
189
 
182
190
  def ensure_project_id(config)
@@ -204,7 +212,10 @@ module Strata
204
212
  save_api_key_to_strata(api_key)
205
213
  end
206
214
 
207
- Utils::Git.commit_file(Configuration::STRATA_CONFIG_FILE, "[Strata-CLI] Save API key to .strata", project_path) if Utils::Git.git_repo?
215
+ if Utils::Git.git_repo?
216
+ Utils::Git.commit_file(Configuration::STRATA_CONFIG_FILE, "[Strata-CLI] Save API key to .strata",
217
+ project_path)
218
+ end
208
219
 
209
220
  api_key
210
221
  end
@@ -244,7 +255,7 @@ module Strata
244
255
  end
245
256
  end
246
257
 
247
- def handle_missing_deployment_config(config, key)
258
+ def handle_missing_deployment_config(_config, key)
248
259
  raise Strata::CommandError, "Missing required configuration: #{key}. Check your project.yml file."
249
260
  end
250
261
 
@@ -276,9 +287,11 @@ module Strata
276
287
  commit_status = Utils::Git.check_commit_status(branch_name)
277
288
  case commit_status[:status]
278
289
  when :behind
279
- raise Strata::CommandError, "Your local branch is behind remote. Please pull latest changes before deploying."
290
+ raise Strata::CommandError,
291
+ "Your local branch is behind remote. Please pull latest changes before deploying."
280
292
  when :diverged
281
- raise Strata::CommandError, "Your local branch has diverged from remote. Please sync your branch before deploying."
293
+ raise Strata::CommandError,
294
+ "Your local branch has diverged from remote. Please sync your branch before deploying."
282
295
  when :ahead, :same
283
296
  # Status is already shown via spinner, no need for additional message
284
297
  end
@@ -327,9 +340,7 @@ module Strata
327
340
  end.select { |path| File.exist?(path) }
328
341
 
329
342
  change_count = files_to_include.length
330
- if refreshed_imports.any?
331
- change_count += refreshed_imports.length
332
- end
343
+ change_count += refreshed_imports.length if refreshed_imports.any?
333
344
 
334
345
  say "Including #{change_count} changed file(s) in archive...\n", ColorHelper.info
335
346
  Utils::Archive.create(project_path, files_to_include: files_to_include)
@@ -355,7 +366,8 @@ module Strata
355
366
  client = API::Client.new(config["server"], config["api_key"])
356
367
 
357
368
  has_tests = test_files_exist?
358
- Utils::DeploymentMonitor.new(client, config["project_id"], branch_id, deployment_id, has_tests: has_tests).start
369
+ Utils::DeploymentMonitor.new(client, config["project_id"], branch_id, deployment_id,
370
+ has_tests: has_tests).start
359
371
  end
360
372
 
361
373
  def test_files_exist?
@@ -381,7 +393,7 @@ module Strata
381
393
  exit(0)
382
394
  end
383
395
 
384
- def get_production_branch(config)
396
+ def get_production_branch(_config)
385
397
  return nil unless File.exist?("project.yml")
386
398
 
387
399
  project_config = YAML.safe_load_file("project.yml", permitted_classes: [Date, Time], aliases: true) || {}
@@ -418,13 +430,12 @@ module Strata
418
430
  git = project_config["git"]
419
431
  production_branch = project_config["production_branch"]
420
432
 
421
- unless name
422
- raise Strata::CommandError, "Cannot create project: name is required in project.yml"
423
- end
433
+ raise Strata::CommandError, "Cannot create project: name is required in project.yml" unless name
424
434
 
425
435
  with_spinner("Creating project '#{name}' on server") do
426
436
  client = API::Client.new(config["server"], config["api_key"])
427
- project = client.create_project(name, uid, description: description, git: git, production_branch: production_branch)
437
+ project = client.create_project(name, uid, description: description, git: git,
438
+ production_branch: production_branch)
428
439
  project["id"]
429
440
  end
430
441
  end
@@ -433,7 +444,10 @@ module Strata
433
444
  with_spinner("Persisting project ID to project.yml") do
434
445
  Helpers::ProjectHelper.persist_project_id_to_yml(project_id)
435
446
  end
436
- Utils::Git.commit_file(Configuration::PROJECT_CONFIG_FILE, "[Strata-CLI] Persist project ID to project.yml", project_path) if Utils::Git.git_repo?
447
+ return unless Utils::Git.git_repo?
448
+
449
+ Utils::Git.commit_file(Configuration::PROJECT_CONFIG_FILE, "[Strata-CLI] Persist project ID to project.yml",
450
+ project_path)
437
451
  end
438
452
 
439
453
  def refresh_external_imports
@@ -16,9 +16,7 @@ module Strata
16
16
 
17
17
  desc "link PROJECT_ID", "Link local project to an existing project on the server"
18
18
  def link(project_id)
19
- unless project_id && !project_id.to_s.strip.empty?
20
- raise Strata::CommandError, "Project ID is required."
21
- end
19
+ raise Strata::CommandError, "Project ID is required." unless project_id && !project_id.to_s.strip.empty?
22
20
 
23
21
  project_yml_path = "project.yml"
24
22
  project_config = YAML.safe_load_file(project_yml_path, permitted_classes: [Date, Time], aliases: true) || {}
@@ -28,9 +26,9 @@ module Strata
28
26
  return
29
27
  end
30
28
 
31
- if Helpers::ProjectHelper.persist_project_id_to_yml(project_id, project_yml_path: project_yml_path)
32
- say "✓ Project linked successfully. project_id: #{project_id}", ColorHelper.info
33
- end
29
+ return unless Helpers::ProjectHelper.persist_project_id_to_yml(project_id, project_yml_path: project_yml_path)
30
+
31
+ say "✓ Project linked successfully. project_id: #{project_id}", ColorHelper.info
34
32
  end
35
33
  end
36
34
  end
@@ -44,7 +44,7 @@ module Strata
44
44
  name = File.basename(file, ".yml")
45
45
  content = File.read(file)
46
46
  desc = content.match(/^# Description: (.+)$/)&.[](1) || ""
47
- desc = desc[0..50] + "..." if desc.length > 50
47
+ desc = "#{desc[0..50]}..." if desc.length > 50
48
48
 
49
49
  if desc.empty?
50
50
  say " #{name}", :white
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "tty-spinner"
2
4
  require "pastel"
3
5
  require "tty-table"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "tty-prompt"
2
4
  require_relative "../helpers/table_filter"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "tty-prompt"
2
4
  require "tty-table"
3
5
  require "pastel"
@@ -46,9 +46,7 @@ module Strata
46
46
  ]
47
47
 
48
48
  required_files.each do |required_file|
49
- if File.exist?(required_file) && !files.include?(required_file)
50
- files << required_file
51
- end
49
+ files << required_file if File.exist?(required_file) && !files.include?(required_file)
52
50
  end
53
51
 
54
52
  # Always include all test files
@@ -15,26 +15,26 @@ module Strata
15
15
  include Terminal
16
16
 
17
17
  # Terminal statuses that indicate deployment is complete
18
- TERMINAL_STATUSES = ["succeeded", "failed"].freeze
18
+ TERMINAL_STATUSES = %w[succeeded failed].freeze
19
19
  NOT_STARTED_STAGE = "not_started"
20
20
  DEFAULT_POLL_INTERVAL = 0.5 # seconds
21
21
  DEFAULT_TIMEOUT = 600 # seconds (10 minutes)
22
22
  TEST_WAIT_TIMEOUT = 5 # seconds
23
- STAGES = [
24
- :not_started,
25
- :preparing,
26
- :pre_migrations,
27
- :project_configuration,
28
- :processing_datasources,
29
- :processing_models,
30
- :removing_deleted_models,
31
- :processing_relationships,
32
- :forming_universes,
33
- :creating_blend_paths,
34
- :validating_references,
35
- :post_migrations,
36
- :cleaning_up,
37
- :finished
23
+ STAGES = %i[
24
+ not_started
25
+ preparing
26
+ pre_migrations
27
+ project_configuration
28
+ processing_datasources
29
+ processing_models
30
+ removing_deleted_models
31
+ processing_relationships
32
+ forming_universes
33
+ creating_blend_paths
34
+ validating_references
35
+ post_migrations
36
+ cleaning_up
37
+ finished
38
38
  ].freeze
39
39
  TESTING_STAGE = :running_tests
40
40
 
@@ -145,9 +145,7 @@ module Strata
145
145
 
146
146
  process_deployment_state(deployment)
147
147
 
148
- if terminal_status?(deployment_value(deployment, "status"))
149
- display_final_status(deployment)
150
- end
148
+ display_final_status(deployment) if terminal_status?(deployment_value(deployment, "status"))
151
149
 
152
150
  deployment
153
151
  rescue Interrupt
@@ -324,6 +322,7 @@ module Strata
324
322
  final_stage_string = final_stage&.to_s
325
323
  @spinners.each_key do |stage_string|
326
324
  next if stage_string == TESTING_STAGE # Handle test spinner separately
325
+
327
326
  complete_stage(stage_string) if stage_string != final_stage_string
328
327
  end
329
328
  end
@@ -385,9 +384,7 @@ module Strata
385
384
  end
386
385
 
387
386
  def stop_all_spinners
388
- @spinners.each do |_stage_string, spinner|
389
- spinner.stop
390
- end
387
+ @spinners.each_value(&:stop)
391
388
  @spinners.clear
392
389
  @tests_running = false
393
390
  end
@@ -396,11 +393,16 @@ module Strata
396
393
  raise ArgumentError, "client cannot be nil" if client.nil?
397
394
  raise ArgumentError, "project_id cannot be nil or empty" if project_id.nil? || project_id.to_s.strip.empty?
398
395
  raise ArgumentError, "branch_id cannot be nil or empty" if branch_id.nil? || branch_id.to_s.strip.empty?
399
- raise ArgumentError, "deployment_id cannot be nil or empty" if deployment_id.nil? || deployment_id.to_s.strip.empty?
396
+
397
+ return unless deployment_id.nil? || deployment_id.to_s.strip.empty?
398
+
399
+ raise ArgumentError,
400
+ "deployment_id cannot be nil or empty"
400
401
  end
401
402
 
402
403
  def deployment_value(deployment, key)
403
404
  return nil unless deployment.is_a?(Hash)
405
+
404
406
  deployment[key] || deployment[key.to_sym]
405
407
  end
406
408
 
@@ -430,7 +432,7 @@ module Strata
430
432
 
431
433
  test_results = deployment_value(latest_test_run, "test_results")
432
434
  if test_results
433
- say "\n" + "=" * 60, :border
435
+ say "\n#{"=" * 60}", :border
434
436
  complete_stage(TESTING_STAGE)
435
437
  display_test_results(test_results, skip_opening_divider: true)
436
438
  else
@@ -11,6 +11,7 @@ module Strata
11
11
  def validate_commit_hash(commit_hash)
12
12
  return false unless commit_hash.is_a?(String)
13
13
  return false unless commit_hash.match?(/\A[a-f0-9]{7,40}\z/i)
14
+
14
15
  true
15
16
  end
16
17
 
@@ -127,7 +128,8 @@ module Strata
127
128
 
128
129
  return if git_available?
129
130
 
130
- Thor::Shell::Color.new.say_error "ERROR: Git is required but not found. Please install Git to use strata-cli.", :red
131
+ Thor::Shell::Color.new.say_error "ERROR: Git is required but not found. Please install Git to use strata-cli.",
132
+ :red
131
133
  exit 1
132
134
  end
133
135
 
@@ -143,7 +145,7 @@ module Strata
143
145
  end
144
146
 
145
147
  def run_git_command(*args)
146
- stdout, _, _ = Open3.capture3("git", *args)
148
+ stdout, = Open3.capture3("git", *args)
147
149
  stdout&.strip
148
150
  end
149
151
 
@@ -190,7 +192,7 @@ module Strata
190
192
  def uncommitted_changes?
191
193
  return false unless git_repo?
192
194
 
193
- stdout, _, _ = Open3.capture3("git", "status", "--porcelain")
195
+ stdout, = Open3.capture3("git", "status", "--porcelain")
194
196
  !stdout.strip.empty?
195
197
  end
196
198
 
@@ -219,17 +221,18 @@ module Strata
219
221
 
220
222
  # Check if local is ahead, behind, or diverged
221
223
  # rev-list --left-right shows: > = commits in local not in remote (ahead), < = commits in remote not in local (behind)
222
- diff_output, _, _ = Open3.capture3("git", "rev-list", "--left-right", "#{remote_sha}...#{local_sha}")
224
+ diff_output, = Open3.capture3("git", "rev-list", "--left-right", "#{remote_sha}...#{local_sha}")
223
225
 
224
226
  ahead_count = diff_output.lines.count { |line| line.start_with?(">") }
225
227
  behind_count = diff_output.lines.count { |line| line.start_with?("<") }
226
228
 
227
- if ahead_count > 0 && behind_count == 0
229
+ if ahead_count.positive? && behind_count.zero?
228
230
  {status: :ahead, message: "Local branch is #{ahead_count} commit(s) ahead of remote"}
229
- elsif ahead_count == 0 && behind_count > 0
231
+ elsif ahead_count.zero? && behind_count.positive?
230
232
  {status: :behind, message: "Local branch is #{behind_count} commit(s) behind remote"}
231
233
  else
232
- {status: :diverged, message: "Local branch has diverged from remote (#{ahead_count} ahead, #{behind_count} behind)"}
234
+ {status: :diverged,
235
+ message: "Local branch has diverged from remote (#{ahead_count} ahead, #{behind_count} behind)"}
233
236
  end
234
237
  end
235
238
 
@@ -16,9 +16,9 @@ module Strata
16
16
  LOCK_FILE = "strata.lock"
17
17
 
18
18
  def validate_import_path(import_path)
19
- if Pathname.new(import_path).absolute?
20
- raise Strata::InvalidImportPathError, "Import paths must be relative, not absolute: #{import_path}"
21
- end
19
+ return unless Pathname.new(import_path).absolute?
20
+
21
+ raise Strata::InvalidImportPathError, "Import paths must be relative, not absolute: #{import_path}"
22
22
  end
23
23
 
24
24
  def track_external_import(import_path, resolved_path, project_path)
@@ -58,9 +58,7 @@ module Strata
58
58
 
59
59
  resolved_path = File.expand_path(import_path, base_dir)
60
60
 
61
- unless File.exist?(resolved_path)
62
- raise Strata::MissingImportError, "Import file not found: #{import_path}"
63
- end
61
+ raise Strata::MissingImportError, "Import file not found: #{import_path}" unless File.exist?(resolved_path)
64
62
 
65
63
  # Track external imports in lock file
66
64
  track_external_import(import_path, resolved_path, project_path)
@@ -77,14 +75,14 @@ module Strata
77
75
  next unless entry["source"] && File.exist?(entry["source"])
78
76
 
79
77
  current_hash = file_hash(entry["source"])
80
- if current_hash != entry["hash"]
81
- changed << {
82
- path: entry["path"],
83
- source: entry["source"],
84
- old_hash: entry["hash"],
85
- new_hash: current_hash
86
- }
87
- end
78
+ next unless current_hash != entry["hash"]
79
+
80
+ changed << {
81
+ path: entry["path"],
82
+ source: entry["source"],
83
+ old_hash: entry["hash"],
84
+ new_hash: current_hash
85
+ }
88
86
  end
89
87
 
90
88
  changed
@@ -99,15 +97,15 @@ module Strata
99
97
  next unless entry["source"] && File.exist?(entry["source"])
100
98
 
101
99
  current_hash = file_hash(entry["source"])
102
- if current_hash != entry["hash"]
103
- entry["hash"] = current_hash
104
- entry["imported_at"] = Time.now.utc.iso8601
105
- refreshed << {
106
- path: entry["path"],
107
- source: entry["source"],
108
- hash: current_hash
109
- }
110
- end
100
+ next unless current_hash != entry["hash"]
101
+
102
+ entry["hash"] = current_hash
103
+ entry["imported_at"] = Time.now.utc.iso8601
104
+ refreshed << {
105
+ path: entry["path"],
106
+ source: entry["source"],
107
+ hash: current_hash
108
+ }
111
109
  end
112
110
 
113
111
  save_lock_file(project_path, lock_data) if refreshed.any?
@@ -58,15 +58,15 @@ module Strata
58
58
  failed = tests.count { |t| t["status"] == "failed" }
59
59
  errors = tests.count { |t| t["status"] == "error" }
60
60
 
61
- say "\n" + "=" * 60, :border unless skip_opening_divider
61
+ say "\n#{"=" * 60}", :border unless skip_opening_divider
62
62
  say "\n Tests ran: #{total} total, #{passed} passed", :info
63
- say " #{failed} failed, #{errors} error#{"s" if errors != 1}" if failed > 0 || errors > 0
64
- say "\n" + "=" * 60, :border
63
+ say " #{failed} failed, #{errors} error#{"s" if errors != 1}" if failed.positive? || errors.positive?
64
+ say "\n#{"=" * 60}", :border
65
65
  end
66
66
 
67
67
  def display_failures(test_results)
68
68
  tests = test_results["tests"] || []
69
- failed_tests = tests.select { |t| t["status"] == "failed" || t["status"] == "error" }
69
+ failed_tests = tests.select { |t| %w[failed error].include?(t["status"]) }
70
70
 
71
71
  return if failed_tests.empty?
72
72
 
@@ -89,41 +89,32 @@ module Strata
89
89
  end
90
90
 
91
91
  # Display assertion failure details
92
- if test["assertion_type"]
93
- say " Assertion failed: #{test["assertion_type"]}", :error
94
- end
92
+ say " Assertion failed: #{test["assertion_type"]}", :error if test["assertion_type"]
95
93
 
96
- if test["message"]
97
- say " #{test["message"]}", :error
98
- end
94
+ say " #{test["message"]}", :error if test["message"]
99
95
 
100
96
  # Show expected vs generated SQL for debugging
101
- if test["expected_sql"]
102
- say " Expected: #{truncate(test["expected_sql"], 100)}", :error
103
- end
97
+ say " Expected: #{truncate(test["expected_sql"], 100)}", :error if test["expected_sql"]
104
98
 
105
- if test["pattern"]
106
- say " Pattern: #{test["pattern"]}", :error
107
- end
99
+ say " Pattern: #{test["pattern"]}", :error if test["pattern"]
108
100
 
109
- if test["generated_sql"]
110
- say " Generated: #{truncate(test["generated_sql"], 200)}", :error
111
- end
101
+ say " Generated: #{truncate(test["generated_sql"], 200)}", :error if test["generated_sql"]
112
102
 
113
- if test["failing_values"]&.is_a?(Array) && test["failing_values"].any?
114
- sample_values = test["failing_values"].first(5)
115
- say " Sample failing values: #{sample_values.inspect}", :error
116
- end
103
+ return unless test["failing_values"].is_a?(Array) && test["failing_values"].any?
104
+
105
+ sample_values = test["failing_values"].first(5)
106
+ say " Sample failing values: #{sample_values.inspect}", :error
117
107
  end
118
108
 
119
109
  def truncate(str, max_length)
120
110
  return str if str.nil? || str.length <= max_length
121
- str[0, max_length] + "..."
111
+
112
+ "#{str[0, max_length]}..."
122
113
  end
123
114
 
124
115
  def has_failures?(test_results)
125
116
  tests = test_results["tests"] || []
126
- tests.any? { |t| t["status"] == "failed" || t["status"] == "error" }
117
+ tests.any? { |t| %w[failed error].include?(t["status"]) }
127
118
  end
128
119
  end
129
120
  end
@@ -14,7 +14,7 @@ module Strata
14
14
  module_function
15
15
 
16
16
  GEM_NAME = "strata-cli"
17
- RUBYGEMS_API_URL = "https://rubygems.org/api/v1/gems/#{GEM_NAME}.json"
17
+ RUBYGEMS_API_URL = "https://rubygems.org/api/v1/gems/#{GEM_NAME}.json".freeze
18
18
  CACHE_FILE = File.join(ENV.fetch("TMPDIR", "/tmp"), "strata-cli-version-check-cache")
19
19
  CACHE_DURATION = 86_400 # 24 hours in seconds
20
20
 
@@ -24,9 +24,7 @@ module Strata
24
24
  latest_version = fetch_latest_version
25
25
  return unless latest_version
26
26
 
27
- if newer_version_available?(current_version, latest_version)
28
- display_update_message(latest_version)
29
- end
27
+ display_update_message(latest_version) if newer_version_available?(current_version, latest_version)
30
28
 
31
29
  update_cache
32
30
  rescue
@@ -40,8 +38,8 @@ module Strata
40
38
 
41
39
  # Simple version comparison (assumes semantic versioning)
42
40
  # Convert non-numeric parts (like "beta") to 0 for comparison
43
- current_parts = current.split(".").map { |p| p.to_i }
44
- latest_parts = latest.split(".").map { |p| p.to_i }
41
+ current_parts = current.split(".").map(&:to_i)
42
+ latest_parts = latest.split(".").map(&:to_i)
45
43
 
46
44
  # Pad with zeros if needed
47
45
  max_length = [current_parts.length, latest_parts.length].max
@@ -15,7 +15,10 @@ module Strata
15
15
  return {} unless File.exist?(file_path)
16
16
 
17
17
  absolute_path = File.expand_path(file_path)
18
- raise Strata::CircularImportError, "Circular import detected: #{format_cycle(visited, absolute_path)}" if visited.include?(absolute_path)
18
+ if visited.include?(absolute_path)
19
+ raise Strata::CircularImportError,
20
+ "Circular import detected: #{format_cycle(visited, absolute_path)}"
21
+ end
19
22
 
20
23
  visited.add(absolute_path)
21
24
  content = YAML.safe_load_file(file_path, permitted_classes: [Date, Time], aliases: true)
@@ -24,7 +27,7 @@ module Strata
24
27
  resolved_content = content.dup
25
28
  resolved_content.delete("imports")
26
29
 
27
- if content["imports"]&.is_a?(Array)
30
+ if content["imports"].is_a?(Array)
28
31
  merged_fields = resolve_imports(content["imports"], file_path, project_path, visited)
29
32
  resolved_content["fields"] = merge_fields(merged_fields, content["fields"] || [])
30
33
  else
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Strata
2
4
  module CLI
3
5
  module Utils
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Strata
4
4
  module CLI
5
- VERSION = "0.1.4.beta"
5
+ VERSION = "0.1.5.beta"
6
6
  end
7
7
  end