ruby_llm 1.0.0 → 1.1.0rc1

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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +58 -19
  3. data/lib/ruby_llm/active_record/acts_as.rb +46 -7
  4. data/lib/ruby_llm/aliases.json +65 -0
  5. data/lib/ruby_llm/aliases.rb +56 -0
  6. data/lib/ruby_llm/chat.rb +11 -10
  7. data/lib/ruby_llm/configuration.rb +4 -0
  8. data/lib/ruby_llm/error.rb +15 -4
  9. data/lib/ruby_llm/models.json +1489 -283
  10. data/lib/ruby_llm/models.rb +57 -22
  11. data/lib/ruby_llm/provider.rb +44 -41
  12. data/lib/ruby_llm/providers/anthropic/capabilities.rb +8 -9
  13. data/lib/ruby_llm/providers/anthropic/chat.rb +31 -4
  14. data/lib/ruby_llm/providers/anthropic/streaming.rb +12 -6
  15. data/lib/ruby_llm/providers/anthropic.rb +4 -0
  16. data/lib/ruby_llm/providers/bedrock/capabilities.rb +168 -0
  17. data/lib/ruby_llm/providers/bedrock/chat.rb +108 -0
  18. data/lib/ruby_llm/providers/bedrock/models.rb +84 -0
  19. data/lib/ruby_llm/providers/bedrock/signing.rb +831 -0
  20. data/lib/ruby_llm/providers/bedrock/streaming/base.rb +46 -0
  21. data/lib/ruby_llm/providers/bedrock/streaming/content_extraction.rb +63 -0
  22. data/lib/ruby_llm/providers/bedrock/streaming/message_processing.rb +79 -0
  23. data/lib/ruby_llm/providers/bedrock/streaming/payload_processing.rb +90 -0
  24. data/lib/ruby_llm/providers/bedrock/streaming/prelude_handling.rb +91 -0
  25. data/lib/ruby_llm/providers/bedrock/streaming.rb +36 -0
  26. data/lib/ruby_llm/providers/bedrock.rb +83 -0
  27. data/lib/ruby_llm/providers/deepseek/chat.rb +17 -0
  28. data/lib/ruby_llm/providers/deepseek.rb +5 -0
  29. data/lib/ruby_llm/providers/gemini/capabilities.rb +50 -34
  30. data/lib/ruby_llm/providers/gemini/chat.rb +8 -15
  31. data/lib/ruby_llm/providers/gemini/images.rb +5 -10
  32. data/lib/ruby_llm/providers/gemini/models.rb +0 -8
  33. data/lib/ruby_llm/providers/gemini/streaming.rb +35 -76
  34. data/lib/ruby_llm/providers/gemini/tools.rb +12 -12
  35. data/lib/ruby_llm/providers/gemini.rb +4 -0
  36. data/lib/ruby_llm/providers/openai/capabilities.rb +154 -177
  37. data/lib/ruby_llm/providers/openai/streaming.rb +9 -13
  38. data/lib/ruby_llm/providers/openai.rb +4 -0
  39. data/lib/ruby_llm/streaming.rb +96 -0
  40. data/lib/ruby_llm/tool.rb +15 -7
  41. data/lib/ruby_llm/version.rb +1 -1
  42. data/lib/ruby_llm.rb +8 -3
  43. data/lib/tasks/browser_helper.rb +97 -0
  44. data/lib/tasks/capability_generator.rb +123 -0
  45. data/lib/tasks/capability_scraper.rb +224 -0
  46. data/lib/tasks/cli_helper.rb +22 -0
  47. data/lib/tasks/code_validator.rb +29 -0
  48. data/lib/tasks/model_updater.rb +66 -0
  49. data/lib/tasks/models.rake +28 -197
  50. data/lib/tasks/vcr.rake +97 -0
  51. metadata +42 -19
  52. data/.github/workflows/cicd.yml +0 -109
  53. data/.github/workflows/docs.yml +0 -53
  54. data/.gitignore +0 -58
  55. data/.overcommit.yml +0 -26
  56. data/.rspec +0 -3
  57. data/.rspec_status +0 -50
  58. data/.rubocop.yml +0 -10
  59. data/.yardopts +0 -12
  60. data/Gemfile +0 -32
  61. data/Rakefile +0 -9
  62. data/bin/console +0 -17
  63. data/bin/setup +0 -6
  64. data/ruby_llm.gemspec +0 -43
