gem_hadar 1.24.0 → 1.25.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ad8ef3c017e74aa89e444380b3017ec092bf53c2cc8020402a57d3e847f78f5a
4
- data.tar.gz: 89e9769d1c6935ac1213aa430cf39222ea1040b7d4a30085fcfa4c861a5bf53e
3
+ metadata.gz: 5277b0542113dc8de861927c702b9a17c0dc30fc000b0aad88f77559177bd562
4
+ data.tar.gz: 32cfd43ba8dd14a74fd0db9cfba009851866f22bb78decd0dd6cbdd0f3cb9b62
5
5
  SHA512:
6
- metadata.gz: dc28e7d7d4c9acc70d7bdc6e5c59e775d55cce975d39e82f1d919af6c90a3f8114a9ca665031736f899ab857ebbd7746ea5abd0cf41c2b99ae34602f19274ff6
7
- data.tar.gz: 9f4e9c24186ae498b86c741eb6f5afe4e80c36cb8dbff28dbfbc9e789ef4da5d07f92b8bbce9569baaa916cc97c91621c8ffd5810a24b6a48c5b93e3fd477ac4
6
+ metadata.gz: a77a1a309790aac939d7aff2f3973c495baa92a3d36e3443747e7243aa0a6e09781a7162ddde5e36868316b85db3ab58c20bcb3f137b818dc5f458ed3b741fd1
7
+ data.tar.gz: 8754d4b122caf5a5df4af137097440e84a4841f8c0b83fec7e635716997c59cbba36671e6b6b03230dbe1bceb319e131fbfb9c2734a155c8d5771692bfe31289
data/Rakefile CHANGED
@@ -18,6 +18,7 @@ GemHadar do
18
18
  dependency 'tins', '~> 1.0'
19
19
  dependency 'term-ansicolor', '~> 1.0'
20
20
  dependency 'ollama-ruby', '~> 1.0'
21
+ dependency 'mize'
21
22
  dependency 'rake'
22
23
  dependency 'yard'
23
24
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.24.0
1
+ 1.25.0
data/gem_hadar.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: gem_hadar 1.24.0 ruby lib
2
+ # stub: gem_hadar 1.25.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "gem_hadar".freeze
6
- s.version = "1.24.0".freeze
6
+ s.version = "1.25.0".freeze
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
@@ -12,8 +12,8 @@ Gem::Specification.new do |s|
12
12
  s.description = "This library contains some useful functionality to support the development of Ruby Gems".freeze
13
13
  s.email = "flori@ping.de".freeze
14
14
  s.executables = ["gem_hadar".freeze]
15
- s.extra_rdoc_files = ["README.md".freeze, "lib/gem_hadar.rb".freeze, "lib/gem_hadar/github.rb".freeze, "lib/gem_hadar/setup.rb".freeze, "lib/gem_hadar/template_compiler.rb".freeze, "lib/gem_hadar/version.rb".freeze]
16
- s.files = [".gitignore".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "VERSION".freeze, "bin/gem_hadar".freeze, "gem_hadar.gemspec".freeze, "lib/gem_hadar.rb".freeze, "lib/gem_hadar/github.rb".freeze, "lib/gem_hadar/setup.rb".freeze, "lib/gem_hadar/template_compiler.rb".freeze, "lib/gem_hadar/version.rb".freeze]
15
+ s.extra_rdoc_files = ["README.md".freeze, "lib/gem_hadar.rb".freeze, "lib/gem_hadar/github.rb".freeze, "lib/gem_hadar/prompt_template.rb".freeze, "lib/gem_hadar/setup.rb".freeze, "lib/gem_hadar/template_compiler.rb".freeze, "lib/gem_hadar/utils.rb".freeze, "lib/gem_hadar/version.rb".freeze]
16
+ s.files = [".gitignore".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "VERSION".freeze, "bin/gem_hadar".freeze, "gem_hadar.gemspec".freeze, "lib/gem_hadar.rb".freeze, "lib/gem_hadar/github.rb".freeze, "lib/gem_hadar/prompt_template.rb".freeze, "lib/gem_hadar/setup.rb".freeze, "lib/gem_hadar/template_compiler.rb".freeze, "lib/gem_hadar/utils.rb".freeze, "lib/gem_hadar/version.rb".freeze]
17
17
  s.homepage = "https://github.com/flori/gem_hadar".freeze
