ollama-client 0.2.3 → 0.2.4

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: 908909c57f4d7067168bcdcecce27471ea2587d6452aecb68aca2c25a8547839
4
- data.tar.gz: fcbf8ee83cba0f05bcae0892e103ae1201a7db1b045c25848caf0d8a71ca891d
3
+ metadata.gz: 9b126aae11a2fd7f0ff26e53e90e12222eb88e23fa6ecf622215c4a9317fe6ce
4
+ data.tar.gz: 2656544e1ce4bfa852dc687108bdde17084773c3a1e76c53ae9ed59d77604256
5
5
  SHA512:
6
- metadata.gz: 67800e85b23a59fd9717ec76a2d27a591538d1813846213cb095d853d41547d6da3bbb10b8096a05b500bec66576a2e0f9268a5ad8738a9c0176b8f2051a99eb
7
- data.tar.gz: 1bb186cb330c6fec601ed909af0fa9ef9bee786827edeb9195955ed25e7d0e8ab1d2eb81c302e47806cf304014ad847c207cc05f7b881392f936413419158714
6
+ metadata.gz: 5cbd78f768412b8e413e9222b4b0b2ef68e094280546742a0bd8191269072a6281ae4182d591e889ba3829c5b047b0e053c2410fa7734dc4cf1dfe320b527239
7
+ data.tar.gz: 2f1c2eafa75910646ed2300c8ad5ab312aefe56bb03d6e4797356e219543a57532058c2b2f3fc31b773caf0e7e0d26b3a71a6f9887b1a40955f5b818ffe6e227
@@ -0,0 +1,794 @@
1
+ # Automated Gem Release Guide
2
+
3
+ Complete guide to setting up automated Ruby gem releases using GitHub Actions and git tags.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Overview](#overview)
8
+ 2. [Prerequisites](#prerequisites)
9
+ 3. [Initial Setup](#initial-setup)
10
+ 4. [GitHub Actions Workflow](#github-actions-workflow)
11
+ 5. [RubyGems Authentication](#rubygems-authentication)
12
+ 6. [Release Process](#release-process)
13
+ 7. [Troubleshooting](#troubleshooting)
14
+ 8. [Best Practices](#best-practices)
15
+
16
+ ## Overview
17
+
18
+ This guide shows how to automate gem releases so that:
19
+ - **Pushing a git tag** (e.g., `v1.2.3`) triggers an automated release
20
+ - **GitHub Actions** validates, builds, and publishes the gem
21
+ - **No manual `gem push`** required
22
+
23
+ ### Benefits
24
+
25
+ ✅ **Consistent releases** - Same process every time
26
+ ✅ **Version validation** - Tag must match gem version
27
+ ✅ **CI/CD integration** - Tests run before release
28
+ ✅ **Security** - API keys stored in GitHub Secrets
29
+ ✅ **Audit trail** - All releases tracked in GitHub
30
+
31
+ ## Prerequisites
32
+
33
+ ### 1. RubyGems Account
34
+
35
+ Create an account at https://rubygems.org if you don't have one.
36
+
37
+ ### 2. Gem Ownership
38
+
39
+ You must own the gem name or it must be available:
40
+
41
+ ```bash
42
+ # Check if name is available
43
+ gem search ^your-gem-name$ --remote
44
+
45
+ # If gem exists, check ownership
46
+ gem owner your-gem-name
47
+
48
+ # Request ownership (if gem is abandoned)
49
+ # Visit: https://rubygems.org/gems/your-gem-name
50
+ ```
51
+
52
+ ### 3. Gem Structure
53
+
54
+ Your gem should have:
55
+
56
+ ```
57
+ your-gem/
58
+ ├── .github/
59
+ │ └── workflows/
60
+ │ └── release.yml # ← We'll create this
61
+ ├── lib/
62
+ │ └── your_gem/
63
+ │ └── version.rb # ← Must have VERSION constant
64
+ ├── your-gem.gemspec # ← Gem specification
65
+ ├── Gemfile
66
+ └── README.md
67
+ ```
68
+
69
+ ## Initial Setup
70
+
71
+ ### Step 1: Version File
72
+
73
+ Create `lib/your_gem/version.rb`:
74
+
75
+ ```ruby
76
+ # frozen_string_literal: true
77
+
78
+ module YourGem
79
+ VERSION = "0.1.0"
80
+ end
81
+ ```
82
+
83
+ ### Step 2: Gemspec File
84
+
85
+ Create `your-gem.gemspec`:
86
+
87
+ ```ruby
88
+ # frozen_string_literal: true
89
+
90
+ require_relative "lib/your_gem/version"
91
+
92
+ Gem::Specification.new do |spec|
93
+ spec.name = "your-gem"
94
+ spec.version = YourGem::VERSION
95
+ spec.authors = ["Your Name"]
96
+ spec.email = ["your.email@example.com"]
97
+
98
+ spec.summary = "Brief description"
99
+ spec.description = "Longer description"
100
+ spec.homepage = "https://github.com/yourusername/your-gem"
101
+ spec.license = "MIT"
102
+ spec.required_ruby_version = ">= 2.7.0"
103
+
104
+ spec.metadata["homepage_uri"] = spec.homepage
105
+ spec.metadata["source_code_uri"] = spec.homepage
106
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
107
+
108
+ # Specify which files should be added to the gem when it is released
109
+ spec.files = Dir.glob(%w[
110
+ lib/**/*.rb
111
+ lib/**/*.json
112
+ sig/**/*.rbs
113
+ *.md
114
+ LICENSE.txt
115
+ ]).reject { |f| File.directory?(f) }
116
+
117
+ spec.bindir = "exe"
118
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
119
+ spec.require_paths = ["lib"]
120
+
121
+ # Dependencies
122
+ # spec.add_dependency "example-gem", "~> 1.0"
123
+
124
+ # Development dependencies
125
+ spec.add_development_dependency "rake", "~> 13.0"
126
+ spec.add_development_dependency "rspec", "~> 3.0"
127
+ spec.add_development_dependency "rubocop", "~> 1.21"
128
+ end
129
+ ```
130
+
131
+ ### Step 3: Test Local Build
132
+
133
+ ```bash
134
+ # Build the gem locally
135
+ gem build your-gem.gemspec
136
+
137
+ # Test installation
138
+ gem install ./your-gem-0.1.0.gem
139
+
140
+ # Clean up
141
+ rm your-gem-0.1.0.gem
142
+ ```
143
+
144
+ ## GitHub Actions Workflow
145
+
146
+ ### Create Workflow File
147
+
148
+ Create `.github/workflows/release.yml`:
149
+
150
+ ```yaml
151
+ name: Release
152
+
153
+ on:
154
+ push:
155
+ tags:
156
+ - "v*"
157
+
158
+ jobs:
159
+ release:
160
+ runs-on: ubuntu-latest
161
+ permissions:
162
+ contents: read
163
+ steps:
164
+ - uses: actions/checkout@v4
165
+ with:
166
+ persist-credentials: false
167
+
168
+ - name: Set up Ruby
169
+ uses: ruby/setup-ruby@v1
170
+ with:
171
+ ruby-version: "3.3.4" # Use your Ruby version
172
+ bundler-cache: true
173
+
174
+ - name: Validate tag matches gem version
175
+ run: |
176
+ set -euo pipefail
177
+ tag="${GITHUB_REF#refs/tags/}"
178
+ tag_version="${tag#v}"
179
+ gem_version=$(ruby -e "require_relative 'lib/your_gem/version'; puts YourGem::VERSION")
180
+ if [ "$tag_version" != "$gem_version" ]; then
181
+ echo "❌ Tag version ($tag_version) does not match gem version ($gem_version)"
182
+ exit 1
183
+ fi
184
+ echo "✅ Tag v$tag_version matches gem version $gem_version"
185
+
186
+ - name: Build gem
187
+ run: gem build your-gem.gemspec
188
+
189
+ - name: Publish gem
190
+ env:
191
+ GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
192
+ run: |
193
+ set -euo pipefail
194
+ gem_version=$(ruby -e "require_relative 'lib/your_gem/version'; puts YourGem::VERSION")
195
+ gem_file="your-gem-${gem_version}.gem"
196
+ if [ ! -f "$gem_file" ]; then
197
+ echo "❌ Gem file not found: $gem_file"
198
+ exit 1
199
+ fi
200
+ echo "📦 Publishing $gem_file to RubyGems..."
201
+ gem push "$gem_file"
202
+ echo "✅ Published successfully!"
203
+ ```
204
+
205
+ **Important:** Replace:
206
+ - `your_gem` with your gem's module name
207
+ - `YourGem` with your module constant
208
+ - `your-gem` with your gem's name
209
+
210
+ ### Optional: Add Testing Before Release
211
+
212
+ Add a test job that runs before release:
213
+
214
+ ```yaml
215
+ name: Release
216
+
217
+ on:
218
+ push:
219
+ tags:
220
+ - "v*"
221
+
222
+ jobs:
223
+ # Run tests first
224
+ test:
225
+ runs-on: ubuntu-latest
226
+ steps:
227
+ - uses: actions/checkout@v4
228
+ - name: Set up Ruby
229
+ uses: ruby/setup-ruby@v1
230
+ with:
231
+ ruby-version: "3.3.4"
232
+ bundler-cache: true
233
+ - name: Run tests
234
+ run: bundle exec rake spec
235
+ - name: Run RuboCop
236
+ run: bundle exec rubocop
237
+
238
+ # Release only if tests pass
239
+ release:
240
+ needs: test
241
+ runs-on: ubuntu-latest
242
+ permissions:
243
+ contents: read
244
+ steps:
245
+ # ... (release steps as above)
246
+ ```
247
+
248
+ ## RubyGems Authentication
249
+
250
+ ### Step 1: Get RubyGems API Key
251
+
252
+ 1. **Login to RubyGems:**
253
+ - Visit: https://rubygems.org/sign_in
254
+
255
+ 2. **Create API Key:**
256
+ - Go to: https://rubygems.org/profile/edit
257
+ - Scroll to "API Keys" section
258
+ - Click **"New API Key"**
259
+
260
+ 3. **Configure Key:**
261
+ - **Name:** `GitHub Actions - your-gem` (descriptive name)
262
+ - **Scopes:** Select **"Push rubygems"** only (principle of least privilege)
263
+ - Click **"Create"**
264
+
265
+ 4. **Copy Key:**
266
+ - Copy the generated key (you won't see it again!)
267
+ - Format: `rubygems_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`
268
+
269
+ ### Step 2: Add to GitHub Secrets
270
+
271
+ 1. **Navigate to Secrets:**
272
+ - Go to your GitHub repo
273
+ - Click **Settings** → **Secrets and variables** → **Actions**
274
+ - Or visit: `https://github.com/USERNAME/REPO/settings/secrets/actions`
275
+
276
+ 2. **Create Secret:**
277
+ - Click **"New repository secret"**
278
+ - **Name:** `RUBYGEMS_API_KEY` (must match workflow file)
279
+ - **Value:** Paste your RubyGems API key
280
+ - Click **"Add secret"**
281
+
282
+ 3. **Verify:**
283
+ - You should see `RUBYGEMS_API_KEY` in the list
284
+ - The value will be hidden (shows as `***`)
285
+
286
+ ### Step 3: Test Authentication (Optional)
287
+
288
+ Test locally before using in CI:
289
+
290
+ ```bash
291
+ # Set up credentials file
292
+ mkdir -p ~/.gem
293
+ echo "---
294
+ :rubygems_api_key: your_api_key_here" > ~/.gem/credentials
295
+ chmod 600 ~/.gem/credentials
296
+
297
+ # Build and push manually to test
298
+ gem build your-gem.gemspec
299
+ gem push your-gem-0.1.0.gem
300
+
301
+ # Clean up
302
+ rm your-gem-0.1.0.gem
303
+ ```
304
+
305
+ ## Release Process
306
+
307
+ ### Standard Release Workflow
308
+
309
+ #### 1. Update Version
310
+
311
+ Edit `lib/your_gem/version.rb`:
312
+
313
+ ```ruby
314
+ module YourGem
315
+ VERSION = "1.2.3" # Bump version
316
+ end
317
+ ```
318
+
319
+ #### 2. Update Changelog
320
+
321
+ Edit `CHANGELOG.md`:
322
+
323
+ ```markdown
324
+ ## [1.2.3] - 2026-01-17
325
+
326
+ ### Added
327
+ - New feature X
328
+ - New feature Y
329
+
330
+ ### Fixed
331
+ - Bug fix A
332
+ - Bug fix B
333
+
334
+ ### Changed
335
+ - Improvement C
336
+ ```
337
+
338
+ #### 3. Commit Changes
339
+
340
+ ```bash
341
+ git add lib/your_gem/version.rb CHANGELOG.md
342
+ git commit -m "Bump version to 1.2.3"
343
+ git push origin main
344
+ ```
345
+
346
+ #### 4. Create and Push Tag
347
+
348
+ **Option A: Annotated Tag (Recommended)**
349
+
350
+ ```bash
351
+ # Create annotated tag with message
352
+ git tag -a v1.2.3 -m "Release v1.2.3
353
+
354
+ - New feature X
355
+ - Bug fix A
356
+ - Improvement C"
357
+
358
+ # Push the tag
359
+ git push origin v1.2.3
360
+ ```
361
+
362
+ **Option B: Lightweight Tag**
363
+
364
+ ```bash
365
+ # Create simple tag
366
+ git tag v1.2.3
367
+
368
+ # Push it
369
+ git push origin v1.2.3
370
+ ```
371
+
372
+ #### 5. Monitor Release
373
+
374
+ 1. **Check GitHub Actions:**
375
+ - Go to: `https://github.com/USERNAME/REPO/actions`
376
+ - Watch the "Release" workflow run
377
+ - Should show: ✅ Validate → ✅ Build → ✅ Publish
378
+
379
+ 2. **Verify on RubyGems:**
380
+ - Visit: `https://rubygems.org/gems/your-gem`
381
+ - Confirm version 1.2.3 is published
382
+ - Check download stats
383
+
384
+ 3. **Test Installation:**
385
+ ```bash
386
+ gem install your-gem
387
+ # Or with version
388
+ gem install your-gem -v 1.2.3
389
+ ```
390
+
391
+ ### Quick Release Script
392
+
393
+ Create `bin/release.sh`:
394
+
395
+ ```bash
396
+ #!/bin/bash
397
+ set -euo pipefail
398
+
399
+ # Usage: ./bin/release.sh 1.2.3
400
+
401
+ VERSION=$1
402
+ TAG="v${VERSION}"
403
+
404
+ echo "🚀 Releasing version ${VERSION}"
405
+
406
+ # Verify version in version.rb matches
407
+ CURRENT_VERSION=$(ruby -e "require_relative 'lib/your_gem/version'; puts YourGem::VERSION")
408
+ if [ "$CURRENT_VERSION" != "$VERSION" ]; then
409
+ echo "❌ Version mismatch!"
410
+ echo " lib/your_gem/version.rb: $CURRENT_VERSION"
411
+ echo " Requested: $VERSION"
412
+ exit 1
413
+ fi
414
+
415
+ # Verify clean working directory
416
+ if [ -n "$(git status --porcelain)" ]; then
417
+ echo "❌ Working directory not clean. Commit or stash changes first."
418
+ exit 1
419
+ fi
420
+
421
+ # Verify on main branch
422
+ BRANCH=$(git branch --show-current)
423
+ if [ "$BRANCH" != "main" ]; then
424
+ echo "⚠️ Not on main branch (currently on: $BRANCH)"
425
+ read -p "Continue anyway? [y/N] " -n 1 -r
426
+ echo
427
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
428
+ exit 1
429
+ fi
430
+ fi
431
+
432
+ # Create and push tag
433
+ echo "📝 Creating tag $TAG"
434
+ git tag -a "$TAG" -m "Release $TAG"
435
+
436
+ echo "⬆️ Pushing tag to origin"
437
+ git push origin "$TAG"
438
+
439
+ echo "✅ Tag pushed! GitHub Actions will publish the gem."
440
+ echo "📊 Monitor: https://github.com/USERNAME/REPO/actions"
441
+ echo "📦 Once published: https://rubygems.org/gems/your-gem"
442
+ ```
443
+
444
+ Make it executable:
445
+
446
+ ```bash
447
+ chmod +x bin/release.sh
448
+ ```
449
+
450
+ Use it:
451
+
452
+ ```bash
453
+ # Update version in lib/your_gem/version.rb first
454
+ # Update CHANGELOG.md
455
+ # Commit changes
456
+ git add -A
457
+ git commit -m "Bump version to 1.2.3"
458
+ git push
459
+
460
+ # Run release script
461
+ ./bin/release.sh 1.2.3
462
+ ```
463
+
464
+ ## Troubleshooting
465
+
466
+ ### Common Issues
467
+
468
+ #### 1. "Access Denied" Error
469
+
470
+ ```
471
+ Pushing gem to https://rubygems.org...
472
+ Access Denied. Please sign up for an account
473
+ ```
474
+
475
+ **Solution:**
476
+ - Verify `RUBYGEMS_API_KEY` secret is set in GitHub
477
+ - Check API key has "Push rubygems" scope
478
+ - Ensure you own the gem name
479
+
480
+ #### 2. "Gem name already taken"
481
+
482
+ ```
483
+ There was a problem saving your gem: Name 'your-gem' is already taken
484
+ ```
485
+
486
+ **Solution:**
487
+ ```bash
488
+ # Check ownership
489
+ gem owner your-gem
490
+
491
+ # If you own it - check credentials
492
+ # If you don't - choose a different name or request ownership
493
+ ```
494
+
495
+ #### 3. Version Mismatch Error
496
+
497
+ ```
498
+ ❌ Tag version (1.2.3) does not match gem version (1.2.2)
499
+ ```
500
+
501
+ **Solution:**
502
+ ```bash
503
+ # Update version in lib/your_gem/version.rb
504
+ # Delete incorrect tag
505
+ git tag -d v1.2.3
506
+ git push origin :refs/tags/v1.2.3
507
+
508
+ # Create correct tag
509
+ git tag -a v1.2.3 -m "Release v1.2.3"
510
+ git push origin v1.2.3
511
+ ```
512
+
513
+ #### 4. "Gem file not found"
514
+
515
+ ```
516
+ ❌ Gem file not found: your-gem-1.2.3.gem
517
+ ```
518
+
519
+ **Solution:**
520
+ - Check gemspec file is named correctly
521
+ - Verify `spec.name` matches gem name
522
+ - Test build locally: `gem build your-gem.gemspec`
523
+
524
+ #### 5. Workflow Not Triggering
525
+
526
+ **Check:**
527
+ ```bash
528
+ # Verify tag format
529
+ git tag -l # Should show v1.2.3 format
530
+
531
+ # Check workflow file location
532
+ ls -la .github/workflows/release.yml
533
+
534
+ # Verify tag trigger in workflow
535
+ grep "tags:" .github/workflows/release.yml
536
+ ```
537
+
538
+ ### Debug Failed Releases
539
+
540
+ #### View Workflow Logs
541
+
542
+ 1. Go to: `https://github.com/USERNAME/REPO/actions`
543
+ 2. Click on failed "Release" run
544
+ 3. Expand failed step to see error
545
+
546
+ #### Re-run Failed Release
547
+
548
+ ```bash
549
+ # Delete failed tag locally and remotely
550
+ git tag -d v1.2.3
551
+ git push origin :refs/tags/v1.2.3
552
+
553
+ # Fix the issue
554
+
555
+ # Re-create and push tag
556
+ git tag -a v1.2.3 -m "Release v1.2.3"
557
+ git push origin v1.2.3
558
+ ```
559
+
560
+ #### Manual Release (Emergency)
561
+
562
+ If GitHub Actions fails, release manually:
563
+
564
+ ```bash
565
+ # Build gem
566
+ gem build your-gem.gemspec
567
+
568
+ # Push manually
569
+ gem push your-gem-1.2.3.gem
570
+
571
+ # Tag the commit after successful push
572
+ git tag -a v1.2.3 -m "Release v1.2.3 (manual)"
573
+ git push origin v1.2.3
574
+ ```
575
+
576
+ ## Best Practices
577
+
578
+ ### 1. Semantic Versioning
579
+
580
+ Follow [SemVer](https://semver.org/):
581
+
582
+ - **MAJOR** (1.0.0 → 2.0.0): Breaking changes
583
+ - **MINOR** (1.0.0 → 1.1.0): New features, backward compatible
584
+ - **PATCH** (1.0.0 → 1.0.1): Bug fixes, backward compatible
585
+
586
+ ### 2. Changelog Maintenance
587
+
588
+ Keep `CHANGELOG.md` updated:
589
+
590
+ ```markdown
591
+ # Changelog
592
+
593
+ All notable changes to this project will be documented in this file.
594
+
595
+ ## [Unreleased]
596
+
597
+ ### Added
598
+ - Features in development
599
+
600
+ ## [1.2.3] - 2026-01-17
601
+
602
+ ### Added
603
+ - New feature X
604
+
605
+ ### Fixed
606
+ - Bug Y
607
+
608
+ ### Changed
609
+ - Improvement Z
610
+
611
+ ## [1.2.2] - 2026-01-10
612
+ ...
613
+ ```
614
+
615
+ ### 3. Pre-Release Checklist
616
+
617
+ Before tagging a release:
618
+
619
+ - [ ] Version bumped in `lib/your_gem/version.rb`
620
+ - [ ] `CHANGELOG.md` updated with changes
621
+ - [ ] All tests passing locally (`bundle exec rake spec`)
622
+ - [ ] RuboCop clean (`bundle exec rubocop`)
623
+ - [ ] Changes committed and pushed to main
624
+ - [ ] Local build works (`gem build your-gem.gemspec`)
625
+
626
+ ### 4. Git Tag Conventions
627
+
628
+ Use consistent tag format:
629
+
630
+ ✅ **Good:**
631
+ - `v1.2.3` (recommended)
632
+ - `1.2.3` (acceptable)
633
+
634
+ ❌ **Bad:**
635
+ - `version-1.2.3`
636
+ - `release-1.2.3`
637
+ - `v1.2.3-final`
638
+
639
+ ### 5. Security
640
+
641
+ **API Key Security:**
642
+ - ✅ Store in GitHub Secrets only
643
+ - ✅ Use "Push rubygems" scope only
644
+ - ✅ Rotate keys periodically (every 6-12 months)
645
+ - ✅ Delete keys for deprecated projects
646
+ - ❌ Never commit API keys to git
647
+ - ❌ Never share API keys in chat/email
648
+
649
+ **Gem File Security:**
650
+ - Include only necessary files in gem
651
+ - Use `spec.files` to explicitly list included files
652
+ - Exclude sensitive files (`.env`, credentials, etc.)
653
+
654
+ ### 6. Release Notes
655
+
656
+ Create GitHub releases for major versions:
657
+
658
+ ```bash
659
+ # Using gh CLI
660
+ gh release create v1.2.3 \
661
+ --title "v1.2.3 - Feature Name" \
662
+ --notes "## Highlights
663
+
664
+ - New feature X
665
+ - Bug fix Y
666
+
667
+ See [CHANGELOG.md](CHANGELOG.md) for details."
668
+ ```
669
+
670
+ ### 7. Testing
671
+
672
+ Always test gems before public release:
673
+
674
+ ```bash
675
+ # Build gem
676
+ gem build your-gem.gemspec
677
+
678
+ # Install locally
679
+ gem install ./your-gem-1.2.3.gem
680
+
681
+ # Test in a sample project
682
+ cd ~/tmp/test-project
683
+ bundle init
684
+ echo 'gem "your-gem", path: "/path/to/your-gem"' >> Gemfile
685
+ bundle install
686
+
687
+ # Test functionality
688
+ ruby -e "require 'your_gem'; puts YourGem::VERSION"
689
+ ```
690
+
691
+ ## Example: Complete Release Flow
692
+
693
+ Here's a complete example from start to finish:
694
+
695
+ ```bash
696
+ # 1. Create new feature branch
697
+ git checkout -b feature/add-cool-feature
698
+
699
+ # 2. Implement feature
700
+ # ... code changes ...
701
+
702
+ # 3. Test locally
703
+ bundle exec rspec
704
+ bundle exec rubocop
705
+
706
+ # 4. Commit and push
707
+ git add -A
708
+ git commit -m "Add cool feature"
709
+ git push origin feature/add-cool-feature
710
+
711
+ # 5. Create PR and merge to main
712
+ gh pr create --title "Add cool feature"
713
+ # ... review and merge ...
714
+
715
+ # 6. Pull latest main
716
+ git checkout main
717
+ git pull origin main
718
+
719
+ # 7. Bump version
720
+ # Edit lib/your_gem/version.rb: VERSION = "1.3.0"
721
+ # Edit CHANGELOG.md: Add [1.3.0] section
722
+
723
+ # 8. Commit version bump
724
+ git add lib/your_gem/version.rb CHANGELOG.md
725
+ git commit -m "Bump version to 1.3.0"
726
+ git push origin main
727
+
728
+ # 9. Create and push tag
729
+ git tag -a v1.3.0 -m "Release v1.3.0
730
+
731
+ - Add cool feature
732
+ - Fix minor bugs"
733
+ git push origin v1.3.0
734
+
735
+ # 10. Monitor GitHub Actions
736
+ # Visit: https://github.com/USERNAME/REPO/actions
737
+ # Watch Release workflow complete
738
+
739
+ # 11. Verify on RubyGems
740
+ # Visit: https://rubygems.org/gems/your-gem
741
+ # Confirm v1.3.0 is live
742
+
743
+ # 12. Test installation
744
+ gem install your-gem
745
+ ruby -e "require 'your_gem'; puts YourGem::VERSION"
746
+ # Should output: 1.3.0
747
+
748
+ # 13. Announce release (optional)
749
+ # - Update README badges
750
+ # - Post on social media
751
+ # - Notify users/community
752
+ ```
753
+
754
+ ## Additional Resources
755
+
756
+ ### Official Documentation
757
+
758
+ - **RubyGems Guides:** https://guides.rubygems.org/
759
+ - **GitHub Actions:** https://docs.github.com/en/actions
760
+ - **Semantic Versioning:** https://semver.org/
761
+
762
+ ### Useful Tools
763
+
764
+ - **gh CLI:** https://cli.github.com/ - Manage GitHub from command line
765
+ - **gem-release:** https://github.com/svenfuchs/gem-release - Automate version bumping
766
+ - **bundler:** https://bundler.io/ - Dependency management
767
+
768
+ ### Related Workflows
769
+
770
+ For more advanced setups, check:
771
+ - **Multi-platform testing:** Test on multiple Ruby versions
772
+ - **Dependency updates:** Automated dependabot PRs
773
+ - **Documentation:** Auto-generate and publish docs
774
+ - **Code coverage:** Track test coverage over time
775
+
776
+ ## Conclusion
777
+
778
+ You now have a complete automated gem release pipeline that:
779
+
780
+ 1. ✅ Validates version matches tag
781
+ 2. ✅ Builds gem automatically
782
+ 3. ✅ Publishes to RubyGems
783
+ 4. ✅ Maintains security with GitHub Secrets
784
+ 5. ✅ Provides audit trail via git tags
785
+
786
+ This workflow can be reused for all your Ruby gems with minimal modifications!
787
+
788
+ ---
789
+
790
+ **Questions or Issues?**
791
+
792
+ - Check [Troubleshooting](#troubleshooting) section
793
+ - Review [GitHub Actions logs](https://github.com/USERNAME/REPO/actions)
794
+ - Consult [RubyGems Guides](https://guides.rubygems.org/)
@@ -0,0 +1,151 @@
1
+ # How to Get Your RubyGems OTP Secret
2
+
3
+ ## The Problem
4
+
5
+ You need the **OTP secret key** from RubyGems, not the 6-digit codes from your authenticator app.
6
+
7
+ ## What It Looks Like
8
+
9
+ ```
10
+ Example: JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP
11
+
12
+ ✅ Valid format:
13
+ - All UPPERCASE letters A-Z
14
+ - Numbers 2-7 only
15
+ - Usually 16-32 characters
16
+ - No spaces, dashes, underscores, or special characters
17
+
18
+ ❌ This is NOT it:
19
+ - 123456 (that's the OTP code, not the secret)
20
+ - abc123_secret (contains invalid characters)
21
+ - YOUR_SECRET_HERE (that's a placeholder!)
22
+ ```
23
+
24
+ ## Step-by-Step: Get Your Secret
25
+
26
+ ### Method 1: Find Existing Secret (If Saved)
27
+
28
+ When you first enabled MFA on RubyGems, it showed you a QR code and a secret key. If you saved that secret key, use it!
29
+
30
+ Check these places:
31
+ - Password manager (1Password, LastPass, Bitwarden, etc.)
32
+ - Notes app
33
+ - Screenshot of the QR code setup page
34
+
35
+ ### Method 2: Regenerate MFA on RubyGems
36
+
37
+ If you can't find the original secret, regenerate it:
38
+
39
+ #### Step 1: Log in to RubyGems
40
+ Go to https://rubygems.org
41
+
42
+ #### Step 2: Go to MFA Settings
43
+ 1. Click your profile picture/name (top right)
44
+ 2. Click **Edit Profile**
45
+ 3. Click **Multi-factor Authentication** (left sidebar)
46
+
47
+ #### Step 3: Regenerate MFA
48
+ 1. Click **"Disable Multi-factor Authentication"**
49
+ 2. Confirm disabling
50
+ 3. Click **"Enable Multi-factor Authentication"** again
51
+ 4. You'll see a QR code and the **secret key** text
52
+
53
+ #### Step 4: Save the Secret
54
+ ```
55
+ IMPORTANT: Copy the secret key NOW!
56
+ Example: JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP
57
+ ```
58
+
59
+ #### Step 5: Update Your Authenticator App
60
+ 1. Remove the old RubyGems entry from your authenticator app
61
+ 2. Scan the new QR code
62
+ 3. Enter the 6-digit code to verify
63
+
64
+ ⚠️ **Warning:** After regenerating, your old authenticator codes won't work!
65
+
66
+ ## Test Your Secret
67
+
68
+ Once you have the secret, test it:
69
+
70
+ ```bash
71
+ # Replace JBSWY... with YOUR actual secret
72
+ ruby -r rotp -e "puts ROTP::TOTP.new('JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP').now"
73
+ ```
74
+
75
+ **Expected output:**
76
+ ```
77
+ 123456 ← A 6-digit number
78
+ ```
79
+
80
+ **This number should match** your authenticator app at the same time!
81
+
82
+ ## Common Mistakes
83
+
84
+ ### ❌ Using the 6-digit OTP code
85
+ ```bash
86
+ # WRONG - This is the code, not the secret
87
+ ruby -r rotp -e "puts ROTP::TOTP.new('123456').now"
88
+ # Error: Invalid Base32 Character
89
+ ```
90
+
91
+ ### ❌ Using the placeholder text
92
+ ```bash
93
+ # WRONG - This is the example placeholder
94
+ ruby -r rotp -e "puts ROTP::TOTP.new('YOUR_SECRET_HERE').now"
95
+ # Error: Invalid Base32 Character - '_'
96
+ ```
97
+
98
+ ### ✅ Using the actual secret
99
+ ```bash
100
+ # CORRECT - Your actual Base32 secret from RubyGems
101
+ ruby -r rotp -e "puts ROTP::TOTP.new('JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP').now"
102
+ # Output: 123456
103
+ ```
104
+
105
+ ## Where to Use It
106
+
107
+ Once you have your real secret:
108
+
109
+ ### 1. Test Locally
110
+ ```bash
111
+ ruby -r rotp -e "puts ROTP::TOTP.new('YOUR_ACTUAL_SECRET').now"
112
+ ```
113
+
114
+ ### 2. Add to GitHub Secrets
115
+ 1. Go to: https://github.com/YOUR_USERNAME/YOUR_REPO/settings/secrets/actions
116
+ 2. Click **New repository secret**
117
+ 3. Name: `RUBYGEMS_OTP_SECRET`
118
+ 4. Value: Your actual secret (e.g., `JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP`)
119
+ 5. Click **Add secret**
120
+
121
+ ## Still Having Issues?
122
+
123
+ ### Error: "Invalid Base32 Character"
124
+
125
+ Your secret contains invalid characters. Check:
126
+ - No underscores (`_`)
127
+ - No lowercase letters
128
+ - No numbers 0, 1, 8, 9
129
+ - No spaces or special characters
130
+
131
+ Valid characters: `A-Z` and `2-7` only
132
+
133
+ ### Error: "OTP code doesn't match"
134
+
135
+ 1. Make sure your computer's time is synchronized
136
+ 2. Try again (codes change every 30 seconds)
137
+ 3. Verify the secret is correct
138
+
139
+ ### Can't Find Secret Anywhere
140
+
141
+ You'll need to regenerate MFA (see Method 2 above).
142
+
143
+ ## Security Note
144
+
145
+ 🔒 **Keep your OTP secret secure!**
146
+ - Don't share it publicly
147
+ - Don't commit it to git
148
+ - Store it in a password manager
149
+ - Only add it to GitHub Secrets (which are encrypted)
150
+
151
+ The secret is like a password - anyone with it can generate your OTP codes!
@@ -0,0 +1,80 @@
1
+ # Quick OTP Setup for Automated Releases
2
+
3
+ ## What You Need
4
+
5
+ Your GitHub repository needs **two secrets** for automated gem releases with MFA:
6
+
7
+ 1. **RUBYGEMS_API_KEY** - Your RubyGems API key
8
+ 2. **RUBYGEMS_OTP_SECRET** - Your RubyGems OTP secret
9
+
10
+ ## Step 1: Get Your OTP Secret
11
+
12
+ 1. Log in to https://rubygems.org
13
+ 2. Go to **Edit Profile** → **Multi-factor Authentication**
14
+ 3. Copy the **secret key** (long alphanumeric string like `JBSWY3DPEHPK3PXP`)
15
+
16
+ **⚠️ Save this securely!** If you don't see it, you may need to regenerate your MFA.
17
+
18
+ ## Step 2: Add Secrets to GitHub
19
+
20
+ 1. Go to your GitHub repo: https://github.com/shubhamtaywade82/ollama-client
21
+ 2. Click **Settings** → **Secrets and variables** → **Actions**
22
+ 3. Add two secrets:
23
+
24
+ | Secret Name | Value | Where to Get It |
25
+ | --------------------- | --------------- | ------------------------------------- |
26
+ | `RUBYGEMS_API_KEY` | Your API key | https://rubygems.org/profile/api_keys |
27
+ | `RUBYGEMS_OTP_SECRET` | Your OTP secret | RubyGems MFA settings (Step 1) |
28
+
29
+ ## Step 3: Test It
30
+
31
+ ```bash
32
+ # Bump version in lib/ollama/version.rb
33
+ # Then create and push tag:
34
+ git tag v0.2.4
35
+ git push origin v0.2.4
36
+ ```
37
+
38
+ The GitHub Action will automatically:
39
+ - Generate OTP code
40
+ - Build gem
41
+ - Push to RubyGems with OTP authentication
42
+
43
+ ## Test OTP Locally (Optional)
44
+
45
+ ```bash
46
+ gem install rotp
47
+ ruby -r rotp -e "puts ROTP::TOTP.new('YOUR_SECRET_HERE').now"
48
+ ```
49
+
50
+ This should match the code in your authenticator app.
51
+
52
+ ## Troubleshooting
53
+
54
+ ### "Invalid OTP code"
55
+ - Verify `RUBYGEMS_OTP_SECRET` is correct
56
+ - Check it matches your authenticator app
57
+
58
+ ### "unauthorized"
59
+ - Verify `RUBYGEMS_API_KEY` is correct
60
+ - Create new API key with push permissions
61
+
62
+ ### Need more help?
63
+ See full guide: `docs/RUBYGEMS_OTP_SETUP.md`
64
+
65
+ ## How It Works
66
+
67
+ ```yaml
68
+ - name: Install OTP generator
69
+ run: gem install rotp
70
+
71
+ - name: Publish gem with OTP
72
+ env:
73
+ GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
74
+ RUBYGEMS_OTP_SECRET: ${{ secrets.RUBYGEMS_OTP_SECRET }}
75
+ run: |
76
+ otp_code=$(ruby -r rotp -e "puts ROTP::TOTP.new(ENV['RUBYGEMS_OTP_SECRET']).now")
77
+ gem push "ollama-client-${version}.gem" --otp "$otp_code"
78
+ ```
79
+
80
+ That's it! Your automated releases are now secured with MFA. 🔒
@@ -0,0 +1,106 @@
1
+ # Quick Release Reference
2
+
3
+ Quick reference for releasing gems via GitHub Actions. See [GEM_RELEASE_GUIDE.md](GEM_RELEASE_GUIDE.md) for full details.
4
+
5
+ ## One-Time Setup
6
+
7
+ ### 1. RubyGems API Key
8
+ 1. Visit: https://rubygems.org/profile/edit
9
+ 2. Create API key with "Push rubygems" scope
10
+ 3. Copy the key
11
+
12
+ ### 2. GitHub Secret
13
+ 1. Go to: `https://github.com/USERNAME/REPO/settings/secrets/actions`
14
+ 2. Add secret: `RUBYGEMS_API_KEY`
15
+ 3. Paste your RubyGems API key
16
+
17
+ ### 3. Workflow File
18
+ Create `.github/workflows/release.yml`:
19
+
20
+ ```yaml
21
+ name: Release
22
+ on:
23
+ push:
24
+ tags: ["v*"]
25
+ jobs:
26
+ release:
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: "3.3.4"
33
+ bundler-cache: true
34
+ - name: Validate version
35
+ run: |
36
+ tag_version="${GITHUB_REF#refs/tags/v}"
37
+ gem_version=$(ruby -e "require_relative 'lib/your_gem/version'; puts YourGem::VERSION")
38
+ [ "$tag_version" = "$gem_version" ] || exit 1
39
+ - name: Build and publish
40
+ env:
41
+ GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
42
+ run: |
43
+ gem build your-gem.gemspec
44
+ gem push your-gem-*.gem
45
+ ```
46
+
47
+ ## Release Process
48
+
49
+ ### Every Release
50
+
51
+ ```bash
52
+ # 1. Update version
53
+ # Edit: lib/your_gem/version.rb
54
+ VERSION = "1.2.3"
55
+
56
+ # 2. Update changelog
57
+ # Edit: CHANGELOG.md
58
+
59
+ # 3. Commit
60
+ git add lib/your_gem/version.rb CHANGELOG.md
61
+ git commit -m "Bump version to 1.2.3"
62
+ git push
63
+
64
+ # 4. Tag and push
65
+ git tag -a v1.2.3 -m "Release v1.2.3"
66
+ git push origin v1.2.3
67
+
68
+ # 5. Monitor
69
+ # https://github.com/USERNAME/REPO/actions
70
+ ```
71
+
72
+ ## Quick Commands
73
+
74
+ ```bash
75
+ # Create release script: bin/release.sh
76
+ #!/bin/bash
77
+ VERSION=$1
78
+ git tag -a v${VERSION} -m "Release v${VERSION}"
79
+ git push origin v${VERSION}
80
+ echo "✅ Releasing v${VERSION} - check GitHub Actions"
81
+
82
+ # Use it:
83
+ chmod +x bin/release.sh
84
+ ./bin/release.sh 1.2.3
85
+ ```
86
+
87
+ ## Common Issues
88
+
89
+ **Access Denied?**
90
+ - Check `RUBYGEMS_API_KEY` secret exists
91
+ - Verify API key has "Push rubygems" scope
92
+
93
+ **Version Mismatch?**
94
+ - Update `lib/your_gem/version.rb`
95
+ - Delete tag: `git tag -d v1.2.3 && git push origin :refs/tags/v1.2.3`
96
+
97
+ **Workflow Not Running?**
98
+ - Verify `.github/workflows/release.yml` exists
99
+ - Check tag format: `v1.2.3` (with v prefix)
100
+
101
+ ## Links
102
+
103
+ - **Full Guide:** [GEM_RELEASE_GUIDE.md](GEM_RELEASE_GUIDE.md)
104
+ - **Your Actions:** https://github.com/USERNAME/REPO/actions
105
+ - **RubyGems:** https://rubygems.org/profile/edit
106
+ - **GitHub Secrets:** https://github.com/USERNAME/REPO/settings/secrets/actions
data/docs/README.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  This directory contains internal development documentation for the ollama-client gem.
4
4
 
5
+ ## Quick Links
6
+
7
+ - 🚀 **[Quick Release Reference](QUICK_RELEASE.md)** - Fast release checklist
8
+ - 📘 **[Complete Release Guide](GEM_RELEASE_GUIDE.md)** - Full automation setup (794 lines)
9
+
5
10
  ## Contents
6
11
 
7
12
  ### Design Documentation
@@ -17,6 +22,7 @@ This directory contains internal development documentation for the ollama-client
17
22
 
18
23
  ### CI/Automation
19
24
  - **[CLOUD.md](CLOUD.md)** - Cloud agent guide for automated testing and fixes
25
+ - **[GEM_RELEASE_GUIDE.md](GEM_RELEASE_GUIDE.md)** - Complete guide for automated gem releases via GitHub Actions and git tags
20
26
 
21
27
  ## For Users
22
28
 
@@ -0,0 +1,199 @@
1
+ # RubyGems OTP Setup for Automated Releases
2
+
3
+ This guide explains how to configure OTP (One-Time Password) authentication for automated gem releases with MFA enabled.
4
+
5
+ ## Why This Is Needed
6
+
7
+ When `rubygems_mfa_required = "true"` is set in your gemspec, RubyGems requires MFA verification for all gem pushes, including automated CI/CD releases. This guide shows how to configure GitHub Actions to generate OTP codes automatically.
8
+
9
+ ## Prerequisites
10
+
11
+ - RubyGems account with MFA enabled
12
+ - Admin access to your GitHub repository (to add secrets)
13
+ - Authenticator app (Google Authenticator, Authy, 1Password, etc.)
14
+
15
+ ## Step 1: Get Your RubyGems OTP Secret
16
+
17
+ ### Option A: From Existing MFA Setup
18
+
19
+ If you already have MFA enabled on RubyGems:
20
+
21
+ 1. **Log in to RubyGems.org**
22
+ 2. **Go to Edit Profile** → **Multi-factor Authentication**
23
+ 3. **Click "Show QR Code"** or **"Regenerate Recovery Codes"**
24
+ 4. When you see the QR code, look for the **secret key** (usually shown below the QR code)
25
+ 5. Copy the secret key (it's a long alphanumeric string like `JBSWY3DPEHPK3PXP`)
26
+
27
+ ### Option B: Enable MFA Fresh
28
+
29
+ If you're setting up MFA for the first time:
30
+
31
+ 1. **Log in to RubyGems.org**
32
+ 2. **Go to Edit Profile** → **Multi-factor Authentication**
33
+ 3. **Click "Enable MFA"**
34
+ 4. You'll see a QR code and a **secret key** below it
35
+ 5. **Copy the secret key** before scanning the QR code
36
+ 6. Scan the QR code with your authenticator app
37
+ 7. Enter the 6-digit code to verify
38
+
39
+ **⚠️ IMPORTANT:** Save the secret key securely. You'll need it for GitHub Actions.
40
+
41
+ ### What the Secret Looks Like
42
+
43
+ ```
44
+ Example: JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP
45
+ - All uppercase letters and numbers
46
+ - Typically 32 characters long
47
+ - Base32 encoded
48
+ ```
49
+
50
+ ## Step 2: Add Secrets to GitHub
51
+
52
+ ### 2.1: Add API Key Secret
53
+
54
+ 1. Go to your GitHub repository
55
+ 2. Click **Settings** → **Secrets and variables** → **Actions**
56
+ 3. Click **New repository secret**
57
+ 4. Name: `RUBYGEMS_API_KEY`
58
+ 5. Value: Your RubyGems API key (get from https://rubygems.org/profile/api_keys)
59
+ 6. Click **Add secret**
60
+
61
+ ### 2.2: Add OTP Secret
62
+
63
+ 1. Still in **Secrets and variables** → **Actions**
64
+ 2. Click **New repository secret**
65
+ 3. Name: `RUBYGEMS_OTP_SECRET`
66
+ 4. Value: Your OTP secret key (from Step 1)
67
+ 5. Click **Add secret**
68
+
69
+ ## Step 3: Verify GitHub Secrets
70
+
71
+ Your repository should now have two secrets:
72
+
73
+ ```
74
+ ✅ RUBYGEMS_API_KEY
75
+ ✅ RUBYGEMS_OTP_SECRET
76
+ ```
77
+
78
+ ## Step 4: Test the Setup
79
+
80
+ ### Test Locally First
81
+
82
+ You can test OTP generation locally before pushing:
83
+
84
+ ```bash
85
+ # Install rotp gem
86
+ gem install rotp
87
+
88
+ # Generate an OTP code (replace with your actual secret)
89
+ ruby -r rotp -e "puts ROTP::TOTP.new('YOUR_SECRET_HERE').now"
90
+ ```
91
+
92
+ This should output a 6-digit code that matches your authenticator app.
93
+
94
+ ### Test in CI/CD
95
+
96
+ 1. Bump your gem version in `lib/ollama/version.rb`
97
+ 2. Commit and push
98
+ 3. Create and push a matching tag:
99
+
100
+ ```bash
101
+ git tag v0.2.4
102
+ git push origin v0.2.4
103
+ ```
104
+
105
+ 4. Check GitHub Actions to see the release workflow run
106
+
107
+ ## How It Works
108
+
109
+ The GitHub Actions workflow:
110
+
111
+ 1. **Installs `rotp` gem** - Ruby library for generating TOTP codes
112
+ 2. **Generates OTP code** - Uses your secret to generate a 6-digit code
113
+ 3. **Pushes gem** - Runs `gem push --otp <code>` with the generated code
114
+
115
+ ```yaml
116
+ - name: Install OTP generator
117
+ run: gem install rotp
118
+
119
+ - name: Publish gem with OTP
120
+ env:
121
+ GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
122
+ RUBYGEMS_OTP_SECRET: ${{ secrets.RUBYGEMS_OTP_SECRET }}
123
+ run: |
124
+ otp_code=$(ruby -r rotp -e "puts ROTP::TOTP.new(ENV['RUBYGEMS_OTP_SECRET']).now")
125
+ gem push "ollama-client-${gem_version}.gem" --otp "$otp_code"
126
+ ```
127
+
128
+ ## Troubleshooting
129
+
130
+ ### "Invalid OTP code" Error
131
+
132
+ **Cause:** Time synchronization issue or wrong secret
133
+
134
+ **Solutions:**
135
+ 1. Verify your secret is correct
136
+ 2. Check server time is synchronized:
137
+ ```bash
138
+ date
139
+ ```
140
+ 3. Try regenerating the secret on RubyGems
141
+
142
+ ### "OTP code expired" Error
143
+
144
+ **Cause:** Code expired before being used (they last 30 seconds)
145
+
146
+ **Solution:** The workflow generates the code immediately before use, so this shouldn't happen. If it does, there may be a network delay. The workflow will need to retry.
147
+
148
+ ### "unauthorized" Error
149
+
150
+ **Cause:** API key is invalid or doesn't have push permissions
151
+
152
+ **Solutions:**
153
+ 1. Verify `RUBYGEMS_API_KEY` is correct
154
+ 2. Create a new API key with push permissions
155
+ 3. Update the secret in GitHub
156
+
157
+ ### Missing Secrets
158
+
159
+ **Error:** `RUBYGEMS_OTP_SECRET not found`
160
+
161
+ **Solution:** Ensure both secrets are added to GitHub (Settings → Secrets and variables → Actions)
162
+
163
+ ## Security Considerations
164
+
165
+ ### ✅ Pros
166
+ - MFA protection on gem releases
167
+ - OTP secret encrypted in GitHub Secrets
168
+ - No manual intervention needed
169
+ - Audit trail in GitHub Actions
170
+
171
+ ### ⚠️ Considerations
172
+ - OTP secret stored in GitHub increases attack surface
173
+ - If GitHub is compromised, attacker has both API key and OTP secret
174
+ - Alternative: Remove `rubygems_mfa_required` and rely on account-level MFA
175
+
176
+ ### Best Practices
177
+
178
+ 1. **Rotate API keys** regularly
179
+ 2. **Use scoped API keys** (push-only if possible)
180
+ 3. **Enable GitHub branch protection** on main branch
181
+ 4. **Require PR reviews** for sensitive changes
182
+ 5. **Monitor release logs** for unauthorized pushes
183
+ 6. **Regenerate OTP secret** if you suspect compromise
184
+
185
+ ## Alternative: Account-Level MFA Only
186
+
187
+ If you want simpler automation:
188
+
189
+ 1. Remove `rubygems_mfa_required` from gemspec
190
+ 2. Keep account-level MFA enabled on RubyGems
191
+ 3. Use API key only (no OTP needed)
192
+
193
+ This is the recommended approach for most projects as it provides good security with less complexity.
194
+
195
+ ## Reference
196
+
197
+ - [RubyGems MFA Documentation](https://guides.rubygems.org/setting-up-multifactor-authentication/)
198
+ - [ROTP Gem Documentation](https://github.com/mdp/rotp)
199
+ - [GitHub Encrypted Secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ollama
4
- VERSION = "0.2.3"
4
+ VERSION = "0.2.4"
5
5
  end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ollama-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shubham Taywade
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2026-01-18 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: bigdecimal
@@ -59,9 +60,14 @@ files:
59
60
  - docs/CLOUD.md
60
61
  - docs/CONSOLE_IMPROVEMENTS.md
61
62
  - docs/FEATURES_ADDED.md
63
+ - docs/GEM_RELEASE_GUIDE.md
64
+ - docs/GET_RUBYGEMS_SECRET.md
62
65
  - docs/HANDLERS_ANALYSIS.md
63
66
  - docs/PRODUCTION_FIXES.md
67
+ - docs/QUICK_OTP_SETUP.md
68
+ - docs/QUICK_RELEASE.md
64
69
  - docs/README.md
70
+ - docs/RUBYGEMS_OTP_SETUP.md
65
71
  - docs/SCHEMA_FIXES.md
66
72
  - docs/TESTING.md
67
73
  - docs/TEST_UPDATES.md
@@ -141,6 +147,7 @@ metadata:
141
147
  source_code_uri: https://github.com/shubhamtaywade82/ollama-client
142
148
  changelog_uri: https://github.com/shubhamtaywade82/ollama-client/blob/main/CHANGELOG.md
143
149
  rubygems_mfa_required: 'true'
150
+ post_install_message:
144
151
  rdoc_options: []
145
152
  require_paths:
146
153
  - lib
@@ -155,7 +162,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
162
  - !ruby/object:Gem::Version
156
163
  version: '0'
157
164
  requirements: []
158
- rubygems_version: 4.0.3
165
+ rubygems_version: 3.5.11
166
+ signing_key:
159
167
  specification_version: 4
160
168
  summary: An agent-first Ruby client for Ollama (planner/executor + safe tool loops)
161
169
  test_files: []