kettle-jem 7.1.1 → 7.1.3

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/lib/kettle/jem.rb CHANGED
@@ -38,7 +38,7 @@ module Kettle
38
38
  CONTENT_RECIPE_TRANSPORT_VERSION = Ast::Merge::STRUCTURED_EDIT_TRANSPORT_VERSION
39
39
  TEMPLATE_SOURCE_APPLICATION_FINGERPRINT_VERSION = 1
40
40
  APPRAISALS_TEMPLATE_POLICY_FINGERPRINT_VERSION = 2
41
- GEMSPEC_TEMPLATE_POLICY_FINGERPRINT_VERSION = 1
41
+ GEMSPEC_TEMPLATE_POLICY_FINGERPRINT_VERSION = 2
42
42
  SPEC_HELPER_TEMPLATE_POLICY_FINGERPRINT_VERSION = 1
43
43
  VERSION_NAMESPACE_TEMPLATE_POLICY_FINGERPRINT_VERSION = 2
44
44
  KETTLE_CONFIG_PATH = ".structuredmerge/kettle-jem.yml"
@@ -50,6 +50,9 @@ module Kettle
50
50
  GEMSPEC_DEPENDENCY_MINIMUM_REQUIREMENTS = {
51
51
  "rspec-stubbed_env" => ">= 1.0.6"
52
52
  }.freeze
53
+ DEFAULT_GEMSPEC_METADATA_VALUES = {
54
+ "allowed_push_host" => "TODO: Set to your gem server 'https://example.com'"
55
+ }.freeze
53
56
  OBSOLETE_GITHUB_WORKFLOWS = %w[
54
57
  ancient.yml
55
58
  legacy.yml
@@ -439,6 +442,7 @@ module Kettle
439
442
  KJ|MAIN_GEMFILE_NOMONO_BOOTSTRAP
440
443
  KJ|MIN_DIVERGENCE_THRESHOLD
441
444
  KJ|MIN_RUBY
445
+ KJ|KETTLE_CHANGELOG_GEMFILE_DEPENDENCY
442
446
  KJ|OPENCOLLECTIVE_ORG
443
447
  KJ|README:COPYRIGHT_NOTICE
444
448
  KJ|README:CORPORATE_SPONSORS
@@ -848,6 +852,9 @@ module Kettle
848
852
  label = owner.label.to_s
849
853
  label if patterns.fetch(:ref_prefixes).any? { |pattern| pattern.match?(label) }
850
854
  end
855
+ ref_labels.each do |label|
856
+ processed = remove_markdown_inline_references(processed, label)
857
+ end
851
858
  processed = delete_markdown_link_definitions(processed, ref_labels)
852
859
  end
853
860
 
@@ -1399,6 +1406,7 @@ module Kettle
1399
1406
  "🖇osc-sponsors-bottom-img"
1400
1407
  ].freeze
1401
1408
  README_INTEGRATIONS = %w[codecov coveralls qlty codeql skywalking-eyes].freeze
1409
+ README_STAR_HISTORY_MIN_STARS = 150
1402
1410
  README_DISCOVERED_INTEGRATIONS = (README_INTEGRATIONS - [SKYWALKING_EYES_INTEGRATION]).freeze
1403
1411
  COVERAGE_INTEGRATIONS = %w[codecov coveralls qlty].freeze
1404
1412
  MANAGED_INTEGRATIONS = (COVERAGE_INTEGRATIONS + [SKYWALKING_EYES_INTEGRATION]).freeze
@@ -4790,6 +4798,10 @@ module Kettle
4790
4798
  end
4791
4799
 
4792
4800
  def post_apply_steps(project_root, report)