@@ -1,212 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'English'
4
- require 'faraday'
5
- require 'nokogiri'
6
-
7
- # URLs to process
8
- PROVIDER_DOCS = {
9
- openai: {
10
- models: 'https://platform.openai.com/docs/models',
11
- pricing: 'https://platform.openai.com/docs/pricing'
12
- },
13
- gemini: {
14
- models: 'https://ai.google.dev/gemini-api/docs/models/gemini',
15
- pricing: 'https://ai.google.dev/gemini-api/docs/pricing'
16
- },
17
- deepseek: {
18
- models: 'https://api-docs.deepseek.com/quick_start/pricing/'
19
- },
20
- anthropic: {
21
- models: 'https://docs.anthropic.com/en/docs/about-claude/models/all-models'
22
- }
23
- }.freeze
24
-
25
- def fetch_page(url) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
26
- if url.include?('openai.com')
27
- puts "Please visit #{url} and paste the content below (type 'END' on a new line when done):"
28
- original_separator = $INPUT_RECORD_SEPARATOR
29
- $/ = 'END'
30
- content = $stdin.gets&.chomp
31
- $/ = original_separator
32
-
33
- raise "No content provided for #{url}" unless content
34
-
35
- content
36
- else
37
- response = http_client.get(url)
38
- html = Nokogiri::HTML(response.body)
39
-
40
- # Remove script tags and comments
41
- html.css('script').remove
42
- html.xpath('//comment()').remove
43
-
44
- # Extract text content
45
- text = html.css('body').text
46
-
47
- # Clean up whitespace
48
- text.gsub!(/\s+/, ' ')
49
- text.strip!
50
-
51
- text
52
- end
53
- rescue StandardError => e
54
- raise "Failed to fetch #{url}: #{e.message}"
55
- end
56
-
57
- def http_client
58
- @http_client ||= Faraday.new do |f|
59
- f.response :raise_error
60
- f.response :logger, RubyLLM.logger, { headers: false, bodies: true }
61
- end
62
- end
3
+ require_relative 'model_updater'
4
+ require_relative 'capability_scraper'
5
+ require_relative 'capability_generator'
63
6
 
64
7
  namespace :models do # rubocop:disable Metrics/BlockLength
65
- desc 'Update available models from providers'
8
+ desc 'Update available models from providers (API keys needed)'
66
9
  task :update do
67
- require 'ruby_llm'
68
-
69
- # Configure API keys
70
- RubyLLM.configure do |config|
71
- config.openai_api_key = ENV.fetch('OPENAI_API_KEY')
72
- config.anthropic_api_key = ENV.fetch('ANTHROPIC_API_KEY')
73
- config.gemini_api_key = ENV.fetch('GEMINI_API_KEY')
74
- config.deepseek_api_key = ENV.fetch('DEEPSEEK_API_KEY')
75
- end
76
-
77
- # Refresh models (now returns self instead of models array)
78
- models = RubyLLM.models.refresh!.all
79
- # Write to models.json
80
- File.write(File.expand_path('../ruby_llm/models.json', __dir__), JSON.pretty_generate(models.map(&:to_h)))
81
-
82
- puts "Updated models.json with #{models.size} models:"
83
- RubyLLM::Provider.providers.each do |provider_sym, provider_module|
84
- provider_name = provider_module.to_s.split('::').last
85
- provider_models = models.select { |m| m.provider == provider_sym.to_s }
86
- puts "#{provider_name} models: #{provider_models.size}"
87
- end
10
+ ModelUpdater.new.run
88
11
  end
89
12
 
