gem_hadar 1.20.0 → 1.21.1
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/Rakefile +1 -0
- data/VERSION +1 -1
- data/gem_hadar.gemspec +8 -7
- data/lib/gem_hadar/github.rb +62 -0
- data/lib/gem_hadar/setup.rb +41 -0
- data/lib/gem_hadar/template_compiler.rb +31 -0
- data/lib/gem_hadar/version.rb +1 -1
- data/lib/gem_hadar.rb +375 -191
- metadata +25 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b87e2b5371fa3f1260204c5d71a43d793516d5d734f7b3f0ef3846f696d8b98
|
4
|
+
data.tar.gz: 3ea0ff7dc2ea379f270716b8d46dda9fe7901ebaaadf1e76ee713324674fb262
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d0ca8414e965de5954624b7d2467317fe7dedff4578ea1f7ce8d6e7c9eb9c95693cc65907172dce03ed58678f0bdd0e2a961709e91154d3e3a92a95cfa530bca
|
7
|
+
data.tar.gz: 492ed0f4757edf87d56f4b10074a76eff4220dc43b7f78e696bf7f1abfa1ebc986439aefc7de1825c893c1a98f7bbd4dc8c981873d92ecb7ce1e49e339858bc4
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.21.1
|
data/gem_hadar.gemspec
CHANGED
@@ -1,30 +1,31 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: gem_hadar 1.
|
2
|
+
# stub: gem_hadar 1.21.1 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "gem_hadar".freeze
|
6
|
-
s.version = "1.
|
6
|
+
s.version = "1.21.1".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]
|
10
10
|
s.authors = ["Florian Frank".freeze]
|
11
|
-
s.date = "
|
11
|
+
s.date = "1980-01-02"
|
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/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/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/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]
|
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]
|
20
|
-
s.rubygems_version = "3.6.
|
20
|
+
s.rubygems_version = "3.6.9".freeze
|
21
21
|
s.summary = "Library for the development of Ruby Gems".freeze
|
22
22
|
|
23
23
|
s.specification_version = 4
|
24
24
|
|
25
|
-
s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 1.
|
25
|
+
s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 1.21".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
|
+
s.add_runtime_dependency(%q<ollama-ruby>.freeze, ["~> 1.0".freeze])
|
28
29
|
s.add_runtime_dependency(%q<rake>.freeze, [">= 0".freeze])
|
29
30
|
s.add_runtime_dependency(%q<yard>.freeze, [">= 0".freeze])
|
30
31
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module GemHadar::GitHub
|
5
|
+
end
|
6
|
+
|
7
|
+
class GemHadar::GitHub::ReleaseCreator
|
8
|
+
class << self
|
9
|
+
attr_accessor :github_api_url
|
10
|
+
end
|
11
|
+
self.github_api_url = 'https://api.github.com'
|
12
|
+
|
13
|
+
def initialize(owner:, repo:, token:, api_version: '2022-11-28')
|
14
|
+
@owner = owner
|
15
|
+
@repo = repo
|
16
|
+
@token = token
|
17
|
+
@api_version = api_version
|
18
|
+
end
|
19
|
+
|
20
|
+
def perform(tag_name:, target_commitish:, body:, name: tag_name, draft: false, prerelease: false)
|
21
|
+
uri = URI("#{self.class.github_api_url}/repos/#{@owner}/#{@repo}/releases")
|
22
|
+
|
23
|
+
headers = {
|
24
|
+
"Accept" => "application/vnd.github+json",
|
25
|
+
"Authorization" => "Bearer #{@token}",
|
26
|
+
"X-GitHub-Api-Version" => @api_version
|
27
|
+
}
|
28
|
+
|
29
|
+
data = {
|
30
|
+
tag_name:,
|
31
|
+
target_commitish:,
|
32
|
+
body:,
|
33
|
+
name:,
|
34
|
+
draft:,
|
35
|
+
prerelease:,
|
36
|
+
}.compact
|
37
|
+
|
38
|
+
req = Net::HTTP::Post.new(uri.request_uri, headers)
|
39
|
+
req.body = JSON(data)
|
40
|
+
|
41
|
+
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
42
|
+
http.request(req)
|
43
|
+
end
|
44
|
+
|
45
|
+
case response
|
46
|
+
when Net::HTTPSuccess
|
47
|
+
JSON.parse(response.body, object_class: JSON::GenericObject)
|
48
|
+
else
|
49
|
+
error_data =
|
50
|
+
begin
|
51
|
+
JSON.pretty_generate(JSON.parse(response.body))
|
52
|
+
rescue
|
53
|
+
response.body
|
54
|
+
end
|
55
|
+
error_msg = "Failed to create release. Status: #{response.code}\n\n#{error_data}"
|
56
|
+
raise error_msg
|
57
|
+
end
|
58
|
+
rescue => e
|
59
|
+
warn "Error creating release: #{e.message}"
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class GemHadar::Setup
|
2
|
+
include FileUtils
|
3
|
+
|
4
|
+
def perform
|
5
|
+
mkdir_p 'lib'
|
6
|
+
unless File.exist?('VERSION')
|
7
|
+
File.open('VERSION', 'w') do |output|
|
8
|
+
output.puts '0.0.0'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
unless File.exist?('Rakefile')
|
12
|
+
File.open('Rakefile', 'w') do |output|
|
13
|
+
output.puts <<~EOT
|
14
|
+
# vim: set filetype=ruby et sw=2 ts=2:
|
15
|
+
|
16
|
+
require 'gem_hadar'
|
17
|
+
|
18
|
+
GemHadar do
|
19
|
+
#developing true
|
20
|
+
#name 'TODO'
|
21
|
+
module_type :class
|
22
|
+
#author 'TODO'
|
23
|
+
#email 'todo@example.com'
|
24
|
+
#homepage "https://github.com/TODO/NAME"
|
25
|
+
#summary 'TODO'
|
26
|
+
description 'TODO'
|
27
|
+
test_dir 'spec'
|
28
|
+
ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', '.AppleDouble', '.bundle', '.yardoc', 'tags'
|
29
|
+
readme 'README.md'
|
30
|
+
|
31
|
+
#executables << 'bin/TODO'
|
32
|
+
|
33
|
+
#dependency 'TODO', '~>1.2.3'
|
34
|
+
|
35
|
+
#licenses << 'TODO
|
36
|
+
end
|
37
|
+
EOT
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
class GemHadar::TemplateCompiler
|
4
|
+
include Tins::BlockSelf
|
5
|
+
include Tins::MethodMissingDelegator::DelegatorModule
|
6
|
+
|
7
|
+
def initialize(&block)
|
8
|
+
super block_self(&block)
|
9
|
+
@values = {}
|
10
|
+
instance_eval(&block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def compile(src, dst)
|
14
|
+
template = File.read(src)
|
15
|
+
File.open(dst, 'w') do |output|
|
16
|
+
erb = ERB.new(template, nil, '-')
|
17
|
+
erb.filename = src.to_s
|
18
|
+
output.write erb.result binding
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing(id, *a, &b)
|
23
|
+
if a.empty? && id && @values.key?(id)
|
24
|
+
@values[id]
|
25
|
+
elsif a.size == 1
|
26
|
+
@values[id] = a.first
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/gem_hadar/version.rb
CHANGED
data/lib/gem_hadar.rb
CHANGED
@@ -15,18 +15,19 @@ require 'rake/testtask'
|
|
15
15
|
require 'dslkit/polite'
|
16
16
|
require 'set'
|
17
17
|
require 'pathname'
|
18
|
-
require '
|
19
|
-
require 'gem_hadar/version'
|
18
|
+
require 'ollama'
|
20
19
|
require 'term/ansicolor'
|
21
20
|
require_maybe 'yard'
|
22
21
|
require_maybe 'simplecov'
|
23
22
|
require_maybe 'rubygems/package_task'
|
24
23
|
require_maybe 'rcov/rcovtask'
|
25
24
|
require_maybe 'rspec/core/rake_task'
|
26
|
-
|
27
|
-
def GemHadar(&block)
|
28
|
-
GemHadar.new(&block).create_all_tasks
|
25
|
+
class GemHadar
|
29
26
|
end
|
27
|
+
require 'gem_hadar/version'
|
28
|
+
require 'gem_hadar/setup'
|
29
|
+
require 'gem_hadar/template_compiler'
|
30
|
+
require 'gem_hadar/github'
|
30
31
|
|
31
32
|
class GemHadar
|
32
33
|
include Term::ANSIColor
|
@@ -50,18 +51,6 @@ class GemHadar
|
|
50
51
|
fail "#{self.class}: #{name} has to be set for gem"
|
51
52
|
end
|
52
53
|
|
53
|
-
def assert_valid_link(name, orig_url)
|
54
|
-
developing and return orig_url
|
55
|
-
url = orig_url
|
56
|
-
begin
|
57
|
-
response = Net::HTTP.get_response(URI.parse(url))
|
58
|
-
url = response['location']
|
59
|
-
end while response.is_a?(Net::HTTPRedirection)
|
60
|
-
response.is_a?(Net::HTTPOK) or
|
61
|
-
fail "#{orig_url.inspect} for #{name} has to be a valid link"
|
62
|
-
orig_url
|
63
|
-
end
|
64
|
-
|
65
54
|
dsl_accessor :developing, false
|
66
55
|
|
67
56
|
dsl_accessor :name do
|
@@ -214,7 +203,7 @@ class GemHadar
|
|
214
203
|
end
|
215
204
|
|
216
205
|
def install_library(&block)
|
217
|
-
@install_library_block =
|
206
|
+
@install_library_block = -> do
|
218
207
|
desc 'Install executable/library into site_ruby directories'
|
219
208
|
task :install => :prepare_install, &block
|
220
209
|
end
|
@@ -268,72 +257,22 @@ class GemHadar
|
|
268
257
|
end
|
269
258
|
end
|
270
259
|
|
271
|
-
def gem_files
|
272
|
-
(files.to_a - package_ignore_files.to_a)
|
273
|
-
end
|
274
|
-
|
275
|
-
def gemspec
|
276
|
-
Gem::Specification.new do |s|
|
277
|
-
s.name = name
|
278
|
-
s.version = ::Gem::Version.new(version)
|
279
|
-
s.author = author
|
280
|
-
s.email = email
|
281
|
-
s.homepage = assert_valid_link(:homepage, homepage)
|
282
|
-
s.summary = summary
|
283
|
-
s.description = description
|
284
|
-
|
285
|
-
gem_files.full? { |f| s.files = Array(f) }
|
286
|
-
test_files.full? { |t| s.test_files = Array(t) }
|
287
|
-
extensions.full? { |e| s.extensions = Array(e) }
|
288
|
-
bindir.full? { |b| s.bindir = b }
|
289
|
-
executables.full? { |e| s.executables = Array(e) }
|
290
|
-
licenses.full? { |l| s.licenses = Array(licenses) }
|
291
|
-
post_install_message.full? { |m| s.post_install_message = m }
|
292
|
-
|
293
|
-
required_ruby_version.full? { |v| s.required_ruby_version = v }
|
294
|
-
s.add_development_dependency('gem_hadar', "~> #{VERSION[/\A\d+\.\d+/, 0]}")
|
295
|
-
for d in @development_dependencies
|
296
|
-
s.add_development_dependency(*d)
|
297
|
-
end
|
298
|
-
for d in @dependencies
|
299
|
-
if s.respond_to?(:add_runtime_dependency)
|
300
|
-
s.add_runtime_dependency(*d)
|
301
|
-
else
|
302
|
-
s.add_dependency(*d)
|
303
|
-
end
|
304
|
-
end
|
305
|
-
|
306
|
-
require_paths.full? { |r| s.require_paths = Array(r) }
|
307
|
-
|
308
|
-
if title
|
309
|
-
s.rdoc_options << '--title' << title
|
310
|
-
else
|
311
|
-
s.rdoc_options << '--title' << "#{name.camelize} - #{summary}"
|
312
|
-
end
|
313
|
-
if readme
|
314
|
-
s.rdoc_options << '--main' << readme
|
315
|
-
s.extra_rdoc_files << readme
|
316
|
-
end
|
317
|
-
doc_files.full? { |df| s.extra_rdoc_files.concat Array(df) }
|
318
|
-
end
|
319
|
-
end
|
320
|
-
|
321
260
|
def version_task
|
322
261
|
desc m = "Writing version information for #{name}-#{version}"
|
323
262
|
task :version do
|
324
263
|
puts m
|
325
264
|
mkdir_p dir = File.join('lib', path_name)
|
326
265
|
secure_write(File.join(dir, 'version.rb')) do |v|
|
327
|
-
v.puts
|
328
|
-
#{module_type} #{path_module}
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
end
|
336
|
-
EOT
|
266
|
+
v.puts <<~EOT
|
267
|
+
#{module_type} #{path_module}
|
268
|
+
# #{path_module} version
|
269
|
+
VERSION = '#{version}'
|
270
|
+
VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
|
271
|
+
VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
|
272
|
+
VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
|
273
|
+
VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
|
274
|
+
end
|
275
|
+
EOT
|
337
276
|
version_epilogue.full? { |ve| v.puts ve }
|
338
277
|
end
|
339
278
|
end
|
@@ -357,10 +296,36 @@ EOT
|
|
357
296
|
end
|
358
297
|
end
|
359
298
|
|
360
|
-
def
|
361
|
-
|
362
|
-
|
363
|
-
|
299
|
+
def version_log_diff(to_version: 'HEAD', from_version: nil)
|
300
|
+
if to_version == 'HEAD'
|
301
|
+
if from_version.blank?
|
302
|
+
from_version = versions.last
|
303
|
+
else
|
304
|
+
unless versions.find { |v| v == from_version }
|
305
|
+
fail "Could not find #{from_version.inspect}."
|
306
|
+
end
|
307
|
+
end
|
308
|
+
`git log -p #{version_identifier(from_version)}..HEAD`
|
309
|
+
else
|
310
|
+
unless versions.find { |v| v == to_version }
|
311
|
+
fail "Could not find #{to_version.inspect}."
|
312
|
+
end
|
313
|
+
if from_version.blank?
|
314
|
+
from_version = versions.each_cons(2).find do |previous_version, v|
|
315
|
+
if v == to_version
|
316
|
+
break previous_version
|
317
|
+
end
|
318
|
+
end
|
319
|
+
unless from_version
|
320
|
+
fail "Could not find version before #{to_version.inspect}."
|
321
|
+
end
|
322
|
+
else
|
323
|
+
unless versions.find { |v| v == from_version }
|
324
|
+
fail "Could not find #{from_version.inspect}."
|
325
|
+
end
|
326
|
+
end
|
327
|
+
`git log -p #{version_identifier(from_version)}..#{version_identifier(to_version)}`
|
328
|
+
end
|
364
329
|
end
|
365
330
|
|
366
331
|
def version_diff_task
|
@@ -374,8 +339,8 @@ EOT
|
|
374
339
|
|
375
340
|
desc "Displaying the diff from env var VERSION to the next version or HEAD"
|
376
341
|
task :diff do
|
377
|
-
arg_version = ENV.fetch('VERSION', version)
|
378
|
-
my_versions = versions.map { _1
|
342
|
+
arg_version = version_identifier(ENV.fetch('VERSION', version))
|
343
|
+
my_versions = versions.map { version_identifier(_1) } + %w[ HEAD ]
|
379
344
|
start_version, end_version = my_versions[my_versions.index(arg_version), 2]
|
380
345
|
puts color(172) {"Showing diff from version %s to %s:" % [ start_version, end_version ]}
|
381
346
|
puts `git diff --color=always #{start_version}..#{end_version}`
|
@@ -489,41 +454,6 @@ EOT
|
|
489
454
|
end
|
490
455
|
end
|
491
456
|
|
492
|
-
def self.start_simplecov
|
493
|
-
defined? SimpleCov or return
|
494
|
-
filter = "#{File.basename(File.dirname(caller.first))}/"
|
495
|
-
SimpleCov.start do
|
496
|
-
add_filter filter
|
497
|
-
end
|
498
|
-
end
|
499
|
-
|
500
|
-
def write_ignore_file
|
501
|
-
secure_write('.gitignore') do |output|
|
502
|
-
output.puts(ignore.sort)
|
503
|
-
end
|
504
|
-
end
|
505
|
-
|
506
|
-
def write_gemfile
|
507
|
-
default_gemfile =<<EOT
|
508
|
-
# vim: set filetype=ruby et sw=2 ts=2:
|
509
|
-
|
510
|
-
source 'https://rubygems.org'
|
511
|
-
|
512
|
-
gemspec
|
513
|
-
EOT
|
514
|
-
current_gemfile = File.exist?('Gemfile') && File.read('Gemfile')
|
515
|
-
case current_gemfile
|
516
|
-
when false
|
517
|
-
secure_write('Gemfile') do |output|
|
518
|
-
output.write default_gemfile
|
519
|
-
end
|
520
|
-
when default_gemfile
|
521
|
-
;;
|
522
|
-
else
|
523
|
-
warn "INFO: Current Gemfile differs from default Gemfile."
|
524
|
-
end
|
525
|
-
end
|
526
|
-
|
527
457
|
def version_bump_task
|
528
458
|
namespace :version do
|
529
459
|
namespace :bump do
|
@@ -557,7 +487,7 @@ EOT
|
|
557
487
|
task :tag do
|
558
488
|
force = ENV['FORCE'].to_i == 1
|
559
489
|
begin
|
560
|
-
sh "git tag -a -m 'Version #{version}' #{'-f' if force}
|
490
|
+
sh "git tag -a -m 'Version #{version}' #{'-f' if force} #{version_identifier(version)}"
|
561
491
|
rescue RuntimeError
|
562
492
|
if `git diff v#{version}..HEAD`.empty?
|
563
493
|
puts "Version #{version} is already tagged, but it's no different"
|
@@ -579,12 +509,6 @@ EOT
|
|
579
509
|
ENV.fetch('GIT_REMOTE', 'origin').split(/\s+/).first
|
580
510
|
end
|
581
511
|
|
582
|
-
def git_remotes
|
583
|
-
remotes = ENV['GIT_REMOTE'].full?(:split, /\s+/)
|
584
|
-
remotes or remotes = `git remote`.lines.map(&:chomp)
|
585
|
-
remotes
|
586
|
-
end
|
587
|
-
|
588
512
|
def master_prepare_task
|
589
513
|
namespace :master do
|
590
514
|
desc "Prepare a remote git repository for this project"
|
@@ -671,12 +595,107 @@ EOT
|
|
671
595
|
end
|
672
596
|
end
|
673
597
|
|
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
|
604
|
+
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
|
635
|
+
end
|
636
|
+
|
637
|
+
def edit_temp_file(content)
|
638
|
+
editor = ENV.fetch('EDITOR', `which vi`.chomp)
|
639
|
+
unless File.exist?(editor)
|
640
|
+
warn "Can't find EDITOR. => Returning."
|
641
|
+
return
|
642
|
+
end
|
643
|
+
temp_file = Tempfile.new('changelog')
|
644
|
+
temp_file.write(content)
|
645
|
+
temp_file.close
|
646
|
+
|
647
|
+
unless system("#{editor} #{temp_file.path}")
|
648
|
+
warn "#{editor} returned #{$?.exitstatus} => Returning."
|
649
|
+
return
|
650
|
+
end
|
651
|
+
|
652
|
+
File.read(temp_file.path)
|
653
|
+
ensure
|
654
|
+
temp_file&.close&.unlink
|
655
|
+
end
|
656
|
+
|
657
|
+
def github_release_task
|
658
|
+
namespace :github do
|
659
|
+
unless github_api_token = ENV['GITHUB_API_TOKEN'].full?
|
660
|
+
warn "GITHUB_API_TOKEN not set. => Skipping github release task."
|
661
|
+
task :release
|
662
|
+
return
|
663
|
+
end
|
664
|
+
desc "Create a new GitHub release for the current version with a changelog"
|
665
|
+
task :release do
|
666
|
+
yes = ask?(
|
667
|
+
"Do you want to publish a release message on github? (y/n%{default}) ",
|
668
|
+
/\Ay/i, default: ENV['GITHUB_RELEASE_ENABLED']
|
669
|
+
)
|
670
|
+
unless yes
|
671
|
+
warn "Skipping publication of a github release message."
|
672
|
+
next
|
673
|
+
end
|
674
|
+
if %r(\A/*(?<owner>[^/]+)/(?<repo>[^/.]+)) =~ github_remote_url&.path
|
675
|
+
rc = GitHub::ReleaseCreator.new(owner:, repo:, token: github_api_token)
|
676
|
+
tag_name = version_identifier(version)
|
677
|
+
target_commitish = `git rev-parse #{tag_name.inspect}`.chomp
|
678
|
+
body = edit_temp_file(create_body)
|
679
|
+
if body.present?
|
680
|
+
response = rc.perform(tag_name:, target_commitish:, body:)
|
681
|
+
puts "Release created successfully! See #{response['html_url']}"
|
682
|
+
else
|
683
|
+
warn "Skipping creation of github release message."
|
684
|
+
end
|
685
|
+
else
|
686
|
+
warn "Could not derive github remote url from git remotes. => Skipping github release task."
|
687
|
+
end
|
688
|
+
end
|
689
|
+
end
|
690
|
+
end
|
691
|
+
|
674
692
|
def push_task
|
675
693
|
master_prepare_task
|
676
694
|
version_push_task
|
677
695
|
master_push_task
|
678
696
|
gem_push_task
|
679
697
|
git_remotes_task
|
698
|
+
github_release_task
|
680
699
|
task :modified do
|
681
700
|
changed_files = `git status --porcelain`.gsub(/^\s*\S\s+/, '').lines
|
682
701
|
unless changed_files.empty?
|
@@ -685,7 +704,7 @@ EOT
|
|
685
704
|
end
|
686
705
|
end
|
687
706
|
desc "Push master and version #{version} all git remotes: #{git_remotes * ' '}"
|
688
|
-
task :push => %i[ modified build master:push version:push gem:push ]
|
707
|
+
task :push => %i[ modified build master:push version:push gem:push github:release ]
|
689
708
|
end
|
690
709
|
|
691
710
|
def compile_task
|
@@ -709,11 +728,11 @@ EOT
|
|
709
728
|
desc 'Create .rvmrc file'
|
710
729
|
task :rvm do
|
711
730
|
secure_write('.rvmrc') do |output|
|
712
|
-
output.write
|
713
|
-
rvm use #{rvm.use}
|
714
|
-
rvm gemset create #{rvm.gemset}
|
715
|
-
rvm gemset use #{rvm.gemset}
|
716
|
-
EOT
|
731
|
+
output.write <<~EOT
|
732
|
+
rvm use #{rvm.use}
|
733
|
+
rvm gemset create #{rvm.gemset}
|
734
|
+
rvm gemset use #{rvm.gemset}
|
735
|
+
EOT
|
717
736
|
end
|
718
737
|
end
|
719
738
|
end
|
@@ -750,14 +769,10 @@ EOT
|
|
750
769
|
task :yard => %i[ yard:private yard:view ]
|
751
770
|
end
|
752
771
|
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
$~
|
758
|
-
end
|
759
|
-
end
|
760
|
-
|
772
|
+
# The create_all_tasks method sets up and registers all the Rake tasks for
|
773
|
+
# the gem project.
|
774
|
+
#
|
775
|
+
# @return [GemHadar] the instance of GemHadar
|
761
776
|
def create_all_tasks
|
762
777
|
default_task
|
763
778
|
build_task
|
@@ -791,77 +806,246 @@ EOT
|
|
791
806
|
self
|
792
807
|
end
|
793
808
|
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
super block_self(&block)
|
800
|
-
@values = {}
|
801
|
-
instance_eval(&block)
|
809
|
+
# The write_ignore_file method writes the current ignore_files configuration
|
810
|
+
# to a .gitignore file in the project root directory.
|
811
|
+
def write_ignore_file
|
812
|
+
secure_write('.gitignore') do |output|
|
813
|
+
output.puts(ignore.sort)
|
802
814
|
end
|
815
|
+
end
|
816
|
+
|
817
|
+
# The write_gemfile method creates and writes the default Gemfile content if
|
818
|
+
# it doesn't exist. If a custom Gemfile exists, it only displays a warning.
|
819
|
+
def write_gemfile
|
820
|
+
default_gemfile =<<~EOT
|
821
|
+
# vim: set filetype=ruby et sw=2 ts=2:
|
803
822
|
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
823
|
+
source 'https://rubygems.org'
|
824
|
+
|
825
|
+
gemspec
|
826
|
+
EOT
|
827
|
+
current_gemfile = File.exist?('Gemfile') && File.read('Gemfile')
|
828
|
+
case current_gemfile
|
829
|
+
when false
|
830
|
+
secure_write('Gemfile') do |output|
|
831
|
+
output.write default_gemfile
|
810
832
|
end
|
833
|
+
when default_gemfile
|
834
|
+
;;
|
835
|
+
else
|
836
|
+
warn "INFO: Current Gemfile differs from default Gemfile."
|
811
837
|
end
|
838
|
+
end
|
839
|
+
|
840
|
+
# The assert_valid_link method verifies that the provided URL is valid by
|
841
|
+
# checking if it returns an HTTP OK status after following redirects, unless
|
842
|
+
# project is still `developing`.
|
843
|
+
#
|
844
|
+
# @param name [String] the name associated with the link being validated
|
845
|
+
# @param orig_url [String] the URL to validate
|
846
|
+
#
|
847
|
+
# @return [String] the original URL if validation succeeds
|
848
|
+
#
|
849
|
+
# @raise [ArgumentError] if the final response is not an HTTP OK status after
|
850
|
+
# following redirects
|
851
|
+
def assert_valid_link(name, orig_url)
|
852
|
+
developing and return orig_url
|
853
|
+
url = orig_url
|
854
|
+
begin
|
855
|
+
response = Net::HTTP.get_response(URI.parse(url))
|
856
|
+
url = response['location']
|
857
|
+
end while response.is_a?(Net::HTTPRedirection)
|
858
|
+
response.is_a?(Net::HTTPOK) or
|
859
|
+
fail "#{orig_url.inspect} for #{name} has to be a valid link"
|
860
|
+
orig_url
|
861
|
+
end
|
812
862
|
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
863
|
+
# The gemspec method creates and returns a new Gem::Specification object
|
864
|
+
# that defines the metadata and dependencies for the gem package.
|
865
|
+
#
|
866
|
+
# @return [Gem::Specification] a fully configured Gem specification object
|
867
|
+
def gemspec
|
868
|
+
Gem::Specification.new do |s|
|
869
|
+
s.name = name
|
870
|
+
s.version = ::Gem::Version.new(version)
|
871
|
+
s.author = author
|
872
|
+
s.email = email
|
873
|
+
s.homepage = assert_valid_link(:homepage, homepage)
|
874
|
+
s.summary = summary
|
875
|
+
s.description = description
|
876
|
+
|
877
|
+
gem_files.full? { |f| s.files = Array(f) }
|
878
|
+
test_files.full? { |t| s.test_files = Array(t) }
|
879
|
+
extensions.full? { |e| s.extensions = Array(e) }
|
880
|
+
bindir.full? { |b| s.bindir = b }
|
881
|
+
executables.full? { |e| s.executables = Array(e) }
|
882
|
+
licenses.full? { |l| s.licenses = Array(licenses) }
|
883
|
+
post_install_message.full? { |m| s.post_install_message = m }
|
884
|
+
|
885
|
+
required_ruby_version.full? { |v| s.required_ruby_version = v }
|
886
|
+
s.add_development_dependency('gem_hadar', "~> #{VERSION[/\A\d+\.\d+/, 0]}")
|
887
|
+
for d in @development_dependencies
|
888
|
+
s.add_development_dependency(*d)
|
889
|
+
end
|
890
|
+
for d in @dependencies
|
891
|
+
if s.respond_to?(:add_runtime_dependency)
|
892
|
+
s.add_runtime_dependency(*d)
|
893
|
+
else
|
894
|
+
s.add_dependency(*d)
|
895
|
+
end
|
896
|
+
end
|
897
|
+
|
898
|
+
require_paths.full? { |r| s.require_paths = Array(r) }
|
899
|
+
|
900
|
+
if title
|
901
|
+
s.rdoc_options << '--title' << title
|
818
902
|
else
|
819
|
-
|
903
|
+
s.rdoc_options << '--title' << "#{name.camelize} - #{summary}"
|
904
|
+
end
|
905
|
+
if readme
|
906
|
+
s.rdoc_options << '--main' << readme
|
907
|
+
s.extra_rdoc_files << readme
|
820
908
|
end
|
909
|
+
doc_files.full? { |df| s.extra_rdoc_files.concat Array(df) }
|
821
910
|
end
|
822
911
|
end
|
823
912
|
|
824
|
-
|
825
|
-
|
913
|
+
# The warn method displays warning messages using orange colored output.
|
914
|
+
#
|
915
|
+
# @param msgs [Array<String>] the array of message strings to display
|
916
|
+
def warn(*msgs)
|
917
|
+
msgs.map! { |m| color(208) { m } }
|
918
|
+
super(*msgs, uplevel: 1)
|
919
|
+
end
|
826
920
|
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
921
|
+
# The fail method formats and displays failure messages using red colored
|
922
|
+
# output.
|
923
|
+
#
|
924
|
+
# @param args [Array] the array of arguments to be formatted and passed to super
|
925
|
+
def fail(*args)
|
926
|
+
args.map! do |a|
|
927
|
+
a.respond_to?(:to_str) ? color(196) { a.to_str } : a
|
928
|
+
end
|
929
|
+
super(*args)
|
930
|
+
end
|
931
|
+
def fail(*args)
|
932
|
+
args.map! do |a|
|
933
|
+
a.respond_to?(:to_str) ? color(196) { a.to_str } : a
|
934
|
+
end
|
935
|
+
super(*args)
|
936
|
+
end
|
838
937
|
|
839
|
-
|
938
|
+
# The git_remotes method retrieves the list of remote repositories configured
|
939
|
+
# for the current Git project.
|
940
|
+
#
|
941
|
+
# It first attempts to read the remotes from the ENV['GIT_REMOTE']
|
942
|
+
# environment variable, splitting it by whitespace. If this is not available,
|
943
|
+
# it falls back to querying the local Git repository using `git remote`.
|
944
|
+
#
|
945
|
+
# @return [ Array<String> ] an array of remote names
|
946
|
+
def git_remotes
|
947
|
+
remotes = ENV['GIT_REMOTE'].full?(:split, /\s+/)
|
948
|
+
remotes or remotes = `git remote`.lines.map(&:chomp)
|
949
|
+
remotes
|
950
|
+
end
|
840
951
|
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
952
|
+
# The ask? method prompts the user with a message and reads their input It
|
953
|
+
# returns a MatchData object if the input matches the provided pattern.
|
954
|
+
#
|
955
|
+
# @param prompt [ String ] the message to display to the user
|
956
|
+
# @param pattern [ Regexp ] the regular expression to match against the input
|
957
|
+
#
|
958
|
+
# @return [ MatchData, nil ] the result of the pattern match or nil if no match
|
959
|
+
def ask?(prompt, pattern, default: nil)
|
960
|
+
if prompt.include?('%{default}')
|
961
|
+
if default.present?
|
962
|
+
prompt = prompt % { default: ", default is #{default.inspect}" }
|
963
|
+
else
|
964
|
+
prompt = prompt % { default: '' }
|
965
|
+
end
|
966
|
+
end
|
967
|
+
STDOUT.print prompt
|
968
|
+
answer = STDIN.gets.chomp
|
969
|
+
default.present? && answer.blank? and answer = default
|
970
|
+
if answer =~ pattern
|
971
|
+
$~
|
972
|
+
end
|
973
|
+
end
|
853
974
|
|
854
|
-
|
975
|
+
# The gem_files method returns an array of files that are included in the gem
|
976
|
+
# package.
|
977
|
+
#
|
978
|
+
# It calculates this by subtracting the files listed in package_ignore_files
|
979
|
+
# from the list of all files.
|
980
|
+
#
|
981
|
+
# @return [ Array<String> ] the list of files to include in the gem package
|
982
|
+
def gem_files
|
983
|
+
(files.to_a - package_ignore_files.to_a)
|
984
|
+
end
|
855
985
|
|
856
|
-
|
986
|
+
# The versions method retrieves and processes the list of git tags that match
|
987
|
+
# semantic versioning patterns.
|
988
|
+
#
|
989
|
+
# It executes `git tag` to get all available tags, filters them using a
|
990
|
+
# regular expression to identify valid version strings, removes any 'v'
|
991
|
+
# prefix from each version string, trims whitespace, and sorts the resulting
|
992
|
+
# array based on semantic versioning order.
|
993
|
+
#
|
994
|
+
# @return [ Array<String> ] an array of version strings sorted in ascending
|
995
|
+
# order according to semantic versioning rules.
|
996
|
+
def versions
|
997
|
+
@versions ||= `git tag`.lines.grep(/^v?\d+\.\d+\.\d+$/).map(&:chomp).map {
|
998
|
+
_1.sub(/\Av/, '')
|
999
|
+
}.sort_by(&:version)
|
1000
|
+
end
|
857
1001
|
|
858
|
-
|
859
|
-
|
860
|
-
|
1002
|
+
# The version_identifier method prepends a 'v' prefix to the given version
|
1003
|
+
# string.
|
1004
|
+
#
|
1005
|
+
# @param version [String] the version string to modify
|
1006
|
+
# @return [String] the modified version string with a 'v' prefix
|
1007
|
+
def version_identifier(version)
|
1008
|
+
version.dup.prepend ?v
|
1009
|
+
end
|
1010
|
+
|
1011
|
+
# The github_remote_url method retrieves and parses the GitHub remote URL
|
1012
|
+
# from the local Git configuration.
|
1013
|
+
#
|
1014
|
+
# It executes `git remote -v` to get all remote configurations, extracts the
|
1015
|
+
# push URLs, processes them to construct valid URIs, and returns the first
|
1016
|
+
# URI pointing to GitHub.com.
|
1017
|
+
#
|
1018
|
+
# @return [URI, nil] The parsed GitHub remote URI or nil if not found.
|
1019
|
+
def github_remote_url
|
1020
|
+
if remotes = `git remote -v`
|
1021
|
+
remotes_urls = remotes.scan(/^(\S+)\s+(\S+)\s+\(push\)/)
|
1022
|
+
remotes_uris = remotes_urls.map do |name, url|
|
1023
|
+
if %r(\A(?<scheme>[^@]+)@(?<hostname>[A-Za-z0-9.]+):(?:\d*)(?<path>.*)) =~ url
|
1024
|
+
path = ?/ + path unless path.start_with? ?/
|
1025
|
+
url = 'ssh://%s@%s%s' % [ scheme, hostname, path ] # approximate correct URIs
|
861
1026
|
end
|
1027
|
+
URI.parse(url)
|
862
1028
|
end
|
1029
|
+
remotes_uris.find { |uri| uri.hostname == 'github.com' }
|
863
1030
|
end
|
864
1031
|
end
|
1032
|
+
|
1033
|
+
class << self
|
1034
|
+
# The start_simplecov method initializes SimpleCov and configures it to
|
1035
|
+
# ignore coverage data from the directory containing the caller. This can be
|
1036
|
+
# called from a test or spec helper.
|
1037
|
+
def start_simplecov
|
1038
|
+
defined? SimpleCov or return
|
1039
|
+
filter = "#{File.basename(File.dirname(caller.first))}/"
|
1040
|
+
SimpleCov.start do
|
1041
|
+
add_filter filter
|
1042
|
+
end
|
1043
|
+
end
|
1044
|
+
end
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
def GemHadar(&block)
|
1048
|
+
GemHadar.new(&block).create_all_tasks
|
865
1049
|
end
|
866
1050
|
|
867
1051
|
def template(pathname, &block)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gem_hadar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.21.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Frank
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: gem_hadar
|
@@ -15,14 +15,14 @@ dependencies:
|
|
15
15
|
requirements:
|
16
16
|
- - "~>"
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version: '1.
|
18
|
+
version: '1.21'
|
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.
|
25
|
+
version: '1.21'
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: tins
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -51,6 +51,20 @@ dependencies:
|
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: '1.0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: ollama-ruby
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.0'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '1.0'
|
54
68
|
- !ruby/object:Gem::Dependency
|
55
69
|
name: rake
|
56
70
|
requirement: !ruby/object:Gem::Requirement
|
@@ -88,6 +102,9 @@ extensions: []
|
|
88
102
|
extra_rdoc_files:
|
89
103
|
- README.md
|
90
104
|
- lib/gem_hadar.rb
|
105
|
+
- lib/gem_hadar/github.rb
|
106
|
+
- lib/gem_hadar/setup.rb
|
107
|
+
- lib/gem_hadar/template_compiler.rb
|
91
108
|
- lib/gem_hadar/version.rb
|
92
109
|
files:
|
93
110
|
- ".gitignore"
|
@@ -99,6 +116,9 @@ files:
|
|
99
116
|
- bin/gem_hadar
|
100
117
|
- gem_hadar.gemspec
|
101
118
|
- lib/gem_hadar.rb
|
119
|
+
- lib/gem_hadar/github.rb
|
120
|
+
- lib/gem_hadar/setup.rb
|
121
|
+
- lib/gem_hadar/template_compiler.rb
|
102
122
|
- lib/gem_hadar/version.rb
|
103
123
|
homepage: https://github.com/flori/gem_hadar
|
104
124
|
licenses:
|
@@ -122,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
142
|
- !ruby/object:Gem::Version
|
123
143
|
version: '0'
|
124
144
|
requirements: []
|
125
|
-
rubygems_version: 3.6.
|
145
|
+
rubygems_version: 3.6.9
|
126
146
|
specification_version: 4
|
127
147
|
summary: Library for the development of Ruby Gems
|
128
148
|
test_files: []
|