4801
+ selection = report.fetch(:template_selection, {})
4802
+ scoped_template = Array(selection[:only]).any?
4803
+ return [kettle_jem_state_sync_step(project_root, report)].compact if scoped_template
4804
+
4793
4805
  [
4794
4806
  *[template_version_gem_bootstrap_step(project_root, report)].flatten,
4795
4807
  executable_version_entrypoint_sync_step(project_root, report),
@@ -5164,6 +5176,7 @@ module Kettle
5164
5176
  updated.insert(profile_index + 1, *entries_lines)
5165
5177
  end
5166
5178
  sync_kettle_config_gemspec_strategy_lines!(updated, gemspec_path)
5179
+ sync_kettle_config_rakefile_strategy_lines!(updated)
5167
5180
  ensure_trailing_newline(updated.join("\n"))
5168
5181
  end
5169
5182
 
@@ -5194,6 +5207,33 @@ module Kettle
5194
5207
  end
5195
5208
  end
5196
5209
 
5210
+ def sync_kettle_config_rakefile_strategy_lines!(lines)
5211
+ files_index = lines.index("files:")
5212
+ return unless files_index
5213
+
5214
+ rakefile_index = ((files_index + 1)...lines.length).find do |index|
5215
+ line = lines.fetch(index)
5216
+ break nil if top_level_yaml_key_line?(line)
5217
+
5218
+ line == " Rakefile:"
5219
+ end
5220
+ unless rakefile_index
5221
+ insertion_index = kettle_config_gemspec_override_insertion_index(lines, files_index)
5222
+ lines.insert(insertion_index, " Rakefile:", " strategy: accept_template")
5223
+ return
5224
+ end
5225
+
5226
+ block_end = kettle_config_file_override_block_end(lines, rakefile_index)
5227
+ strategy_index = ((rakefile_index + 1)...block_end).find do |index|
5228
+ lines.fetch(index).start_with?(" strategy:")
5229
+ end
5230
+ if strategy_index
5231
+ lines[strategy_index] = " strategy: accept_template"
5232
+ else
5233
+ lines.insert(rakefile_index + 1, " strategy: accept_template")
5234
+ end
5235
+ end
5236
+
5197
5237
  def remove_stale_gemspec_file_override_blocks!(lines, files_index, gemspec)
5198
5238
  index = files_index + 1
5199
5239
  while index < lines.length
@@ -5278,15 +5318,15 @@ module Kettle
5278
5318
  [
5279
5319
  {name: "appraisal2", source: %(gem "appraisal2", "~> 3.2", ">= 3.2.2"\n)},
5280
5320
  {name: "bundler-audit", source: %(gem "bundler-audit", "~> 0.9.3"\n)},
5281
- {name: "kettle-dev", source: %(gem "kettle-dev", "~> 2.5", ">= 2.5.24"\n)},
5321
+ {name: "kettle-dev", source: %(gem "kettle-dev", "~> 3.0", ">= 3.0.0"\n)},
5282
5322
  {name: "kettle-drift", source: %(gem "kettle-drift", "~> 1.0", ">= 1.0.12"\n)},
5283
- {name: "kettle-family", source: %(gem "kettle-family", "~> 1.2", ">= 1.2.41"\n)},
5284
- {name: "kettle-jem", source: %(gem "kettle-jem", "~> 7.0", ">= 7.0.0"\n)},
5323
+ {name: "kettle-family", source: %(gem "kettle-family", "~> 1.2", ">= 1.2.44"\n)},
5324
+ {name: "kettle-jem", source: %(gem "kettle-jem", "~> 7.1", ">= 7.1.1"\n)},
5285
5325
  {name: "kettle-test", source: %(gem "kettle-test", "~> 2.0", ">= 2.0.19"\n)},
5286
5326
  {name: "rake", source: %(gem "rake", "~> 13.0"\n)},
5287
5327
  {name: "rspec", source: %(gem "rspec", "~> 3.0"\n)},
5288
5328
  {name: "stone_checksums", source: %(gem "stone_checksums", "~> 1.0", ">= 1.0.8"\n)},
5289
- {name: "turbo_tests2", source: %(gem "turbo_tests2", "~> 3.2", ">= 3.2.4"\n)}
5329
+ {name: "turbo_tests2", source: %(gem "turbo_tests2", "~> 3.2", ">= 3.2.5"\n)}
5290
5330
  ].freeze
5291
5331
  end
5292
5332
 
@@ -6988,7 +7028,13 @@ module Kettle
6988
7028
  destination_content: original
6989
7029
  )