90
- desc 'Update model capabilities modules by scraping provider documentation (use PROVIDER=name to update only one)'
91
- task :update_capabilities do # rubocop:disable Metrics/BlockLength
92
- # Check if a specific provider was requested
93
- target_provider = ENV['PROVIDER']&.to_sym
94
- require 'ruby_llm'
95
- require 'fileutils'
96
-
97
- # Configure API keys
98
- RubyLLM.configure do |config|
99
- config.openai_api_key = ENV.fetch('OPENAI_API_KEY')
100
- config.anthropic_api_key = ENV.fetch('ANTHROPIC_API_KEY')
101
- config.gemini_api_key = ENV.fetch('GEMINI_API_KEY')
13
+ desc 'Update capabilities modules (GEMINI_API_KEY needed)'
14
+ task :update_capabilities, [:providers] do |_t, args|
15
+ gemini_key = ENV.fetch('GEMINI_API_KEY', nil)
16
+ unless gemini_key && !gemini_key.empty?
17
+ puts 'Error: GEMINI_API_KEY required'
18
+ exit(1)
102
19
  end
103
20
 
104
- # Filter providers if a specific one was requested
105
- providers_to_process = if target_provider && PROVIDER_DOCS.key?(target_provider)
106
- { target_provider => PROVIDER_DOCS[target_provider] }
107
- else
108
- PROVIDER_DOCS
109
- end
110
-
111
- # Process each provider
112
- providers_to_process.each do |provider, urls| # rubocop:disable Metrics/BlockLength
113
- puts "Processing #{provider}..."
114
-
115
- # Initialize our AI assistants
116
- #
117
- gemini = RubyLLM.chat(model: 'gemini-2.0-flash').with_temperature(0)
118
- claude = RubyLLM.chat(model: 'claude-3-7-sonnet-20250219').with_temperature(0)
119
-
120
- # Read existing capabilities file if present
121
- existing_file = "lib/ruby_llm/providers/#{provider}/capabilities.rb"
122
- existing_code = File.read(existing_file) if File.exist?(existing_file)
123
-
124
- begin
125
- # Download documentation
126
- docs = urls.map do |type, url|
127
- puts " Getting #{type} documentation..."
128
- content = fetch_page(url)
129
-
130
- puts "\nHere's what I got:\n\n"
131
- puts "#{content.slice(0, 500)}...\n\n"
132
-
133
- loop do
134
- print 'Does this content look correct? (y/n): '
135
- answer = $stdin.gets&.chomp&.downcase
136
- break if answer == 'y'
137
- raise "Content verification failed for #{url}" if answer == 'n'
138
- end
139
-
140
- "#{type.to_s.upcase} DOCUMENTATION:\n\n#{content}"
141
- end.join("\n\n")
142
-
143
- # Extract relevant information with Gemini
144
- puts ' Extracting model information...'
145
- extraction_prompt = <<~PROMPT
146
- Extract relevant model capabilities information from this documentation:
147
-
148
- #{docs}
149
-
150
- Focus on:
151
- 1. Available models and their IDs
152
- 2. Context window sizes
153
- 3. Maximum output tokens
154
- 4. Pricing information
155
- 5. Model capabilities (vision, function calling, etc)
156
-
157
- Format the information clearly and concisely, focusing only on facts about the models.
158
- PROMPT
159
-
160
- model_info = gemini.ask(extraction_prompt).content
161
-
162
- # Generate Ruby code with Claude
163
- puts ' Generating Ruby code...'
164
- code_prompt = <<~PROMPT
165
- I need you to generate a Ruby module for #{provider}'s model capabilities.
166
- Use this extracted model information:
167
-
168
- #{model_info}
169
-
170
- The module should go in lib/ruby_llm/providers/#{provider}/capabilities.rb and follow these conventions:
171
-
172
- 1. Include methods for determining context windows, token limits, pricing, and capabilities
173
- 2. Use consistent naming with other providers
174
- 3. Include detailed pricing information in a PRICES constant
175
- 4. Follow the existing structure in the codebase
176
- 5. Use Ruby idioms and clean code practices
177
- 6. Include module_function to make methods callable at module level
178
- 7. Include all necessary method documentation
179
-
180
- Here's the existing implementation for reference (maintain similar structure and same method names):
181
-
182
- #{existing_code}
183
-
184
- Focus on accuracy and maintaining consistency with the existing codebase structure.
185
- PROMPT
186
-
187
- response = claude.ask(code_prompt)
188
-
189
- # Extract Ruby code from Claude's response
190
- puts " Extracting Ruby code from Claude's response..."
191
- ruby_code = nil
192
-
193
- # Look for Ruby code block
194
- ruby_code = Regexp.last_match(1).strip if response.content =~ /```ruby\s*(.*?)```/m
195
-
196
- # Verify we found Ruby code
197
- raise "No Ruby code block found in Claude's response" if ruby_code.nil? || ruby_code.empty?
21
+ RubyLLM.configure do |c|
22
+ c.gemini_api_key = gemini_key
23
+ c.request_timeout = 300
24
+ end
198
25
 
