Class: Kettle::Jem::Appraisals::WorkflowStrategyGenerator
- Inherits:
-
Object
- Object
- Kettle::Jem::Appraisals::WorkflowStrategyGenerator
- Defined in:
- lib/kettle/jem/appraisals/workflow_strategy_generator.rb,
sig/kettle/jem/appraisals.rbs
Overview
Generates GitHub Actions workflow strategy matrix entries from the resolved appraisal matrix.
Groups entries by workflow lifecycle category (+current+, supported,
legacy, unsupported, ancient) based on Ruby bucket ranges.
Each matrix entry maps to a single CI job: a specific appraisal (tier1×tier2 version combo) on a specific Ruby version.
Lifecycle categories (kettle-jem convention)
current — latest stable MRI ("ruby"), plus jruby/truffleruby
supported — maintained MRI versions (currently 3.2, 3.3, 3.4)
legacy — security-only MRI (3.0, 3.1)
unsupported — EOL but recent MRI (2.6, 2.7)
ancient — very old MRI (2.3, 2.4, 2.5)
Constant Summary collapse
- LIFECYCLE_RANGES =
Returns Ruby lifecycle boundaries mapping lifecycle name to min/max
Gem::Versionranges (update as Ruby EOL progresses). { "current" => {ruby_alias: "ruby", min: Gem::Version.new("3.4"), max: Gem::Version.new("3.99")}, "supported" => {min: Gem::Version.new("3.2"), max: Gem::Version.new("3.3")}, "legacy" => {min: Gem::Version.new("3.0"), max: Gem::Version.new("3.1")}, "unsupported" => {min: Gem::Version.new("2.6"), max: Gem::Version.new("2.7")}, "ancient" => {min: Gem::Version.new("2.3"), max: Gem::Version.new("2.5")} }.freeze
Instance Attribute Summary collapse
-
#bucket_ranges ⇒ Hash{String => Hash}
readonly
Bucket →
{floor: Gem::Version, ceiling: Gem::Version}. -
#exec_cmd ⇒ String
readonly
The shell command to execute in each CI matrix job.
Instance Method Summary collapse
- #build_matrix_entry(entry, ruby_version) ⇒ Hash[Symbol, untyped]
-
#generate(appraisal_entries) ⇒ Hash{String => Array<Hash>}
Groups appraisal entries into workflow lifecycle files with matrix entries.
-
#generate_yaml_snippets(appraisal_entries) ⇒ Hash{String => String}
Generates YAML-compatible
strategy.matrix.includesnippets for each lifecycle. -
#initialize(bucket_ranges:, exec_cmd: "rake spec") ⇒ WorkflowStrategyGenerator
constructor
A new instance of WorkflowStrategyGenerator.
-
#lifecycle_for(ruby_floor) ⇒ String
Determines which lifecycle a Ruby floor version belongs to.
-
#ruby_version_for(ruby_floor, lifecycle) ⇒ String
Maps a Ruby floor version to the setup-ruby version string.
Constructor Details
#initialize(bucket_ranges:, exec_cmd: "rake spec") ⇒ WorkflowStrategyGenerator
Returns a new instance of WorkflowStrategyGenerator.
46 47 48 49 |
# File 'lib/kettle/jem/appraisals/workflow_strategy_generator.rb', line 46 def initialize(bucket_ranges:, exec_cmd: "rake spec") @bucket_ranges = bucket_ranges @exec_cmd = exec_cmd end |
Instance Attribute Details
#bucket_ranges ⇒ Hash{String => Hash} (readonly)
Returns bucket → {floor: Gem::Version, ceiling: Gem::Version}.
39 40 41 |
# File 'lib/kettle/jem/appraisals/workflow_strategy_generator.rb', line 39 def bucket_ranges @bucket_ranges end |
#exec_cmd ⇒ String (readonly)
Returns the shell command to execute in each CI matrix job.
42 43 44 |
# File 'lib/kettle/jem/appraisals/workflow_strategy_generator.rb', line 42 def exec_cmd @exec_cmd end |
Instance Method Details
#build_matrix_entry(entry, ruby_version) ⇒ Hash[Symbol, untyped]
122 123 124 125 126 127 128 129 130 131 |
# File 'lib/kettle/jem/appraisals/workflow_strategy_generator.rb', line 122 def build_matrix_entry(entry, ruby_version) { ruby: ruby_version, appraisal: entry[:appraisal_name] || entry[:name], exec_cmd: exec_cmd, gemfile: "Appraisal.root", rubygems: "latest", bundler: "latest" } end |
#generate(appraisal_entries) ⇒ Hash{String => Array<Hash>}
Groups appraisal entries into workflow lifecycle files with matrix entries.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/kettle/jem/appraisals/workflow_strategy_generator.rb', line 59 def generate(appraisal_entries) grouped = Hash.new { |h, k| h[k] = [] } appraisal_entries.each do |entry| bucket = entry[:ruby_series] range = bucket_ranges[bucket] next unless range lifecycle = lifecycle_for(range[:floor]) ruby_version = ruby_version_for(range[:floor], lifecycle) grouped[lifecycle] << build_matrix_entry(entry, ruby_version) end # Sort entries within each lifecycle by appraisal name grouped.transform_values { |entries| entries.sort_by { |e| e[:appraisal] } } end |
#generate_yaml_snippets(appraisal_entries) ⇒ Hash{String => String}
Generates YAML-compatible strategy.matrix.include snippets for each lifecycle.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/kettle/jem/appraisals/workflow_strategy_generator.rb', line 81 def generate_yaml_snippets(appraisal_entries) groups = generate(appraisal_entries) groups.transform_values { |entries| lines = ["strategy:", " matrix:", " include:"] entries.each do |entry| lines << " - ruby: #{entry[:ruby].inspect}" lines << " appraisal: #{entry[:appraisal].inspect}" lines << " exec_cmd: #{entry[:exec_cmd].inspect}" lines << " gemfile: #{entry[:gemfile].inspect}" lines << " rubygems: #{entry[:rubygems].inspect}" lines << " bundler: #{entry[:bundler].inspect}" end lines.join("\n") } end |
#lifecycle_for(ruby_floor) ⇒ String
Determines which lifecycle a Ruby floor version belongs to.
101 102 103 104 105 106 107 108 |
# File 'lib/kettle/jem/appraisals/workflow_strategy_generator.rb', line 101 def lifecycle_for(ruby_floor) LIFECYCLE_RANGES.each do |name, range| return name if ruby_floor.between?(range[:min], range[:max]) end # Fallback: if below all ranges, ancient; if above, current return "ancient" if ruby_floor < LIFECYCLE_RANGES["ancient"][:min] "current" end |
#ruby_version_for(ruby_floor, lifecycle) ⇒ String
Maps a Ruby floor version to the setup-ruby version string. For "current", uses "ruby" alias (latest stable). For all others, uses the explicit minor version (e.g., "3.2").
113 114 115 116 117 118 119 120 |
# File 'lib/kettle/jem/appraisals/workflow_strategy_generator.rb', line 113 def ruby_version_for(ruby_floor, lifecycle) if lifecycle == "current" "ruby" else segs = ruby_floor.segments "#{segs[0]}.#{segs[1] || 0}" end end |