6990
7030
  return with_readme_timing("readme.append_used_link_definitions") do
6991
- append_used_markdown_link_definitions(processed, resolved)
7031
+ appended = append_used_markdown_link_definitions(processed, resolved)
7032
+ postprocess_readme_content(
7033
+ appended,
7034
+ facts,
7035
+ project_root: project_root,
7036
+ destination_content: original
7037
+ )
6992
7038
  end
6993
7039
  end
6994
7040
  if strategy.empty? || strategy == "merge"
@@ -7164,7 +7210,9 @@ module Kettle
7164
7210
 
7165
7211
  def delete_yaml_top_level_mapping_entries(content, parent_key:, child_keys:)
7166
7212
  document = Psych.parse(content.to_s)
7167
- root = document&.root
7213
+ # Psych returns `false` for a comment-only document under some versions.
7214
+ # Such content has no mapping to prune and must pass through unchanged.
7215
+ root = document.root if document.respond_to?(:root)
7168
7216
  return content unless root.is_a?(Psych::Nodes::Mapping)
7169
7217
 
7170
7218
  parent = yaml_mapping_value(root, parent_key)
@@ -7174,7 +7222,7 @@ module Kettle
7174
7222
  ranges = parent.children.each_slice(2).filter_map do |key_node, value_node|
7175
7223
  next unless child_key_set.include?(key_node.value.to_s)
7176
7224
 
7177
- key_node.start_line..value_node.end_line
7225
+ key_node.start_line...value_node.end_line
7178
7226
  end
7179
7227
  return content if ranges.empty?
7180
7228
 
@@ -7232,6 +7280,13 @@ module Kettle
7232
7280
  engines: facts.dig(:rubygems, :engines)
7233
7281
  )
7234
7282
  end
7283
+ processed = with_readme_timing("postprocess.compatibility_summary") do
7284
+ normalize_readme_compatibility_summary(
7285
+ processed,
7286
+ facts.dig(:rubygems, :engines),
7287
+ minimum_ruby_token(facts.dig(:rubygems, :min_ruby))
7288
+ )
7289
+ end
7235
7290
  processed = with_readme_timing("postprocess.project_heading") { normalize_readme_project_heading(processed, facts) }
7236
7291
  processed = with_readme_timing("postprocess.synopsis_heading") { normalize_readme_synopsis_heading(processed, facts) }
7237
7292
  processed = with_readme_timing("postprocess.conditional_blocks") { apply_readme_conditional_blocks(processed, facts) }
@@ -7334,7 +7389,17 @@ module Kettle
7334
7389
  def apply_readme_conditional_blocks(content, facts)
7335
7390
  open_collective_enabled = !facts.dig(:funding, :open_collective_disabled)
7336
7391
  processed = apply_markdown_conditional_block(content, "OPEN_COLLECTIVE", keep: open_collective_enabled)
7337
- apply_markdown_conditional_block(processed, "NO_OPEN_COLLECTIVE", keep: !open_collective_enabled)
7392
+ processed = apply_markdown_conditional_block(processed, "NO_OPEN_COLLECTIVE", keep: !open_collective_enabled)
7393
+ star_history_enabled = facts.dig(:repository, :star_history, :enabled) == true
7394
+ return processed if star_history_enabled
7395
+
7396
+ delete_markdown_with_ast_crispr(
7397
+ processed,
7398
+ Ast::Crispr::Markdown::Markly::Selectors.html_details(
7399
+ summary_text: "⭐️ Star History",
7400
+ limit: {at_least: 0}
7401
+ )
7402
+ )
7338
7403
  end