199
- # Save the file
200
- file_path = "lib/ruby_llm/providers/#{provider}/capabilities.rb"
201
- puts " Writing #{file_path}..."
26
+ target_providers = CapabilityScraper.parse_providers(args[:providers])
202
27
 
203
- FileUtils.mkdir_p(File.dirname(file_path))
204
- File.write(file_path, ruby_code)
205
- rescue StandardError => e
206
- raise "Failed to process #{provider}: #{e.message}"
28
+ begin
29
+ scraper = CapabilityScraper.new(target_providers)
30
+ scraper.run do |provider, docs_html|
31
+ generator = CapabilityGenerator.new(provider, docs_html)
32
+ generator.generate_and_save
207
33
  end
34
+ rescue StandardError => e
35
+ puts "Error: #{e.message}"
36
+ puts e.backtrace.first(5).join("\n")
37
+ ensure
38
+ puts 'Update process complete. Review generated files.'
208
39
  end
209
-
210
- puts "Done! Don't forget to review the generated code and run the tests."
211
40
  end
212
41
  end
42
+
43
+ task default: ['models:update']
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Helper functions at the top level
4
+ def record_all_cassettes(cassette_dir)
5
+ # Re-record all cassettes
6
+ FileUtils.rm_rf(cassette_dir)
7
+ FileUtils.mkdir_p(cassette_dir)
8
+
9
+ puts 'Recording cassettes for all providers...'
10
+ run_tests
11
+ puts 'Done recording. Please review the new cassettes.'
12
+ end
13
+
14
+ def record_for_providers(providers, cassette_dir) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
15
+ # Get the list of available providers from RubyLLM itself
16
+ all_providers = RubyLLM::Provider.providers.keys.map(&:to_s)
17
+
18
+ # Check for valid providers
19
+ if providers.empty?
20
+ puts "Please specify providers or 'all'. Example: rake vcr:record[openai,anthropic]"
21
+ puts "Available providers: #{all_providers.join(', ')}"
22
+ return
23
+ end
24
+
25
+ invalid_providers = providers - all_providers
26
+ if invalid_providers.any?
27
+ puts "Invalid providers: #{invalid_providers.join(', ')}"
28
+ puts "Available providers: #{all_providers.join(', ')}"
29
+ return
30
+ end
31
+
32
+ # Find and delete matching cassettes
33
+ cassettes_to_delete = find_matching_cassettes(cassette_dir, providers)
34
+
35
+ if cassettes_to_delete.empty?
36
+ puts 'No cassettes found for the specified providers.'
37
+ puts 'Running tests to record new cassettes...'
38
+ else
39
+ delete_cassettes(cassettes_to_delete)
40
+ puts "\nRunning tests to record new cassettes..."
41
+ end
42
+
43
+ run_tests
44
+
45
+ puts "\nDone recording cassettes for #{providers.join(', ')}."
46
+ puts 'Please review the updated cassettes for sensitive information.'
47
+ end
48
+
49
+ def find_matching_cassettes(dir, providers) # rubocop:disable Metrics/MethodLength
50
+ cassettes = []
51
+
52
+ Dir.glob("#{dir}/**/*.yml").each do |file|
53
+ basename = File.basename(file)
54
+
55
+ # Precise matching to avoid cross-provider confusion
56
+ providers.each do |provider|
57
+ # Match only exact provider prefixes
58
+ next unless basename =~ /^[^_]*_#{provider}_/ || # For first section like "chat_openai_"
59
+ basename =~ /_#{provider}_[^_]+_/ # For middle sections like "_openai_gpt4_"
60
+
61
+ cassettes << file
62
+ break
63
+ end
64
+ end
65
+
66
+ cassettes
67
+ end
68
+
69
+ def delete_cassettes(cassettes)
70
+ puts "Deleting #{cassettes.size} cassettes for re-recording:"
71
+ cassettes.each do |file|
72
+ puts " - #{File.basename(file)}"
73
+ File.delete(file)
74
+ end
75
+ end
76
+
77
+ def run_tests
78
+ system('bundle exec rspec') || abort('Tests failed')
79
+ end
80
+
81
+ namespace :vcr do
82
+ desc 'Record VCR cassettes (rake vcr:record[all] or vcr:record[openai,anthropic])'
83
+ task :record, [:providers] do |_, args|
84
+ require 'fileutils'
85
+ require 'ruby_llm'
86
+
87
+ providers = (args[:providers] || '').downcase.split(',')
88
+ cassette_dir = 'spec/fixtures/vcr_cassettes'
89
+ FileUtils.mkdir_p(cassette_dir)
90
+
91
+ if providers.include?('all')
92
+ record_all_cassettes(cassette_dir)
93
+ else
94
+ record_for_providers(providers, cassette_dir)
95
+ end
96
+ end
97
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_llm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carmine Paolino
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-11 00:00:00.000000000 Z
11
+ date: 2025-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: base64
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: event_stream_parser
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -82,31 +96,21 @@ dependencies:
82
96
  version: '2'