18
18
  s.licenses = ["MIT".freeze]
19
19
  s.rdoc_options = ["--title".freeze, "GemHadar - Library for the development of Ruby Gems".freeze, "--main".freeze, "README.md".freeze]
@@ -22,10 +22,11 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.specification_version = 4
24
24
 
25
- s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 1.23".freeze])
25
+ s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 1.24".freeze])
26
26
  s.add_runtime_dependency(%q<tins>.freeze, ["~> 1.0".freeze])
27
27
  s.add_runtime_dependency(%q<term-ansicolor>.freeze, ["~> 1.0".freeze])
28
28
  s.add_runtime_dependency(%q<ollama-ruby>.freeze, ["~> 1.0".freeze])
29
+ s.add_runtime_dependency(%q<mize>.freeze, [">= 0".freeze])
29
30
  s.add_runtime_dependency(%q<rake>.freeze, [">= 0".freeze])
30
31
  s.add_runtime_dependency(%q<yard>.freeze, [">= 0".freeze])
31
32
  end
@@ -0,0 +1,54 @@
1
+ module GemHadar::PromptTemplate
2
+ def default_git_release_system_prompt
3
+ <<~EOT
4
+ You are a Ruby programmer generating changelog messages in markdown
5
+ format for new releases, so users can see what has changed. Remember you
6
+ are not a chatbot of any kind.
7
+ EOT
8
+ end
9
+
10
+ def default_git_release_prompt
11
+ <<~EOT
12
+ Output the content of a changelog for the new release of %{name} %{version}
13
+
14
+ **Strictly** follow these guidelines:
15
+
16
+ - Use bullet points in markdown format (`-`) to list significant changes.
17
+ - Exclude trivial updates such as:
18
+ * Version number increments
19
+ * Dependency version bumps (unless they resolve critical issues)
20
+ * Minor code style adjustments
21
+ * Internal documentation tweaks
22
+ - Include only verified and substantial changes that impact
23
+ functionality, performance, or user experience.
24
+ - If unsure about a change's significance, omit it from the output.
25
+ - Avoid adding any comments or notes; keep the output purely factual.
26
+
27
+ These are the log messages including patches for the new release:
28
+
29
+ %{log_diff}
30
+ EOT
31
+ end
32
+
33
+ def default_version_bump_system_prompt
34
+ <<~EOT
35
+ You are an expert at semantic versioning. Analyze the provided changes
36
+ and suggest whether to bump major, minor, or build version according to
37
+ Semantic Versioning. Provide a brief explanation of your reasoning,
38
+ followed by a single line containing only one word: 'major', 'minor', or
39
+ 'build'.
40
+ EOT
41
+ end
42
+
43
+ def default_version_bump_prompt
44
+ <<~EOT
45
+ Given the current version %{version} and the following changes:
46
+
47
+ %{log_diff}
48
+
49
+ Please explain your reasoning for suggesting a version bump and then end
50
+ with a single line containing only one word: 'major', 'minor', or
51
+ 'build'.
52
+ EOT
53
+ end
54
+ end
@@ -0,0 +1,18 @@
1
+ module GemHadar::Utils
2
+ def xdg_config_filename(name)
3
+ if xdg = ENV['XDG_CONFIG_HOME'].full?
4
+ File.join(xdg, name)
5
+ else
6
+ File.join(ENV.fetch('HOME'), '.config', name)
7
+ end
8
+ end
9
+
10
+ memoize method:
11
+ def xdg_config(name, default)
12
+ if File.exist?(xdg_config_filename(name))
13
+ File.read(xdg_config_filename(name))
14
+ else
15
+ default
16
+ end
17
+ end
18
+ end
@@ -1,6 +1,6 @@
1
1
  class GemHadar
2
2
  # GemHadar version
3
- VERSION = '1.24.0'
3
+ VERSION = '1.25.0'
4
4
  VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