7339
7404
 
7340
7405
  def apply_readme_badge_policy(content, facts)
@@ -7364,9 +7429,31 @@ module Kettle
7364
7429
  )
7365
7430
  end
7366
7431
  end
7432
+ Array(facts.dig(:readme_style, :disabled_integrations)).each do |integration|
7433
+ patterns = README_INTEGRATION_BADGE_PATTERNS.fetch(integration.to_s, [])
7434
+ labels = README_INTEGRATION_LINK_LABELS.fetch(integration.to_s, [])
7435
+ processed = patterns.reduce(processed) { |content, pattern| content.gsub(pattern, "") }
7436
+ processed = ReadmePostProcessor.delete_markdown_link_definitions(processed, labels)
7437
+ end
7367
7438
  processed
7368
7439
  end
7369
7440
 
7441
+ def normalize_readme_compatibility_summary(content, engines, min_ruby = "")
7442
+ enabled = Array(engines).map { |engine| engine.to_s.strip.downcase }.reject(&:empty?).uniq
7443
+ return content if enabled.empty?
7444
+
7445
+ runtime_floor = min_ruby.to_s.strip
7446
+ runtime_floor = " #{runtime_floor}+" unless runtime_floor.empty?
7447
+ runtime_engines = ["MRI Ruby#{runtime_floor}"]
7448
+ runtime_engines << "JRuby" if enabled.include?("jruby")
7449
+ runtime_engines << "TruffleRuby" if enabled.include?("truffleruby") || enabled.include?("truby")
7450
+ description = runtime_engines.one? ? runtime_engines.first : runtime_engines[0...-1].join(", ") + ", and #{runtime_engines.last}"
7451
+ content.to_s.sub(
7452
+ /Compatible with MRI Ruby [^\n]+\./,
7453
+ "Compatible with #{description}."
7454
+ )
7455
+ end
7456
+
7370
7457
  def remove_readme_badge_and_refs(content, badge_source, link_labels)
7371
7458
  ensure_runtime_dependencies!
7372
7459
  processed = content.to_s.gsub(badge_source, "").lines.map(&:rstrip).join("\n")
@@ -9646,7 +9733,7 @@ module Kettle
9646
9733
  replacement = if record.fetch(:source).lines.one?
9647
9734
  "%w[#{kept.join(" ")}]"
9648
9735
  else
9649
- ruby_multiline_word_array_source(kept, indent: record.fetch(:start_column))
9736
+ ruby_multiline_word_array_source(kept, indent: record.fetch(:line_indent))
9650
9737
  end
9651
9738
  {start_offset: record.fetch(:start_offset), end_offset: record.fetch(:end_offset), replacement: replacement}
9652
9739
  end
@@ -9657,13 +9744,15 @@ module Kettle
9657
9744
  end
9658
9745
 
9659
9746
  def ruby_word_array_records(content)
9747
+ lines = content.to_s.lines
9660
9748
  ruby_word_array_nodes(content).map do |node|
9749
+ source_line = lines.fetch(node.location.start_line - 1)
9661
9750
  {
9662
9751
  names: ruby_word_array_names(node),
9663
9752
  source: node.location.slice,
9664
9753
  start_line: node.location.start_line,
9665
9754
  end_line: node.location.end_line,
9666
- start_column: node.location.start_column,
9755
+ line_indent: source_line.length - source_line.lstrip.length,
9667
9756
  start_offset: node.location.start_offset,
9668
9757
  end_offset: node.location.end_offset
9669
9758
  }
@@ -9690,9 +9779,9 @@ module Kettle
9690
9779
  end
9691
9780
 
9692
9781
  def ruby_multiline_word_array_source(names, indent:)
