serialbench 0.1.0 → 0.1.2
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 +4 -4
- data/.github/workflows/benchmark.yml +181 -30
- data/.github/workflows/ci.yml +3 -3
- data/.github/workflows/docker.yml +272 -0
- data/.github/workflows/rake.yml +15 -0
- data/.github/workflows/release.yml +25 -0
- data/Gemfile +6 -30
- data/README.adoc +381 -415
- data/Rakefile +0 -55
- data/config/benchmarks/full.yml +29 -0
- data/config/benchmarks/short.yml +26 -0
- data/config/environments/asdf-ruby-3.2.yml +8 -0
- data/config/environments/asdf-ruby-3.3.yml +8 -0
- data/config/environments/docker-ruby-3.0.yml +9 -0
- data/config/environments/docker-ruby-3.1.yml +9 -0
- data/config/environments/docker-ruby-3.2.yml +9 -0
- data/config/environments/docker-ruby-3.3.yml +9 -0
- data/config/environments/docker-ruby-3.4.yml +9 -0
- data/docker/Dockerfile.alpine +33 -0
- data/docker/Dockerfile.ubuntu +32 -0
- data/docker/README.md +214 -0
- data/exe/serialbench +1 -1
- data/lib/serialbench/benchmark_runner.rb +270 -350
- data/lib/serialbench/cli/base_cli.rb +51 -0
- data/lib/serialbench/cli/benchmark_cli.rb +380 -0
- data/lib/serialbench/cli/environment_cli.rb +181 -0
- data/lib/serialbench/cli/resultset_cli.rb +215 -0
- data/lib/serialbench/cli/ruby_build_cli.rb +238 -0
- data/lib/serialbench/cli.rb +59 -410
- data/lib/serialbench/config_manager.rb +140 -0
- data/lib/serialbench/models/benchmark_config.rb +63 -0
- data/lib/serialbench/models/benchmark_result.rb +45 -0
- data/lib/serialbench/models/environment_config.rb +71 -0
- data/lib/serialbench/models/platform.rb +59 -0
- data/lib/serialbench/models/result.rb +53 -0
- data/lib/serialbench/models/result_set.rb +71 -0
- data/lib/serialbench/models/result_store.rb +108 -0
- data/lib/serialbench/models.rb +54 -0
- data/lib/serialbench/ruby_build_manager.rb +153 -0
- data/lib/serialbench/runners/asdf_runner.rb +296 -0
- data/lib/serialbench/runners/base.rb +32 -0
- data/lib/serialbench/runners/docker_runner.rb +142 -0
- data/lib/serialbench/serializers/base_serializer.rb +8 -16
- data/lib/serialbench/serializers/json/base_json_serializer.rb +4 -4
- data/lib/serialbench/serializers/json/json_serializer.rb +0 -2
- data/lib/serialbench/serializers/json/oj_serializer.rb +0 -2
- data/lib/serialbench/serializers/json/rapidjson_serializer.rb +50 -0
- data/lib/serialbench/serializers/json/yajl_serializer.rb +6 -4
- data/lib/serialbench/serializers/toml/base_toml_serializer.rb +5 -3
- data/lib/serialbench/serializers/toml/toml_rb_serializer.rb +0 -2
- data/lib/serialbench/serializers/toml/tomlib_serializer.rb +0 -2
- data/lib/serialbench/serializers/toml/tomlrb_serializer.rb +56 -0
- data/lib/serialbench/serializers/xml/base_xml_serializer.rb +4 -9
- data/lib/serialbench/serializers/xml/libxml_serializer.rb +0 -2
- data/lib/serialbench/serializers/xml/nokogiri_serializer.rb +21 -5
- data/lib/serialbench/serializers/xml/oga_serializer.rb +0 -2
- data/lib/serialbench/serializers/xml/ox_serializer.rb +0 -2
- data/lib/serialbench/serializers/xml/rexml_serializer.rb +32 -4
- data/lib/serialbench/serializers/yaml/base_yaml_serializer.rb +59 -0
- data/lib/serialbench/serializers/yaml/psych_serializer.rb +54 -0
- data/lib/serialbench/serializers/yaml/syck_serializer.rb +102 -0
- data/lib/serialbench/serializers.rb +34 -6
- data/lib/serialbench/site_generator.rb +105 -0
- data/lib/serialbench/templates/assets/css/benchmark_report.css +535 -0
- data/lib/serialbench/templates/assets/css/format_based.css +526 -0
- data/lib/serialbench/templates/assets/css/themes.css +588 -0
- data/lib/serialbench/templates/assets/js/chart_helpers.js +381 -0
- data/lib/serialbench/templates/assets/js/dashboard.js +796 -0
- data/lib/serialbench/templates/assets/js/navigation.js +142 -0
- data/lib/serialbench/templates/base.liquid +49 -0
- data/lib/serialbench/templates/format_based.liquid +279 -0
- data/lib/serialbench/templates/partials/chart_section.liquid +4 -0
- data/lib/serialbench/version.rb +1 -1
- data/lib/serialbench.rb +2 -31
- data/serialbench.gemspec +28 -17
- metadata +192 -55
- data/lib/serialbench/chart_generator.rb +0 -821
- data/lib/serialbench/result_formatter.rb +0 -182
- data/lib/serialbench/result_merger.rb +0 -1201
- data/lib/serialbench/serializers/xml/base_parser.rb +0 -69
- data/lib/serialbench/serializers/xml/libxml_parser.rb +0 -98
- data/lib/serialbench/serializers/xml/nokogiri_parser.rb +0 -111
- data/lib/serialbench/serializers/xml/oga_parser.rb +0 -85
- data/lib/serialbench/serializers/xml/ox_parser.rb +0 -64
- data/lib/serialbench/serializers/xml/rexml_parser.rb +0 -129
@@ -0,0 +1,215 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_cli'
|
4
|
+
require_relative '../models/result_set'
|
5
|
+
require_relative '../site_generator'
|
6
|
+
|
7
|
+
module Serialbench
|
8
|
+
module Cli
|
9
|
+
# CLI for managing benchmark resultsets (collections of runs)
|
10
|
+
class ResultsetCli < BaseCli
|
11
|
+
desc 'create NAME PATH', 'Create a new resultset'
|
12
|
+
long_desc <<~DESC
|
13
|
+
Create a new resultset (collection of benchmark runs).
|
14
|
+
|
15
|
+
NAME is required and must be unique.
|
16
|
+
PATH is the directory where the resultset will be created.
|
17
|
+
|
18
|
+
Examples:
|
19
|
+
serialbench resultset create performance-comparison results/sets/performance-comparison
|
20
|
+
serialbench resultset create cross-platform-test results/sets/cross-platform-test
|
21
|
+
DESC
|
22
|
+
def create(resultset_name, resultset_path)
|
23
|
+
store = Serialbench::Models::ResultStore.default
|
24
|
+
|
25
|
+
# Check if resultset already exists
|
26
|
+
definition_path = File.join(resultset_path, 'resultset.yaml')
|
27
|
+
|
28
|
+
if File.exist?(definition_path)
|
29
|
+
say "ResultSet at '#{resultset_path}' already exists", :yellow
|
30
|
+
return unless yes?('Create anyway with timestamp suffix? (y/n)')
|
31
|
+
|
32
|
+
resultset_path = "#{resultset_path}-#{generate_timestamp}"
|
33
|
+
end
|
34
|
+
|
35
|
+
# Create empty resultset using the new ResultSet model
|
36
|
+
resultset = Serialbench::Models::ResultSet.new(
|
37
|
+
name: resultset_name,
|
38
|
+
description: "ResultSet for #{resultset_name} benchmarks",
|
39
|
+
created_at: Time.now.utc.iso8601,
|
40
|
+
updated_at: Time.now.utc.iso8601
|
41
|
+
)
|
42
|
+
resultset.save(resultset_path)
|
43
|
+
|
44
|
+
say "✅ Created resultset: #{resultset_path}", :green
|
45
|
+
say "Path: #{definition_path}", :cyan
|
46
|
+
say "Use 'serialbench resultset add-result' to add benchmark runs", :white
|
47
|
+
rescue StandardError => e
|
48
|
+
say "Error creating resultset: #{e.message}", :red
|
49
|
+
exit 1
|
50
|
+
end
|
51
|
+
|
52
|
+
desc 'add-result RESULT_PATH RESULTSET_PATH', 'Add a run to a resultset'
|
53
|
+
long_desc <<~DESC
|
54
|
+
Add an existing benchmark run to a resultset.
|
55
|
+
|
56
|
+
RESULT_PATH should be the path to a run result directory
|
57
|
+
RESULTSET_PATH must be specified explicitly
|
58
|
+
|
59
|
+
Examples:
|
60
|
+
serialbench resultset add-result results/sets/performance-comparison results/runs/my-run-local-macos-arm64-ruby-3.3.8
|
61
|
+
serialbench resultset add-result results/sets/cross-platform-test results/runs/my-docker-run
|
62
|
+
DESC
|
63
|
+
def add_result(resultset_path, result_path)
|
64
|
+
resultset = Serialbench::Models::ResultSet.load(resultset_path)
|
65
|
+
|
66
|
+
# Validate that the run location exists
|
67
|
+
unless Dir.exist?(result_path)
|
68
|
+
say "Result directory not found: #{result_path}", :red
|
69
|
+
return
|
70
|
+
end
|
71
|
+
|
72
|
+
# Add run to resultset
|
73
|
+
resultset.add_result(result_path)
|
74
|
+
resultset.save(resultset_path)
|
75
|
+
|
76
|
+
say '✅ Added run to resultset', :green
|
77
|
+
say "Path: #{result_path}", :cyan
|
78
|
+
say "ResultSet: #{resultset_path}", :cyan
|
79
|
+
say "Total runs in set: #{resultset.results.count}", :white
|
80
|
+
rescue StandardError => e
|
81
|
+
say "Error adding run to resultset: #{e.message}", :red
|
82
|
+
exit 1
|
83
|
+
end
|
84
|
+
|
85
|
+
desc 'remove-result RESULTSET_PATH RESULT_PATH', 'Remove a run from a resultset'
|
86
|
+
long_desc <<~DESC
|
87
|
+
Remove a benchmark run from a resultset.
|
88
|
+
|
89
|
+
RESULTSET_PATH must be specified explicitly
|
90
|
+
RESULT_PATH is the path to the run result directory
|
91
|
+
|
92
|
+
Examples:
|
93
|
+
serialbench resultset remove-result results/sets/performance-comparison results/runs/my-run-local-macos-arm64-ruby-3.3.8
|
94
|
+
serialbench resultset remove-result results/sets/cross-platform-test results/runs/my-docker-run
|
95
|
+
DESC
|
96
|
+
def remove_result(resultset_path, result_path)
|
97
|
+
store = Serialbench::Models::ResultStore.default
|
98
|
+
|
99
|
+
# Find the resultset
|
100
|
+
resultset = Serialbench::Models::ResultSet.load(resultset_path)
|
101
|
+
if resultset.nil?
|
102
|
+
say "ResultSet '#{resultset_path}' not found", :red
|
103
|
+
exit 1
|
104
|
+
end
|
105
|
+
|
106
|
+
# Remove run from resultset
|
107
|
+
removed = resultset.remove_run(run_identifier)
|
108
|
+
unless removed
|
109
|
+
say "Run '#{run_identifier}' not found in resultset", :yellow
|
110
|
+
say 'Available runs in resultset:', :white
|
111
|
+
resultset.runs.each do |run_info|
|
112
|
+
say " - #{run_info[:name]}", :white
|
113
|
+
end
|
114
|
+
return
|
115
|
+
end
|
116
|
+
|
117
|
+
resultset.save
|
118
|
+
|
119
|
+
say '✅ Removed run from resultset', :green
|
120
|
+
say "Run: #{run_identifier}", :cyan
|
121
|
+
say "ResultSet: #{resultset_path}", :cyan
|
122
|
+
say "Remaining runs in set: #{resultset.runs.length}", :white
|
123
|
+
rescue StandardError => e
|
124
|
+
say "Error removing run from resultset: #{e.message}", :red
|
125
|
+
exit 1
|
126
|
+
end
|
127
|
+
|
128
|
+
desc 'build-site RESULTSET_PATH [OUTPUT_DIR]', 'Generate HTML site for a resultset'
|
129
|
+
long_desc <<~DESC
|
130
|
+
Generate an HTML site for a resultset (comparative analysis).
|
131
|
+
|
132
|
+
RESULTSET_PATH must be specified explicitly
|
133
|
+
OUTPUT_DIR defaults to _site/
|
134
|
+
|
135
|
+
Examples:
|
136
|
+
serialbench resultset build-site results/sets/performance-comparison
|
137
|
+
serialbench resultset build-site results/sets/cross-platform-test output/
|
138
|
+
DESC
|
139
|
+
option :output_dir, type: :string, default: '_site', desc: 'Output directory for generated site'
|
140
|
+
def build_site(resultset_path)
|
141
|
+
unless Dir.exist?(resultset_path)
|
142
|
+
say "ResultSet directory not found: #{resultset_path}", :red
|
143
|
+
say "Please create a resultset first using 'serialbench resultset create'", :white
|
144
|
+
exit 1
|
145
|
+
end
|
146
|
+
|
147
|
+
resultset = Serialbench::Models::ResultSet.load(resultset_path)
|
148
|
+
|
149
|
+
if resultset.results.empty?
|
150
|
+
say "ResultSet '#{resultset_path}' contains no runs", :yellow
|
151
|
+
say "Use 'serialbench resultset add-result' to add runs first", :white
|
152
|
+
return
|
153
|
+
end
|
154
|
+
|
155
|
+
say "🏗️ Generating HTML site for resultset: #{resultset_path}", :green
|
156
|
+
say "Runs in set: #{resultset.results.size}", :cyan
|
157
|
+
|
158
|
+
# Use the unified site generator for resultsets
|
159
|
+
Serialbench::SiteGenerator.generate_for_resultset(resultset, options[:output_dir])
|
160
|
+
|
161
|
+
say '✅ HTML site generated successfully!', :green
|
162
|
+
say "Site location: #{options[:output_dir]}", :cyan
|
163
|
+
say "Open: #{File.join(options[:output_dir], 'index.html')}", :white
|
164
|
+
rescue StandardError => e
|
165
|
+
say "Error generating site: #{e.message}", :red
|
166
|
+
say "Details: #{e.backtrace.first(3).join("\n")}", :red if options[:verbose]
|
167
|
+
exit 1
|
168
|
+
end
|
169
|
+
|
170
|
+
desc 'list', 'List all available resultsets'
|
171
|
+
long_desc <<~DESC
|
172
|
+
List all resultsets in the results/sets/ directory.
|
173
|
+
|
174
|
+
Shows resultset names, number of runs, and timestamps.
|
175
|
+
DESC
|
176
|
+
def list
|
177
|
+
ensure_results_directory
|
178
|
+
|
179
|
+
begin
|
180
|
+
store = Serialbench::Models::ResultStore.default
|
181
|
+
resultsets = store.find_resultsets
|
182
|
+
|
183
|
+
if resultsets.empty?
|
184
|
+
say 'No resultsets found', :yellow
|
185
|
+
say "Use 'serialbench resultset create' to create a resultset", :white
|
186
|
+
return
|
187
|
+
end
|
188
|
+
|
189
|
+
say 'Available ResultSets:', :green
|
190
|
+
say '=' * 50, :green
|
191
|
+
|
192
|
+
resultsets.each do |resultset|
|
193
|
+
say "📁 #{resultset.name}", :cyan
|
194
|
+
say " Runs: #{resultset.runs.length}", :white
|
195
|
+
say " Created: #{resultset.metadata[:timestamp]}", :white
|
196
|
+
say " Path: #{resultset.directory}", :white
|
197
|
+
|
198
|
+
if resultset.runs.any?
|
199
|
+
say ' Contains:', :white
|
200
|
+
resultset.runs.first(3).each do |run_info|
|
201
|
+
say " - #{run_info[:name]}", :white
|
202
|
+
end
|
203
|
+
say " ... and #{resultset.runs.length - 3} more" if resultset.runs.length > 3
|
204
|
+
end
|
205
|
+
|
206
|
+
say ''
|
207
|
+
end
|
208
|
+
rescue StandardError => e
|
209
|
+
say "Error listing resultsets: #{e.message}", :red
|
210
|
+
exit 1
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
@@ -0,0 +1,238 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_cli'
|
4
|
+
require_relative '../ruby_build_manager'
|
5
|
+
|
6
|
+
module Serialbench
|
7
|
+
module Cli
|
8
|
+
# CLI for managing Ruby-Build definitions
|
9
|
+
class RubyBuildCli < BaseCli
|
10
|
+
desc 'update', 'Update Ruby-Build definitions from GitHub'
|
11
|
+
long_desc <<~DESC
|
12
|
+
Fetch the latest Ruby-Build definitions from the official ruby-build repository
|
13
|
+
and cache them locally for validation purposes.
|
14
|
+
|
15
|
+
This command is required before using any Ruby-Build validation features.
|
16
|
+
|
17
|
+
Examples:
|
18
|
+
serialbench ruby-build update
|
19
|
+
DESC
|
20
|
+
def update
|
21
|
+
say '🔄 Updating Ruby-Build definitions...', :green
|
22
|
+
|
23
|
+
begin
|
24
|
+
definitions = RubyBuildManager.update_definitions
|
25
|
+
|
26
|
+
say "✅ Successfully updated #{definitions.length} Ruby-Build definitions", :green
|
27
|
+
say "📁 Cache location: #{RubyBuildManager::CACHE_FILE}", :cyan
|
28
|
+
|
29
|
+
# Show some examples
|
30
|
+
recent_versions = definitions.select { |d| d.match?(/^3\.[2-4]\.\d+$/) }.last(5)
|
31
|
+
if recent_versions.any?
|
32
|
+
say "\n📋 Recent Ruby versions available:", :white
|
33
|
+
recent_versions.each { |version| say " #{version}", :cyan }
|
34
|
+
end
|
35
|
+
|
36
|
+
rescue StandardError => e
|
37
|
+
say "❌ Failed to update Ruby-Build definitions: #{e.message}", :red
|
38
|
+
exit 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'list [FILTER]', 'List available Ruby-Build definitions'
|
43
|
+
long_desc <<~DESC
|
44
|
+
List all available Ruby-Build definitions from the local cache.
|
45
|
+
|
46
|
+
Optionally filter the list by providing a filter string.
|
47
|
+
|
48
|
+
Examples:
|
49
|
+
serialbench ruby-build list # List all definitions
|
50
|
+
serialbench ruby-build list 3.3 # Filter by "3.3"
|
51
|
+
serialbench ruby-build list 3.2. # Filter by "3.2."
|
52
|
+
DESC
|
53
|
+
option :limit, type: :numeric, default: 50, desc: 'Maximum number of definitions to show'
|
54
|
+
def list(filter = nil)
|
55
|
+
begin
|
56
|
+
definitions = RubyBuildManager.list_definitions(filter: filter)
|
57
|
+
|
58
|
+
if definitions.empty?
|
59
|
+
if filter
|
60
|
+
say "No Ruby-Build definitions found matching '#{filter}'", :yellow
|
61
|
+
else
|
62
|
+
say 'No Ruby-Build definitions found in cache', :yellow
|
63
|
+
say 'Update the cache first: serialbench ruby-build update', :white
|
64
|
+
end
|
65
|
+
return
|
66
|
+
end
|
67
|
+
|
68
|
+
# Limit results if there are many
|
69
|
+
limited_definitions = definitions.first(options[:limit])
|
70
|
+
|
71
|
+
say "Ruby-Build Definitions#{filter ? " (filtered by '#{filter}')" : ''}:", :green
|
72
|
+
say '=' * 60, :green
|
73
|
+
|
74
|
+
limited_definitions.each do |definition|
|
75
|
+
say " #{definition}", :cyan
|
76
|
+
end
|
77
|
+
|
78
|
+
if definitions.length > options[:limit]
|
79
|
+
remaining = definitions.length - options[:limit]
|
80
|
+
say "\n... and #{remaining} more definitions", :yellow
|
81
|
+
say "Use --limit to show more results", :white
|
82
|
+
end
|
83
|
+
|
84
|
+
say "\nTotal: #{definitions.length} definitions", :white
|
85
|
+
|
86
|
+
rescue StandardError => e
|
87
|
+
say "❌ Failed to list Ruby-Build definitions: #{e.message}", :red
|
88
|
+
say 'Try updating the cache: serialbench ruby-build update', :white
|
89
|
+
exit 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
desc 'show TAG', 'Show details for a specific Ruby-Build definition'
|
94
|
+
long_desc <<~DESC
|
95
|
+
Show detailed information about a specific Ruby-Build definition.
|
96
|
+
|
97
|
+
Examples:
|
98
|
+
serialbench ruby-build show 3.3.8
|
99
|
+
serialbench ruby-build show 3.2.4
|
100
|
+
DESC
|
101
|
+
def show(tag)
|
102
|
+
begin
|
103
|
+
definition = RubyBuildManager.show_definition(tag)
|
104
|
+
|
105
|
+
say "Ruby-Build Definition: #{tag}", :green
|
106
|
+
say '=' * 40, :green
|
107
|
+
say "Tag: #{definition[:tag]}", :cyan
|
108
|
+
say "Available: #{definition[:available] ? '✅ Yes' : '❌ No'}", :cyan
|
109
|
+
say "Source: #{definition[:source]}", :cyan
|
110
|
+
say "Cache file: #{definition[:cache_file]}", :white
|
111
|
+
|
112
|
+
rescue StandardError => e
|
113
|
+
say "❌ #{e.message}", :red
|
114
|
+
say 'Available definitions: serialbench ruby-build list', :white
|
115
|
+
exit 1
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
desc 'validate TAG', 'Validate a Ruby-Build tag'
|
120
|
+
long_desc <<~DESC
|
121
|
+
Validate whether a Ruby-Build tag exists in the cached definitions.
|
122
|
+
|
123
|
+
Examples:
|
124
|
+
serialbench ruby-build validate 3.3.8
|
125
|
+
serialbench ruby-build validate 3.2.4
|
126
|
+
DESC
|
127
|
+
def validate(tag)
|
128
|
+
begin
|
129
|
+
valid = RubyBuildManager.validate_tag(tag)
|
130
|
+
|
131
|
+
if valid
|
132
|
+
say "✅ Ruby-Build tag '#{tag}' is valid", :green
|
133
|
+
else
|
134
|
+
say "❌ Ruby-Build tag '#{tag}' is not valid", :red
|
135
|
+
|
136
|
+
# Suggest similar tags
|
137
|
+
definitions = RubyBuildManager.list_definitions
|
138
|
+
similar = definitions.select { |d| d.include?(tag.split('.').first(2).join('.')) }.first(5)
|
139
|
+
|
140
|
+
if similar.any?
|
141
|
+
say "\n💡 Similar available tags:", :yellow
|
142
|
+
similar.each { |s| say " #{s}", :cyan }
|
143
|
+
end
|
144
|
+
|
145
|
+
exit 1
|
146
|
+
end
|
147
|
+
|
148
|
+
rescue StandardError => e
|
149
|
+
say "❌ Failed to validate tag: #{e.message}", :red
|
150
|
+
say 'Try updating the cache: serialbench ruby-build update', :white
|
151
|
+
exit 1
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
desc 'suggest', 'Suggest Ruby-Build tag for current Ruby version'
|
156
|
+
long_desc <<~DESC
|
157
|
+
Suggest an appropriate Ruby-Build tag based on the current Ruby version.
|
158
|
+
|
159
|
+
This is useful when creating local environments to get the correct
|
160
|
+
ruby_build_tag value.
|
161
|
+
|
162
|
+
Examples:
|
163
|
+
serialbench ruby-build suggest
|
164
|
+
DESC
|
165
|
+
def suggest
|
166
|
+
begin
|
167
|
+
current_ruby = RUBY_VERSION
|
168
|
+
suggested_tag = RubyBuildManager.suggest_current_ruby_tag
|
169
|
+
|
170
|
+
say "Current Ruby version: #{current_ruby}", :cyan
|
171
|
+
say "Suggested ruby_build_tag: #{suggested_tag}", :green
|
172
|
+
|
173
|
+
# Validate the suggestion
|
174
|
+
if RubyBuildManager.validate_tag(suggested_tag)
|
175
|
+
say "✅ Suggested tag is valid", :green
|
176
|
+
else
|
177
|
+
say "⚠️ Suggested tag not found in ruby-build definitions", :yellow
|
178
|
+
say "You may need to update the cache or use a different tag", :white
|
179
|
+
end
|
180
|
+
|
181
|
+
rescue StandardError => e
|
182
|
+
say "❌ Failed to suggest tag: #{e.message}", :red
|
183
|
+
say 'Try updating the cache: serialbench ruby-build update', :white
|
184
|
+
exit 1
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
desc 'cache-info', 'Show information about the Ruby-Build definitions cache'
|
189
|
+
long_desc <<~DESC
|
190
|
+
Display information about the local Ruby-Build definitions cache,
|
191
|
+
including location, age, and update status.
|
192
|
+
|
193
|
+
Examples:
|
194
|
+
serialbench ruby-build cache-info
|
195
|
+
DESC
|
196
|
+
def cache_info
|
197
|
+
if RubyBuildManager.cache_exists?
|
198
|
+
cache_age = RubyBuildManager.cache_age
|
199
|
+
definitions_count = RubyBuildManager.list_definitions.length
|
200
|
+
|
201
|
+
say 'Ruby-Build Cache Information:', :green
|
202
|
+
say '=' * 40, :green
|
203
|
+
say "Location: #{RubyBuildManager::CACHE_FILE}", :cyan
|
204
|
+
say "Definitions: #{definitions_count}", :cyan
|
205
|
+
say "Age: #{format_cache_age(cache_age)}", :cyan
|
206
|
+
say "Status: ✅ Available", :green
|
207
|
+
|
208
|
+
if cache_age > 7 * 24 * 60 * 60 # 7 days
|
209
|
+
say "\n💡 Cache is older than 7 days, consider updating:", :yellow
|
210
|
+
say " serialbench ruby-build update", :white
|
211
|
+
end
|
212
|
+
else
|
213
|
+
say 'Ruby-Build Cache Information:', :green
|
214
|
+
say '=' * 40, :green
|
215
|
+
say "Location: #{RubyBuildManager::CACHE_FILE}", :cyan
|
216
|
+
say "Status: ❌ Not found", :red
|
217
|
+
say "\n📥 Update the cache first:", :yellow
|
218
|
+
say " serialbench ruby-build update", :white
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
private
|
223
|
+
|
224
|
+
def format_cache_age(seconds)
|
225
|
+
days = (seconds / (24 * 60 * 60)).to_i
|
226
|
+
hours = ((seconds % (24 * 60 * 60)) / (60 * 60)).to_i
|
227
|
+
|
228
|
+
if days > 0
|
229
|
+
"#{days} day#{'s' if days != 1}, #{hours} hour#{'s' if hours != 1}"
|
230
|
+
elsif hours > 0
|
231
|
+
"#{hours} hour#{'s' if hours != 1}"
|
232
|
+
else
|
233
|
+
"less than 1 hour"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|