data/lib/gem_hadar.rb CHANGED
@@ -25,12 +25,16 @@ require_maybe 'rspec/core/rake_task'
25
25
  class GemHadar
26
26
  end
27
27
  require 'gem_hadar/version'
28
+ require 'gem_hadar/utils'
28
29
  require 'gem_hadar/setup'
29
30
  require 'gem_hadar/template_compiler'
30
31
  require 'gem_hadar/github'
32
+ require 'gem_hadar/prompt_template'
31
33
 
32
34
  class GemHadar
33
35
  include Term::ANSIColor
36
+ include GemHadar::Utils
37
+ include GemHadar::PromptTemplate
34
38
 
35
39
  if defined?(::RbConfig)
36
40
  include ::RbConfig
@@ -338,10 +342,7 @@ class GemHadar
338
342
 
339
343
  desc "Displaying the diff from env var VERSION to the next version or HEAD"
340
344
  task :diff do
341
- version_tags = versions.map { version_tag(_1) } + %w[ HEAD ]
342
- found_version_tag = version_tags.index(version_tag(version))
343
- found_version_tag.nil? and fail "cannot find version tag #{version_tag(version)}"
344
- start_version, end_version = version_tags[found_version_tag, 2]
345
+ start_version, end_version = determine_version_range
345
346
  puts color(172) { "Showing diff from version %s to %s:" % [ start_version, end_version ] }
346
347
  puts `git diff --color=always #{start_version}..#{end_version}`
347
348
  end
@@ -459,23 +460,40 @@ class GemHadar
459
460
  namespace :bump do
460
461
  desc 'Bump major version'
461
462
  task :major do
462
- version = File.read('VERSION').chomp.version
463
- version.bump(:major)
464
- secure_write('VERSION') { |v| v.puts version }
463
+ version_bump_to(:major)
465
464
  end
466
465
 
467
466
  desc 'Bump minor version'
468
467
  task :minor do
469
- version = File.read('VERSION').chomp.version
470
- version.bump(:minor)
471
- secure_write('VERSION') { |v| v.puts version }
468
+ version_bump_to(:minor)
472
469
  end
473
470
 
474
471
  desc 'Bump build version'
475
472
  task :build do
476
- version = File.read('VERSION').chomp.version
477
- version.bump(:build)
478
- secure_write('VERSION') { |v| v.puts version }
473
+ version_bump_to(:build)
474
+ end
475
+ end
476
+
477
+ desc 'Bump version with suggestion'
478
+ task :bump do
479
+ log_diff = version_log_diff(from_version: nil, to_version: 'HEAD')
480
+ system = xdg_config('version_bump_system_prompt.txt', default_version_bump_system_prompt)
481
+ prompt = xdg_config('version_bump_prompt.txt', default_version_bump_prompt) % { version:, log_diff: }
482
+ response = ollama_generate(system:, prompt:)
483
+ puts response
484
+ default = nil
485
+ if response =~ /(major|minor|build)\s*$/
486
+ default = $1
487
+ end
488
+ response = ask?(
489
+ 'Bump a major, minor, or build version%{default}? ',
490
+ /\A(major|minor|build)\z/,
491
+ default:
492
+ )
493
+ if version_type = response&.[](1)
494
+ version_bump_to(version_type)
495
+ else
496
+ exit 1
479
497
  end
480
498
  end
481
499
  end
@@ -595,43 +613,11 @@ class GemHadar
595
613
  end
596
614
  end
597
615
 
598
- def create_body
599
- base_url = ENV['OLLAMA_URL']
600
- if base_url.blank? && host = ENV['OLLAMA_HOST'].full?
601
- base_url = 'http://%s' % host
602
- end
603
- base_url.present? or return
616
+ def create_git_release_body
604
617
  log_diff = version_log_diff(to_version: version)