9693
- prefix = " " * indent.to_i
9694
- element_prefix = "#{prefix} "
9695
- (["#{prefix}%w["] + names.map { |name| "#{element_prefix}#{name}" } + ["#{prefix}]"]).join("\n")
9782
+ element_prefix = " " * (indent.to_i + 2)
9783
+ closing_prefix = " " * indent.to_i
9784
+ (["%w["] + names.map { |name| "#{element_prefix}#{name}" } + ["#{closing_prefix}]"]).join("\n")
9696
9785
  end
9697
9786
 
9698
9787
  def replace_source_offsets(content, replacements)
@@ -10259,6 +10348,13 @@ module Kettle
10259
10348
  merged = apply_configured_gemspec_licenses(merged, facts, receiver: template_receiver)
10260
10349
  merged = apply_configured_gemspec_required_ruby_version(merged, facts, receiver: template_receiver)
10261
10350
  merged = apply_configured_gemspec_metadata(merged, facts, receiver: template_receiver)
10351
+ merged = preserve_destination_only_gemspec_metadata(
10352
+ merged,
10353
+ template_content: template_content,
10354
+ destination_content: destination_content,
10355
+ template_receiver: template_receiver,
10356
+ destination_receiver: destination_receiver
10357
+ )
10262
10358
  merged = remove_duplicate_gemspec_assignments(merged, receiver: template_receiver, fields: %w[homepage])
10263
10359
  merged = remove_gemspec_self_dependency_lines(merged, package_name, receiver: template_receiver)