83
97
  description: A delightful Ruby way to work with AI. Chat in text, analyze and generate
84
98
  images, understand audio, and use tools through a unified interface to OpenAI, Anthropic,
85
- Google, and DeepSeek. Built for developer happiness with automatic token counting,
86
- proper streaming, and Rails integration. No wrapping your head around multiple APIs
87
- - just clean Ruby code that works.
99
+ Google, AWS Bedrock Anthropic, and DeepSeek. Built for developer happiness with
100
+ automatic token counting, proper streaming, and Rails integration. No wrapping your
101
+ head around multiple APIs - just clean Ruby code that works.
88
102
  email:
89
103
  - carmine@paolino.me
90
104
  executables: []
91
105
  extensions: []
92
106
  extra_rdoc_files: []
93
107
  files:
94
- - ".github/workflows/cicd.yml"
95
- - ".github/workflows/docs.yml"
96
- - ".gitignore"
97
- - ".overcommit.yml"
98
- - ".rspec"
99
- - ".rspec_status"
100
- - ".rubocop.yml"
101
- - ".yardopts"
102
- - Gemfile
103
108
  - LICENSE
104
109
  - README.md
105
- - Rakefile
106
- - bin/console
107
- - bin/setup
108
110
  - lib/ruby_llm.rb
109
111
  - lib/ruby_llm/active_record/acts_as.rb
112
+ - lib/ruby_llm/aliases.json
113
+ - lib/ruby_llm/aliases.rb
110
114
  - lib/ruby_llm/chat.rb
111
115
  - lib/ruby_llm/chunk.rb
112
116
  - lib/ruby_llm/configuration.rb
@@ -127,8 +131,20 @@ files:
127
131
  - lib/ruby_llm/providers/anthropic/models.rb
128
132
  - lib/ruby_llm/providers/anthropic/streaming.rb
129
133
  - lib/ruby_llm/providers/anthropic/tools.rb
134
+ - lib/ruby_llm/providers/bedrock.rb
135
+ - lib/ruby_llm/providers/bedrock/capabilities.rb
136
+ - lib/ruby_llm/providers/bedrock/chat.rb
137
+ - lib/ruby_llm/providers/bedrock/models.rb
138
+ - lib/ruby_llm/providers/bedrock/signing.rb
139
+ - lib/ruby_llm/providers/bedrock/streaming.rb
140
+ - lib/ruby_llm/providers/bedrock/streaming/base.rb
141
+ - lib/ruby_llm/providers/bedrock/streaming/content_extraction.rb
142
+ - lib/ruby_llm/providers/bedrock/streaming/message_processing.rb
143
+ - lib/ruby_llm/providers/bedrock/streaming/payload_processing.rb
144
+ - lib/ruby_llm/providers/bedrock/streaming/prelude_handling.rb
130
145
  - lib/ruby_llm/providers/deepseek.rb
131
146
  - lib/ruby_llm/providers/deepseek/capabilities.rb