605
- model = ENV.fetch('OLLAMA_MODEL', 'llama3.1')
606
- ollama = Ollama::Client.new(base_url:, read_timeout: 600, connect_timeout: 60)
607
- system = <<~EOT
608
- You are a Ruby programmer generating changelog messages in markdown
609
- format for new releases, so users can see what has changed. Remember you
610
- are not a chatbot of any kind.
611
- EOT
612
- prompt = (<<~EOT) % { name:, version:, log_diff: }
613
- Output the content of a changelog for the new release of %{name} %{version}
614
-
615
- **Strictly** follow these guidelines:
616
-
617
- - Use bullet points in markdown format (`-`) to list significant changes.
618
- - Exclude trivial updates such as:
619
- * Version number increments
620
- * Dependency version bumps (unless they resolve critical issues)
621
- * Minor code style adjustments
622
- * Internal documentation tweaks
623
- - Include only verified and substantial changes that impact
624
- functionality, performance, or user experience.
625
- - If unsure about a change's significance, omit it from the output.
626
- - Avoid adding any comments or notes; keep the output purely factual.
627
-
628
- These are the log messages including patches for the new release:
629
-
630
- %{log_diff}
631
- EOT
632
- options = ENV['OLLAMA_OPTIONS'].full? { |o| JSON.parse(o) } || {}
633
- options |= { "temperature" => 0, "top_p" => 1, "min_p" => 0.1 }
634
- ollama.generate(model:, system:, prompt:, options:, stream: false, think: false).response
618
+ system = xdg_config('release_system_prompt.txt', default_git_release_system_prompt)
619
+ prompt = xdg_config('release_prompt.txt', default_git_release_prompt) % { name:, version:, log_diff: }
620
+ ollama_generate(system:, prompt:)
635
621
  end
636
622
 
637
623
  def edit_temp_file(content)
@@ -675,7 +661,7 @@ class GemHadar
675
661
  rc = GitHub::ReleaseCreator.new(owner:, repo:, token: github_api_token)
676
662
  tag_name = version_tag(version)
677
663
  target_commitish = `git show -s --format=%H #{tag_name.inspect}^{commit}`.chomp
678
- body = edit_temp_file(create_body)
664
+ body = edit_temp_file(create_git_release_body)
679
665
  if body.present?
680
666
  begin
681
667
  response = rc.perform(tag_name:, target_commitish:, body:)
@@ -812,6 +798,52 @@ class GemHadar
812
798
  self
813
799
  end
814
800
 
801
+ # Generates a response from an AI model using the Ollama::Client.
802
+ #
803
+ # @param [String] system The system prompt for the AI model.
804
+ # @param [String] prompt The user prompt to generate a response to.
805
+ # @return [String, nil] The generated response or nil if generation fails.
806
+ def ollama_generate(system:, prompt:)
807
+ base_url = ENV['OLLAMA_URL']
808
+ if base_url.blank? && host = ENV['OLLAMA_HOST'].full?
809
+ base_url = 'http://%s' % host
810
+ end
811
+ base_url.present? or return
812
+ ollama = Ollama::Client.new(base_url:, read_timeout: 600, connect_timeout: 60)
813
+ model = ENV.fetch('OLLAMA_MODEL', 'llama3.1')
814
+ options = ENV['OLLAMA_OPTIONS'].full? { |o| JSON.parse(o) } || {}
815
+ options |= { "temperature" => 0, "top_p" => 1, "min_p" => 0.1 }
816
+ ollama.generate(model:, system:, prompt:, options:, stream: false, think: false).response
817
+ end
818
+
819
+ # Increases the specified part of the version number and writes it back to
820
+ # the VERSION file.
821
+ #
822
+ # @param [Symbol, String] type The part of the version to bump (:major, :minor, or :build)
823
+ def version_bump_to(type)
824
+ type = type.to_sym
825
+ version = File.read('VERSION').chomp.version
826
+ version.bump(type)
827
+ secure_write('VERSION') { |v| v.puts version }
828
+ exit 0
829
+ end
830
+
831
+ # Determine the start and end versions for diff comparison.
832
+ #
833
+ # If the VERSION env var is set, it will be used as the starting version tag.
834
+ # Otherwise, it defaults to the current commit's version or the latest tag.
835
+ #
836
+ # @return [Array(String, String)] A fixed-size array containing:
837
+ # - The start version (e.g., '1.2.3') from which changes are compared.
838
+ # - The end version (e.g., '1.2.4' or 'HEAD') up to which changes are compared.
839
+ def determine_version_range
840
+ version_tags = versions.map { version_tag(_1) } + %w[ HEAD ]
841
+ found_version_tag = version_tags.index(version_tag(version))
842
+ found_version_tag.nil? and fail "cannot find version tag #{version_tag(version)}"
843
+ start_version, end_version = version_tags[found_version_tag, 2]
844
+ return start_version, end_version
845
+ end
846
+
815
847
  # The write_ignore_file method writes the current ignore_files configuration