10264
10360
  merged = remove_gemspec_version_gem_dependency_when_disabled(
@@ -10527,6 +10623,36 @@ module Kettle
10527
10623
  content
10528
10624
  end
10529
10625
 
10626
+ def preserve_destination_only_gemspec_metadata(
10627
+ content,
10628
+ template_content:,
10629
+ destination_content:,
10630
+ template_receiver:,
10631
+ destination_receiver:
10632
+ )
10633
+ template_keys = gemspec_metadata_assignment_records(template_content, receiver: template_receiver).map do |record|
10634
+ record.fetch(:key)
10635
+ end
10636
+ merged_keys = gemspec_metadata_assignment_records(content, receiver: template_receiver).map do |record|
10637
+ record.fetch(:key)
10638
+ end
10639
+ destination_records = gemspec_metadata_assignment_records(destination_content, receiver: destination_receiver).select do |record|
10640
+ !template_keys.include?(record.fetch(:key)) &&
10641
+ !merged_keys.include?(record.fetch(:key)) &&
10642
+ !default_gemspec_metadata_assignment?(record)
10643
+ end
10644
+ return content if destination_records.empty?
10645
+
10646
+ insertion = destination_records.map do |record|
10647
+ normalize_gemspec_receiver(record.fetch(:source).rstrip, from: destination_receiver, to: template_receiver)
10648
+ end.join("\n") + "\n"
10649
+ anchor = gemspec_metadata_assignment_records(content, receiver: template_receiver).last
10650
+ anchor ||= gemspec_assignment_records(content, receiver: template_receiver).find { |record| record.fetch(:field) == "homepage" }
10651
+ return content unless anchor
10652
+
10653
+ insert_lines_after(content, anchor.fetch(:end_line), insertion)
10654
+ end
10655
+
10530
10656
  def gemspec_metadata_assignment_records(content, receiver:)
10531
10657
  lines = content.to_s.lines
10532
10658
  ruby_call_records(content, :[]=).filter_map do |call|
@@ -10540,6 +10666,7 @@ module Kettle
10540
10666
  end_line = ruby_node_source_end_line(call)
10541
10667
  {
10542
10668
  key: key,
10669
+ value: ruby_static_string_value(args[1]),
10543
10670
  start_line: start_line,
10544
10671
  end_line: end_line,
10545
10672
  source: lines[(start_line - 1)..(end_line - 1)].to_a.join
@@ -10549,6 +10676,10 @@ module Kettle
10549
10676
  []
10550
10677
  end
10551
10678
 
10679
+ def default_gemspec_metadata_assignment?(record)
10680
+ DEFAULT_GEMSPEC_METADATA_VALUES[record.fetch(:key)] == record[:value]
10681
+ end
10682
+
10552
10683
  def remove_gemspec_version_gem_dependency_when_disabled(content, facts, receiver:, template_declares_version_gem: false)
10553
10684
  return content if version_gem_enabled?(facts)
10554
10685
  return content if template_declares_version_gem && !version_gem_explicitly_disabled?(facts) && version_gem_runtime_compatible?(facts)
@@ -12576,7 +12707,9 @@ module Kettle
12576
12707
  def add_monorepo_subgem_file_overrides(content, gemspec_path, profile = MONOREPO_SUBGEM_TEMPLATE_PROFILE)
12577
12708
  override_lines = [
12578
12709
  " README.md:",
12579
- " strategy: merge"
12710
+ " strategy: merge",
12711
+ " Rakefile:",
12712
+ " strategy: accept_template"
12580
12713
  ]
12581
12714
  gemspec = gemspec_path.to_s.strip
12582
12715
  unless gemspec.empty?
@@ -13768,6 +13901,9 @@ module Kettle
13768
13901
  "KJ|MIN_RUBY" => minimum_ruby_token(rubygems[:min_ruby]),
13769
13902
  "KJ|MIN_DEV_RUBY" => facts.dig(:project_runtime, :test_min_ruby).to_s,
13770
13903
  "KJ|MIN_TEST_RUBY" => facts.dig(:project_runtime, :test_min_ruby).to_s,
13904
+ "KJ|KETTLE_CHANGELOG_GEMFILE_DEPENDENCY" => kettle_changelog_gemfile_dependency_token(
13905
+ package.fetch(:name).to_s
13906
+ ),
13771
13907
  "KJ|CI:EXEC_CMD" => facts.dig(:ci, :exec_cmd).to_s,
13772
13908
  "KJ|GITHUB_ACTIONS:COVERAGE_UPLOAD_STEPS" => github_actions_coverage_steps(disabled_integrations: facts.dig(:integrations, :disabled))
13773
13909
  }.merge(
@@ -13806,6 +13942,28 @@ module Kettle
13806
13942
  tokens.reject { |key, value| value.empty? && !EMPTY_TEMPLATE_TOKENS.include?(key) }
13807
13943
  end
13808
13944
 
13945
+ def kettle_changelog_gemfile_dependency_token(package_name)
13946
+ return "" if package_name == "kettle-changelog"
13947
+
13948
+ <<~RUBY.chomp
13949
+ kettle_changelog_local = ENV.fetch("KETTLE_DEV_DEV", "false").downcase
13950
+ kettle_changelog_local = !%w[false 0 no off].include?(kettle_changelog_local)
13951
+ if kettle_changelog_local
13952
+ require "nomono/bundler"
13953
+ eval_nomono_gems(
13954
+ gems: ["kettle-changelog"],
13955
+ prefix: "KETTLE_DEV",
13956
+ path_env: "KETTLE_DEV_DEV",
13957
+ root: ["src", "my", "kettle-dev"]
13958
+ )
13959
+ else
13960
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("4.0.0")
13961
+ gem "kettle-changelog", "~> 1.0", ">= 1.0.0"
13962
+ end
13963
+ end
13964
+ RUBY
13965
+ end
13966
+
13809
13967
  def readme_title_token(package, rubygems)
13810
13968
  package_name = package.fetch(:name).to_s.strip
13811
13969
  default_entrypoint = package_name.tr("-", "/")
@@ -14760,7 +14918,7 @@ module Kettle
14760
14918
  def main_gemfile_kettle_family_gem(package_name)
14761
14919
  return "" if package_name.to_s == "kettle-family"
14762
14920
 
14763
- %(gem "kettle-family", "~> 1.2", ">= 1.2.41"\n)
14921
+ %(gem "kettle-family", "~> 1.2", ">= 1.2.44"\n)
14764
14922
  end
14765
14923
 
14766
14924
  def main_gemfile_nomono_bootstrap(package_name)
@@ -15870,8 +16028,10 @@ module Kettle
15870
16028
  topology = normalize_repository_topology(repository_topology)
15871
16029
  monorepo_subproject = topology == REPOSITORY_TOPOLOGY_MONOREPO_SUBPROJECT
15872
16030
  local_root = monorepo_subproject ? git_worktree_root(project_root) : nil
16031
+ repository_root = local_root || project_root
16032
+ git_source_url = git_remote_source_url(repository_root)
15873
16033
  repo_url = if monorepo_subproject
15874
- repository_root_url(git_remote_source_url(local_root || project_root) || source_url)
16034
+ repository_root_url(git_source_url || source_url)
15875
16035
  else
15876
16036
  repository_root_url(source_url)
15877
16037
  end
@@ -15883,7 +16043,8 @@ module Kettle
15883
16043
  topology: topology,
15884
16044
  url: repo_url,
15885
16045
  name: repo_name,
15886
- slug: slug
16046
+ slug: slug,
16047
+ star_history: readme_star_history_facts(repository_root, git_source_url)
15887
16048
  )
15888
16049
  return facts unless monorepo_subproject
15889
16050
 
@@ -16030,6 +16191,54 @@ module Kettle
16030
16191
  nil
16031
16192
  end
16032
16193
 
16194
+ def readme_star_history_facts(project_root, git_source_url)
16195
+ repository_slug = github_repository_slug(git_source_url)
16196
+ return {enabled: false, reason: "no_github_remote"} if repository_slug.to_s.empty?
16197
+
16198
+ stars = github_repository_star_count(project_root, repository_slug)
16199
+ unless stars
16200
+ return {
16201
+ enabled: false,
16202
+ repository: repository_slug,
16203
+ reason: "star_count_unavailable"
16204
+ }
16205
+ end
16206
+
16207
+ {
16208
+ enabled: stars >= README_STAR_HISTORY_MIN_STARS,
16209
+ repository: repository_slug,
16210
+ stars: stars,
16211
+ minimum_stars: README_STAR_HISTORY_MIN_STARS
16212
+ }
16213
+ end
16214
+
16215
+ def github_repository_slug(url)
16216
+ normalized = normalize_git_source_url(url)
16217
+ match = normalized.to_s.match(%r{\Ahttps?://github\.com/([^/]+)/([^/?#]+)})
16218
+ return unless match
16219
+
16220
+ repository = match[2].delete_suffix(".git")
16221
+ return if match[1].empty? || repository.empty?
16222
+
16223
+ "#{match[1]}/#{repository}"
16224
+ end
16225
+
16226
+ def github_repository_star_count(project_root, repository_slug)
16227
+ stdout, _stderr, status = Open3.capture3(
16228
+ "gh",
16229
+ "api",
16230
+ "repos/#{repository_slug}",
16231
+ "--jq",
16232
+ ".stargazers_count",
16233
+ chdir: project_root.to_s
16234
+ )
16235
+ return unless status.success?
16236
+
16237
+ Integer(stdout.to_s.strip)
16238
+ rescue ArgumentError, IOError, SystemCallError
16239
+ nil
16240
+ end
16241
+
16033
16242
  def normalize_git_source_url(url)
16034
16243
  value = url.to_s.strip
16035
16244
  return if value.empty?
@@ -16040,6 +16249,11 @@ module Kettle
16040
16249
  end
16041
16250
 
16042
16251
  uri = URI.parse(value)
16252
+ if uri.scheme == "ssh" && uri.host == "github.com"
16253
+ slug = uri.path.to_s.delete_prefix("/").delete_suffix(".git")
16254
+ return "https://github.com/#{slug}" if slug.split("/").length >= 2
16255
+ end
16256
+
16043
16257
  if %w[http https].include?(uri.scheme) && uri.host == "github.com"
16044
16258
  slug = uri.path.to_s.delete_prefix("/").delete_suffix(".git")
16045
16259
  return "https://github.com/#{slug}" if slug.split("/").length >= 2
@@ -17614,7 +17828,7 @@ module Kettle
17614
17828
  relative_path = path.delete_prefix("#{project_root}/")
17615
17829
  next unless preferred_template_source(PACKAGED_TEMPLATE_ROOT, relative_path)
17616
17830
 
17617
- {target_path: relative_path} if skip_packaged_gemfile_template?(relative_path, config)
17831
+ {target_path: relative_path} if skip_packaged_gemfile_template?(relative_path, config, project_root: project_root)
17618
17832
  end
17619
17833
  (gemfile_cleanups + disabled_integration_config_cleanups(project_root, config)).sort_by { |cleanup| cleanup.fetch(:target_path) }
17620
17834
  end
@@ -17697,7 +17911,7 @@ module Kettle
17697
17911
  return if source_path.to_s.empty? || target_path.to_s.empty?
17698
17912
  return if skip_packaged_workflow_template?(target_path, config, include_patterns: include_patterns)
17699
17913
  return if skip_disabled_integration_template?(target_path, config)
17700
- return if skip_packaged_gemfile_template?(target_path, config)
17914
+ return if skip_packaged_gemfile_template?(target_path, config, project_root: project_root, template_root_path: template_root.fetch(:path))
17701
17915
  return if skip_packaged_license_template?(target_path, config)
17702
17916
  return if skip_packaged_version_gem_entrypoint_template?(project_root, source_path, target_path, config)
17703
17917
  return if template_root.fetch(:kind) == "packaged" && opencollective_disabled && opencollective_disabled_file?(target_path)
@@ -17933,9 +18147,11 @@ module Kettle
17933
18147
  Gem::Version.new(version) < min_ruby
17934
18148
  end
17935
18149
 
17936
- def skip_packaged_gemfile_template?(target_path, config)
18150
+ def skip_packaged_gemfile_template?(target_path, config, project_root: nil, template_root_path: PACKAGED_TEMPLATE_ROOT)
17937
18151
  return true if target_path.to_s.include?("gemfiles/modular/recording/") && !appraisal_recording_enabled?(config)
17938
18152
 
18153
+ return false if packaged_gemfile_referenced_by_x_std_libs?(target_path, project_root: project_root, template_root_path: template_root_path)
18154
+
17939
18155
  version = packaged_gemfile_template_ruby_floor(target_path)
17940
18156
  return false unless version
17941
18157
 
@@ -17945,6 +18161,21 @@ module Kettle
17945
18161
  Gem::Version.new(version) < min_ruby
17946
18162
  end
17947
18163
 
18164
+ def packaged_gemfile_referenced_by_x_std_libs?(target_path, project_root:, template_root_path:)
18165
+ relative_path = target_path.to_s.delete_prefix("gemfiles/modular/")
18166
+ return false unless relative_path.start_with?("x_std_libs/")
18167
+
18168
+ aggregate_paths = [
18169
+ File.join(template_root_path.to_s, "gemfiles/modular/x_std_libs.gemfile.example"),
18170
+ File.join(project_root.to_s, "gemfiles/modular/x_std_libs.gemfile")
18171
+ ].select { |path| File.file?(path) }
18172
+ aggregate_paths.any? do |path|
18173
+ gemfile_eval_paths(File.read(path)).include?(relative_path)
18174
+ end
18175
+ rescue
18176
+ false
18177
+ end
18178
+
17948
18179
  def skip_disabled_integration_template?(target_path, config)
17949
18180
  disabled_integration_template_path?(target_path, config)
17950
18181
  end
data.tar.gz.sig CHANGED
Binary file