147
+ - lib/ruby_llm/providers/deepseek/chat.rb
132
148
  - lib/ruby_llm/providers/gemini.rb
133
149
  - lib/ruby_llm/providers/gemini/capabilities.rb
134
150
  - lib/ruby_llm/providers/gemini/chat.rb
@@ -149,11 +165,18 @@ files:
149
165
  - lib/ruby_llm/providers/openai/tools.rb
150
166
  - lib/ruby_llm/railtie.rb
151
167
  - lib/ruby_llm/stream_accumulator.rb
168
+ - lib/ruby_llm/streaming.rb
152
169
  - lib/ruby_llm/tool.rb
153
170
  - lib/ruby_llm/tool_call.rb
154
171
  - lib/ruby_llm/version.rb
172
+ - lib/tasks/browser_helper.rb
173
+ - lib/tasks/capability_generator.rb
174
+ - lib/tasks/capability_scraper.rb
175
+ - lib/tasks/cli_helper.rb
176
+ - lib/tasks/code_validator.rb
177
+ - lib/tasks/model_updater.rb
155
178
  - lib/tasks/models.rake
156
- - ruby_llm.gemspec
179
+ - lib/tasks/vcr.rake
157
180
  homepage: https://rubyllm.com
158
181
  licenses:
159
182
  - MIT