816
848
  # to a .gitignore file in the project root directory.
817
849
  def write_ignore_file
@@ -934,12 +966,6 @@ class GemHadar
934
966
  end
935
967
  super(*args)
936
968
  end
937
- def fail(*args)
938
- args.map! do |a|
939
- a.respond_to?(:to_str) ? color(196) { a.to_str } : a
940
- end
941
- super(*args)
942
- end
943
969
 
944
970
  # The git_remotes method retrieves the list of remote repositories configured
945
971
  # for the current Git project.
@@ -999,19 +1025,28 @@ class GemHadar
999
1025
  #
1000
1026
  # @return [ Array<String> ] an array of version strings sorted in ascending
1001
1027
  # order according to semantic versioning rules.
1028
+ memoize method:
1002
1029
  def versions
1003
- @versions ||= `git tag`.lines.grep(/^v?\d+\.\d+\.\d+$/).map(&:chomp).map {
1030
+ `git tag`.lines.grep(/^v?\d+\.\d+\.\d+$/).map(&:chomp).map {
1004
1031
  _1.sub(/\Av/, '')
1005
1032
  }.sort_by(&:version)
1006
1033
  end
1007
1034
 
1008
1035
  # The version_tag method prepends a 'v' prefix to the given version
1009
- # string.
1036
+ # string, unless it's HEAD.
1010
1037
  #
1011
1038
  # @param version [String] the version string to modify
1012
1039
  # @return [String] the modified version string with a 'v' prefix
1013
1040
  def version_tag(version)
1014
- version.dup.prepend ?v
1041
+ if version != 'HEAD'
1042
+ version.dup.prepend ?v
1043
+ else
1044
+ version.dup
1045
+ end
1046
+ end
1047
+
1048
+ def version_untag(version_tag)
1049
+ version.sub(/\Av/, '')
1015
1050
  end
1016
1051
 
1017
1052
  # The github_remote_url method retrieves and parses the GitHub remote URL
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gem_hadar
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.24.0
4
+ version: 1.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '1.23'
18
+ version: '1.24'
19
19
  type: :development
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: '1.23'
25
+ version: '1.24'
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: tins
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -65,6 +65,20 @@ dependencies:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
67
  version: '1.0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: mize
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
68
82
  - !ruby/object:Gem::Dependency
69
83
  name: rake
70
84
  requirement: !ruby/object:Gem::Requirement
@@ -103,8 +117,10 @@ extra_rdoc_files:
103
117
  - README.md
104
118
  - lib/gem_hadar.rb
105
119
  - lib/gem_hadar/github.rb
120
+ - lib/gem_hadar/prompt_template.rb
106
121
  - lib/gem_hadar/setup.rb
107
122
  - lib/gem_hadar/template_compiler.rb
123
+ - lib/gem_hadar/utils.rb
108
124
  - lib/gem_hadar/version.rb
109
125
  files:
110
126
  - ".gitignore"
@@ -117,8 +133,10 @@ files:
117
133
  - gem_hadar.gemspec
118
134
  - lib/gem_hadar.rb
119
135
  - lib/gem_hadar/github.rb
136
+ - lib/gem_hadar/prompt_template.rb
120
137
  - lib/gem_hadar/setup.rb
121
138
  - lib/gem_hadar/template_compiler.rb
139
+ - lib/gem_hadar/utils.rb
122
140
  - lib/gem_hadar/version.rb
123
141
  homepage: https://github.com/flori/gem_hadar
124
142
  licenses: