ollama-client 0.2.2 → 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 +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +7 -1
- data/docs/CLOUD.md +29 -0
- data/docs/CONSOLE_IMPROVEMENTS.md +256 -0
- data/docs/GEM_RELEASE_GUIDE.md +794 -0
- data/docs/GET_RUBYGEMS_SECRET.md +151 -0
- data/docs/QUICK_OTP_SETUP.md +80 -0
- data/docs/QUICK_RELEASE.md +106 -0
- data/docs/README.md +43 -0
- data/docs/RUBYGEMS_OTP_SETUP.md +199 -0
- data/docs/SCHEMA_FIXES.md +147 -0
- data/docs/TEST_UPDATES.md +107 -0
- data/examples/README.md +92 -0
- data/examples/advanced_complex_schemas.rb +6 -3
- data/examples/advanced_multi_step_agent.rb +2 -1
- data/examples/chat_console.rb +12 -3
- data/examples/complete_workflow.rb +14 -4
- data/examples/dhan_console.rb +103 -8
- data/examples/dhanhq/agents/technical_analysis_agent.rb +6 -1
- data/examples/dhanhq/schemas/agent_schemas.rb +2 -2
- data/examples/dhanhq_agent.rb +23 -13
- data/examples/dhanhq_tools.rb +311 -246
- data/examples/multi_step_agent_with_external_data.rb +368 -0
- data/{test_dhanhq_tool_calling.rb → examples/test_dhanhq_tool_calling.rb} +99 -6
- data/lib/ollama/agent/executor.rb +30 -30
- data/lib/ollama/client.rb +73 -80
- data/lib/ollama/dto.rb +7 -7
- data/lib/ollama/options.rb +17 -9
- data/lib/ollama/response.rb +4 -6
- data/lib/ollama/tool/function/parameters.rb +1 -0
- data/lib/ollama/version.rb +1 -1
- metadata +24 -9
- /data/{FEATURES_ADDED.md → docs/FEATURES_ADDED.md} +0 -0
- /data/{HANDLERS_ANALYSIS.md → docs/HANDLERS_ANALYSIS.md} +0 -0
- /data/{PRODUCTION_FIXES.md → docs/PRODUCTION_FIXES.md} +0 -0
- /data/{TESTING.md → docs/TESTING.md} +0 -0
- /data/{test_tool_calling.rb → examples/test_tool_calling.rb} +0 -0
|
@@ -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/)
|