@@ -1,109 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [ "main" ]
6
- paths:
7
- - 'lib/**'
8
- - 'spec/**'
9
- - 'Gemfile'
10
- - 'Rakefile'
11
- - 'ruby_llm.gemspec'
12
- pull_request:
13
- branches: [ "main" ]
14
- workflow_call:
15
-
16
- jobs:
17
- test:
18
- runs-on: ubuntu-latest
19
- strategy:
20
- matrix:
21
- ruby-version: ['3.1']
22
-
23
- steps:
24
- - uses: actions/checkout@v4
25
-
26
- - name: Set up Ruby
27
- uses: ruby/setup-ruby@v1
28
- with:
29
- ruby-version: ${{ matrix.ruby-version }}
30
- bundler-cache: true
31
-
32
- - name: Install dependencies
33
- run: bundle install
34
-
35
- - name: Check code format
36
- run: bundle exec rubocop
37
-
38
- - name: Run tests
39
- env:
40
- OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
41
- ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
42
- GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
43
- DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
44
- run: bundle exec rspec
45
-
46
- - name: Upload coverage to Codecov
47
- uses: codecov/codecov-action@v5
48
- env:
49
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
50
- with:
51
- files: ./coverage/coverage.xml
52
- fail_ci_if_error: false
53
-
54
- publish:
55
- name: Build + Publish
56
- needs: test
57
- if: github.event_name == 'push' && github.ref == 'refs/heads/main'
58
- runs-on: ubuntu-latest
59
- permissions:
60
- contents: read
61
- packages: write
62
-
63
- steps:
64
- - uses: actions/checkout@v4
65
-
66
- - name: Set up Ruby
67
- uses: ruby/setup-ruby@v1
68
- with:
69
- ruby-version: '3.3'
70
- bundler-cache: true
71
-
72
- - name: Publish to GPR
73
- run: |
74
- mkdir -p $HOME/.gem
75
- touch $HOME/.gem/credentials
76
- chmod 0600 $HOME/.gem/credentials
77
- printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
78
- gem build *.gemspec
79
- output=$(gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem 2>&1) || {
80
- echo "$output"
81
- if echo "$output" | grep -q "already been pushed"; then
82
- echo "Version already exists, skipping"
83
- exit 0
84
- else
85
- exit 1
86
- fi
87
- }
88
- env:
89
- GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
90
- OWNER: ${{ github.repository_owner }}
91
-
92
- - name: Publish to RubyGems
93
- run: |
94
- mkdir -p $HOME/.gem
95
- touch $HOME/.gem/credentials
96
- chmod 0600 $HOME/.gem/credentials
97
- printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
98
- gem build *.gemspec
99
- output=$(gem push *.gem 2>&1) || {
100
- echo "$output"
101
- if echo "$output" | grep -q "Repushing of gem versions is not allowed"; then
102
- echo "Version already exists, skipping"
103
- exit 0
104
- else
105
- exit 1
106
- fi
107
- }
108
- env:
109
- GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
@@ -1,53 +0,0 @@
1
- name: Deploy docs
2
-
3
- on:
4
- push:
5
- branches: [main]
6
- paths:
7
- - 'docs/**'
8
- - '.github/workflows/docs.yml'
9
- workflow_dispatch:
10
-
11
- permissions:
12
- contents: read
13
- pages: write
14
- id-token: write
15
-
16
- concurrency:
17
- group: "pages"
18
- cancel-in-progress: false
19
-
20
- jobs:
21
- build:
22
- runs-on: ubuntu-latest
23
- steps:
24
- - name: Checkout
25
- uses: actions/checkout@v4
26
- - name: Setup Ruby
27
- uses: ruby/setup-ruby@v1
28
- with:
29
- ruby-version: '3.3'
30
- bundler-cache: true
31
- working-directory: docs
32
- - name: Setup Pages
33
- uses: actions/configure-pages@v4
34
- - name: Build with Jekyll
35
- working-directory: docs
36
- run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}"
37
- env:
38
- JEKYLL_ENV: production
39
- - name: Upload artifact
40
- uses: actions/upload-pages-artifact@v3
41
- with:
42
- path: docs/_site
43
-
44
- deploy:
45
- environment:
46
- name: github-pages
47
- url: ${{ steps.deployment.outputs.page_url }}
48
- runs-on: ubuntu-latest
49
- needs: build
50
- steps:
51
- - name: Deploy to GitHub Pages
52
- id: deployment
53
- uses: actions/deploy-pages@v4
data/.gitignore DELETED
@@ -1,58 +0,0 @@
1
- *.gem
2
- *.rbc
3
- /.config
4
- /coverage/
5
- /InstalledFiles
6
- /pkg/
7
- /spec/reports/
8
- /spec/examples.txt
9
- /test/tmp/
10
- /test/version_tmp/
11
- /tmp/
12
-
13
- # Used by dotenv library to load environment variables.
14
- .env
15
-
16
- # Ignore Byebug command history file.
17
- .byebug_history
18
-
19
- ## Specific to RubyMotion:
20
- .dat*
21
- .repl_history
22
- build/
23
- *.bridgesupport
24
- build-iPhoneOS/
25
- build-iPhoneSimulator/
26
-
27
- ## Specific to RubyMotion (use of CocoaPods):
28
- #
29
- # We recommend against adding the Pods directory to your .gitignore. However
30
- # you should judge for yourself, the pros and cons are mentioned at:
31
- # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
- #
33
- # vendor/Pods/
34
-
35
- ## Documentation cache and generated files:
36
- /.yardoc/
37
- /_yardoc/
38
- /doc/
39
- /rdoc/
40
-
41
- ## Environment normalization:
42
- /.bundle/
43
- /vendor/bundle
44
- /lib/bundler/man/
45
-
46
- # for a library or gem, you might want to ignore these files since the code is
47
- # intended to run in multiple environments; otherwise, check them in:
48
- Gemfile.lock
49
- # .ruby-version
50
- # .ruby-gemset
51
-
52
- # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
- .rvmrc
54
-
55
- # Used by RuboCop. Remote config files pulled in from inherit_from directive.
56
- # .rubocop-https?--*
57
-
58
- repomix-output.txt
data/.overcommit.yml DELETED
@@ -1,26 +0,0 @@
1
- PreCommit:
2
- RuboCop:
3
- enabled: true
4
- auto_correct: true
5
- on_warn: fail # Treat all warnings as failures
6
-
7
- Flay:
8
- enabled: true
9
-
10
- RSpec:
11
- enabled: false
12
- command: ['bundle', 'exec', 'rspec']
13
- on_warn: fail
14
-
15
- TrailingWhitespace:
16
- enabled: true
17
- auto_correct: true
18
- exclude:
19
- - '**/db/structure.sql' # Ignore trailing whitespace in generated files
20
-
21
- PostCheckout:
22
- ALL: # Special hook name that customizes all hooks of this type
23
- quiet: true # Change all post-checkout hooks to only display output on failure
24
-
25
- IndexTags:
26
- enabled: true # Generate a tags file with `ctags` each time HEAD changes