jekyll-theme-zer0 0.7.2 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +72 -0
  3. data/README.md +33 -4
  4. data/_plugins/preview_image_generator.rb +258 -0
  5. data/_plugins/theme_version.rb +88 -0
  6. data/assets/images/previews/git-workflow-best-practices-for-modern-teams.png +0 -0
  7. data/scripts/README.md +443 -0
  8. data/scripts/analyze-commits.sh +313 -0
  9. data/scripts/build +115 -0
  10. data/scripts/build.sh +33 -0
  11. data/scripts/build.sh.legacy +174 -0
  12. data/scripts/example-usage.sh +102 -0
  13. data/scripts/fix-markdown-format.sh +265 -0
  14. data/scripts/gem-publish.sh +42 -0
  15. data/scripts/gem-publish.sh.legacy +700 -0
  16. data/scripts/generate-preview-images.sh +846 -0
  17. data/scripts/install-preview-generator.sh +531 -0
  18. data/scripts/lib/README.md +263 -0
  19. data/scripts/lib/changelog.sh +313 -0
  20. data/scripts/lib/common.sh +154 -0
  21. data/scripts/lib/gem.sh +226 -0
  22. data/scripts/lib/git.sh +205 -0
  23. data/scripts/lib/preview_generator.py +646 -0
  24. data/scripts/lib/test/run_tests.sh +140 -0
  25. data/scripts/lib/test/test_changelog.sh +87 -0
  26. data/scripts/lib/test/test_gem.sh +68 -0
  27. data/scripts/lib/test/test_git.sh +82 -0
  28. data/scripts/lib/test/test_validation.sh +72 -0
  29. data/scripts/lib/test/test_version.sh +96 -0
  30. data/scripts/lib/validation.sh +139 -0
  31. data/scripts/lib/version.sh +178 -0
  32. data/scripts/release +240 -0
  33. data/scripts/release.sh +33 -0
  34. data/scripts/release.sh.legacy +342 -0
  35. data/scripts/setup.sh +155 -0
  36. data/scripts/test-auto-version.sh +260 -0
  37. data/scripts/test-mermaid.sh +251 -0
  38. data/scripts/test.sh +156 -0
  39. data/scripts/version.sh +152 -0
  40. metadata +37 -1
@@ -0,0 +1,700 @@
1
+ #!/bin/bash
2
+
3
+ # Comprehensive Gem Publication Script for zer0-mistakes Jekyll theme
4
+ # Usage: ./scripts/gem-publish.sh [patch|minor|major] [options]
5
+
6
+ set -e
7
+
8
+ # Colors for output
9
+ RED='\033[0;31m'
10
+ GREEN='\033[0;32m'
11
+ YELLOW='\033[1;33m'
12
+ BLUE='\033[0;34m'
13
+ CYAN='\033[0;36m'
14
+ PURPLE='\033[0;35m'
15
+ NC='\033[0m' # No Color
16
+
17
+ # Default values
18
+ VERSION_TYPE="${1:-patch}"
19
+ DRY_RUN=false
20
+ SKIP_TESTS=false
21
+ SKIP_CHANGELOG=false
22
+ SKIP_PUBLISH=false
23
+ CREATE_GITHUB_RELEASE=true
24
+ INTERACTIVE=true
25
+ AUTOMATED_RELEASE=false
26
+ AUTO_COMMIT_RANGE=""
27
+
28
+ # Parse arguments
29
+ while [[ $# -gt 0 ]]; do
30
+ case $1 in
31
+ --dry-run)
32
+ DRY_RUN=true
33
+ shift
34
+ ;;
35
+ --skip-tests)
36
+ SKIP_TESTS=true
37
+ shift
38
+ ;;
39
+ --skip-changelog)
40
+ SKIP_CHANGELOG=true
41
+ shift
42
+ ;;
43
+ --skip-publish)
44
+ SKIP_PUBLISH=true
45
+ shift
46
+ ;;
47
+ --no-github-release)
48
+ CREATE_GITHUB_RELEASE=false
49
+ shift
50
+ ;;
51
+ --non-interactive)
52
+ INTERACTIVE=false
53
+ shift
54
+ ;;
55
+ --automated-release)
56
+ AUTOMATED_RELEASE=true
57
+ INTERACTIVE=false
58
+ shift
59
+ ;;
60
+ --auto-commit-range=*)
61
+ AUTO_COMMIT_RANGE="${1#*=}"
62
+ shift
63
+ ;;
64
+ patch|minor|major)
65
+ VERSION_TYPE="$1"
66
+ shift
67
+ ;;
68
+ --help)
69
+ # show_usage will be called after function definitions
70
+ SHOW_HELP=true
71
+ shift
72
+ ;;
73
+ *)
74
+ echo -e "${RED}Unknown option: $1${NC}"
75
+ exit 1
76
+ ;;
77
+ esac
78
+ done
79
+
80
+ # Function to show usage
81
+ show_usage() {
82
+ cat << EOF
83
+ 🚀 Comprehensive Gem Publication Script for zer0-mistakes
84
+
85
+ USAGE:
86
+ ./scripts/gem-publish.sh [patch|minor|major] [OPTIONS]
87
+
88
+ VERSION TYPES:
89
+ patch Bump patch version (0.0.X) - Bug fixes
90
+ minor Bump minor version (0.X.0) - New features
91
+ major Bump major version (X.0.0) - Breaking changes
92
+
93
+ OPTIONS:
94
+ --dry-run Show what would be done without making changes
95
+ --skip-tests Skip running tests before release
96
+ --skip-changelog Skip automatic changelog generation
97
+ --skip-publish Skip publishing to RubyGems
98
+ --no-github-release Skip creating GitHub release
99
+ --non-interactive Run without user prompts
100
+ --automated-release Enable fully automated release mode
101
+ --auto-commit-range=RANGE Use specific commit range for changelog
102
+ --help Show this help message
103
+
104
+ WORKFLOW:
105
+ 1. Validate environment and dependencies
106
+ 2. Generate changelog from commit history
107
+ 3. Version bump and update files
108
+ 4. Run comprehensive tests
109
+ 5. Build and validate gem
110
+ 6. Publish to RubyGems
111
+ 7. Create GitHub Release with assets
112
+ 8. Push changes and tags to repository
113
+
114
+ EXAMPLES:
115
+ ./scripts/gem-publish.sh patch # Patch release with full workflow
116
+ ./scripts/gem-publish.sh minor --dry-run # Preview minor version bump
117
+ ./scripts/gem-publish.sh major --skip-tests # Major release, skip tests
118
+
119
+ EOF
120
+ }
121
+
122
+ # Function to log messages with different levels
123
+ log() {
124
+ echo -e "${GREEN}[GEM-PUBLISH]${NC} $1"
125
+ }
126
+
127
+ warn() {
128
+ echo -e "${YELLOW}[WARNING]${NC} $1"
129
+ }
130
+
131
+ error() {
132
+ echo -e "${RED}[ERROR]${NC} $1"
133
+ exit 1
134
+ }
135
+
136
+ info() {
137
+ echo -e "${BLUE}[INFO]${NC} $1"
138
+ }
139
+
140
+ step() {
141
+ echo -e "${CYAN}[STEP]${NC} $1"
142
+ }
143
+
144
+ success() {
145
+ echo -e "${GREEN}[SUCCESS]${NC} $1"
146
+ }
147
+
148
+ # Function to ask for user confirmation
149
+ confirm() {
150
+ if [[ "$INTERACTIVE" == false ]]; then
151
+ return 0
152
+ fi
153
+
154
+ echo -e "${YELLOW}$1 (y/N)${NC}"
155
+ read -r response
156
+ [[ "$response" =~ ^[Yy]$ ]]
157
+ }
158
+
159
+ # Function to validate environment
160
+ validate_environment() {
161
+ step "Validating environment..."
162
+
163
+ # Check if we're in a git repository
164
+ if ! git rev-parse --git-dir > /dev/null 2>&1; then
165
+ error "Not in a git repository"
166
+ fi
167
+
168
+ # Check if working directory is clean
169
+ if [[ -n $(git status --porcelain) ]]; then
170
+ error "Working directory is not clean. Please commit or stash changes first."
171
+ fi
172
+
173
+ # Check required files
174
+ local required_files=(
175
+ "lib/jekyll-theme-zer0/version.rb"
176
+ "jekyll-theme-zer0.gemspec"
177
+ "CHANGELOG.md"
178
+ )
179
+
180
+ for file in "${required_files[@]}"; do
181
+ if [[ ! -f "$file" ]]; then
182
+ error "Required file not found: $file"
183
+ fi
184
+ done
185
+
186
+ # Check required commands
187
+ local required_commands=("git" "ruby" "gem" "bundle" "jq")
188
+ for cmd in "${required_commands[@]}"; do
189
+ if ! command -v "$cmd" &> /dev/null; then
190
+ error "Required command not found: $cmd"
191
+ fi
192
+ done
193
+
194
+ # Check if authenticated with RubyGems
195
+ if [[ "$SKIP_PUBLISH" != true ]] && [[ ! -f ~/.gem/credentials ]]; then
196
+ error "Not authenticated with RubyGems. Run 'gem signin' first."
197
+ fi
198
+
199
+ success "Environment validation complete"
200
+ }
201
+
202
+ # Function to get current version
203
+ get_current_version() {
204
+ local version=$(grep -o 'VERSION = "[^"]*"' lib/jekyll-theme-zer0/version.rb | sed 's/VERSION = "\(.*\)"/\1/')
205
+ if [[ -z "$version" ]]; then
206
+ error "Could not read version from lib/jekyll-theme-zer0/version.rb"
207
+ fi
208
+ echo "$version"
209
+ }
210
+
211
+ # Function to calculate new version
212
+ calculate_new_version() {
213
+ local current_version="$1"
214
+ local version_type="$2"
215
+
216
+ IFS='.' read -ra VERSION_PARTS <<< "$current_version"
217
+ local major=${VERSION_PARTS[0]}
218
+ local minor=${VERSION_PARTS[1]}
219
+ local patch=${VERSION_PARTS[2]}
220
+
221
+ case $version_type in
222
+ major)
223
+ major=$((major + 1))
224
+ minor=0
225
+ patch=0
226
+ ;;
227
+ minor)
228
+ minor=$((minor + 1))
229
+ patch=0
230
+ ;;
231
+ patch)
232
+ patch=$((patch + 1))
233
+ ;;
234
+ esac
235
+
236
+ echo "$major.$minor.$patch"
237
+ }
238
+
239
+ # Function to get the last version tag
240
+ get_last_version_tag() {
241
+ local last_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
242
+ if [[ -z "$last_tag" ]]; then
243
+ # If no tags, use initial commit
244
+ echo $(git rev-list --max-parents=0 HEAD)
245
+ else
246
+ echo "$last_tag"
247
+ fi
248
+ }
249
+
250
+ # Function to generate changelog from commits
251
+ generate_changelog() {
252
+ local current_version="$1"
253
+ local new_version="$2"
254
+ local last_tag="$3"
255
+
256
+ step "Generating changelog from commit history..."
257
+
258
+ # Get commits since last version or use provided range
259
+ local commits
260
+ if [[ -n "$AUTO_COMMIT_RANGE" ]]; then
261
+ # Use the provided commit range for automated releases
262
+ log "Using automated commit range: $AUTO_COMMIT_RANGE"
263
+ commits=$(git log --pretty=format:"%H|%s|%an|%ad" --date=short "$AUTO_COMMIT_RANGE")
264
+ elif [[ "$last_tag" =~ ^v[0-9] ]]; then
265
+ commits=$(git log --pretty=format:"%H|%s|%an|%ad" --date=short "${last_tag}..HEAD")
266
+ else
267
+ commits=$(git log --pretty=format:"%H|%s|%an|%ad" --date=short "${last_tag}..HEAD")
268
+ fi
269
+
270
+ if [[ -z "$commits" ]]; then
271
+ warn "No commits found since last version tag"
272
+ return 0
273
+ fi
274
+
275
+ # Categorize commits
276
+ local added=()
277
+ local changed=()
278
+ local fixed=()
279
+ local deprecated=()
280
+ local removed=()
281
+ local security=()
282
+ local other=()
283
+
284
+ while IFS='|' read -r hash subject author date; do
285
+ local subject_lower=$(echo "$subject" | tr '[:upper:]' '[:lower:]')
286
+
287
+ if [[ "$subject_lower" =~ ^(feat|feature)(\(.*\))?:.*$ ]]; then
288
+ added+=("- $(echo "$subject" | sed 's/^[Ff]eat[ure]*(\([^)]*\)): *//' | sed 's/^[Ff]eat[ure]*: *//')")
289
+ elif [[ "$subject_lower" =~ ^(fix|bugfix)(\(.*\))?:.*$ ]]; then
290
+ fixed+=("- $(echo "$subject" | sed 's/^[Ff]ix[bugfix]*(\([^)]*\)): *//' | sed 's/^[Ff]ix[bugfix]*: *//')")
291
+ elif [[ "$subject_lower" =~ ^(perf|performance)(\(.*\))?:.*$ ]]; then
292
+ changed+=("- Performance: $(echo "$subject" | sed 's/^[Pp]erf[ormance]*(\([^)]*\)): *//' | sed 's/^[Pp]erf[ormance]*: *//')")
293
+ elif [[ "$subject_lower" =~ ^(refactor)(\(.*\))?:.*$ ]]; then
294
+ changed+=("- Refactor: $(echo "$subject" | sed 's/^[Rr]efactor(\([^)]*\)): *//' | sed 's/^[Rr]efactor: *//')")
295
+ elif [[ "$subject_lower" =~ ^(style)(\(.*\))?:.*$ ]]; then
296
+ changed+=("- Style: $(echo "$subject" | sed 's/^[Ss]tyle(\([^)]*\)): *//' | sed 's/^[Ss]tyle: *//')")
297
+ elif [[ "$subject_lower" =~ ^(docs|doc)(\(.*\))?:.*$ ]]; then
298
+ changed+=("- Documentation: $(echo "$subject" | sed 's/^[Dd]ocs*(\([^)]*\)): *//' | sed 's/^[Dd]ocs*: *//')")
299
+ elif [[ "$subject_lower" =~ ^(chore)(\(.*\))?:.*$ ]]; then
300
+ changed+=("- $(echo "$subject" | sed 's/^[Cc]hore(\([^)]*\)): *//' | sed 's/^[Cc]hore: *//')")
301
+ elif [[ "$subject_lower" =~ ^(test)(\(.*\))?:.*$ ]]; then
302
+ changed+=("- Testing: $(echo "$subject" | sed 's/^[Tt]est(\([^)]*\)): *//' | sed 's/^[Tt]est: *//')")
303
+ elif [[ "$subject_lower" =~ ^(ci)(\(.*\))?:.*$ ]]; then
304
+ changed+=("- CI/CD: $(echo "$subject" | sed 's/^[Cc][Ii](\([^)]*\)): *//' | sed 's/^[Cc][Ii]: *//')")
305
+ elif [[ "$subject_lower" =~ ^(build)(\(.*\))?:.*$ ]]; then
306
+ changed+=("- Build: $(echo "$subject" | sed 's/^[Bb]uild(\([^)]*\)): *//' | sed 's/^[Bb]uild: *//')")
307
+ elif [[ "$subject_lower" =~ ^(security|sec)(\(.*\))?:.*$ ]]; then
308
+ security+=("- $(echo "$subject" | sed 's/^[Ss]ec[urity]*(\([^)]*\)): *//' | sed 's/^[Ss]ec[urity]*: *//')")
309
+ elif [[ "$subject_lower" =~ deprecat ]]; then
310
+ deprecated+=("- $(echo "$subject")")
311
+ elif [[ "$subject_lower" =~ ^(remove|rm)(\(.*\))?:.*$ ]]; then
312
+ removed+=("- $(echo "$subject" | sed 's/^[Rr]m*[emove]*(\([^)]*\)): *//' | sed 's/^[Rr]m*[emove]*: *//')")
313
+ else
314
+ other+=("- $subject")
315
+ fi
316
+ done <<< "$commits"
317
+
318
+ # Create changelog entry
319
+ local changelog_entry=""
320
+ local date=$(date +"%Y-%m-%d")
321
+
322
+ changelog_entry+="## [$new_version] - $date\n\n"
323
+
324
+ if [[ ${#added[@]} -gt 0 ]]; then
325
+ changelog_entry+="### Added\n"
326
+ for item in "${added[@]}"; do
327
+ changelog_entry+="$item\n"
328
+ done
329
+ changelog_entry+="\n"
330
+ fi
331
+
332
+ if [[ ${#changed[@]} -gt 0 ]]; then
333
+ changelog_entry+="### Changed\n"
334
+ for item in "${changed[@]}"; do
335
+ changelog_entry+="$item\n"
336
+ done
337
+ changelog_entry+="\n"
338
+ fi
339
+
340
+ if [[ ${#deprecated[@]} -gt 0 ]]; then
341
+ changelog_entry+="### Deprecated\n"
342
+ for item in "${deprecated[@]}"; do
343
+ changelog_entry+="$item\n"
344
+ done
345
+ changelog_entry+="\n"
346
+ fi
347
+
348
+ if [[ ${#removed[@]} -gt 0 ]]; then
349
+ changelog_entry+="### Removed\n"
350
+ for item in "${removed[@]}"; do
351
+ changelog_entry+="$item\n"
352
+ done
353
+ changelog_entry+="\n"
354
+ fi
355
+
356
+ if [[ ${#fixed[@]} -gt 0 ]]; then
357
+ changelog_entry+="### Fixed\n"
358
+ for item in "${fixed[@]}"; do
359
+ changelog_entry+="$item\n"
360
+ done
361
+ changelog_entry+="\n"
362
+ fi
363
+
364
+ if [[ ${#security[@]} -gt 0 ]]; then
365
+ changelog_entry+="### Security\n"
366
+ for item in "${security[@]}"; do
367
+ changelog_entry+="$item\n"
368
+ done
369
+ changelog_entry+="\n"
370
+ fi
371
+
372
+ if [[ ${#other[@]} -gt 0 ]]; then
373
+ changelog_entry+="### Other\n"
374
+ for item in "${other[@]}"; do
375
+ changelog_entry+="$item\n"
376
+ done
377
+ changelog_entry+="\n"
378
+ fi
379
+
380
+ # Update CHANGELOG.md
381
+ if [[ "$DRY_RUN" != true ]]; then
382
+ # Create backup
383
+ cp CHANGELOG.md CHANGELOG.md.bak
384
+
385
+ # Insert new entry after the first line (preserving header)
386
+ {
387
+ head -n 1 CHANGELOG.md
388
+ echo ""
389
+ echo -e "$changelog_entry"
390
+ tail -n +2 CHANGELOG.md
391
+ } > CHANGELOG.md.tmp && mv CHANGELOG.md.tmp CHANGELOG.md
392
+
393
+ rm CHANGELOG.md.bak 2>/dev/null || true
394
+ fi
395
+
396
+ info "Generated changelog entry for version $new_version"
397
+ echo -e "${PURPLE}Changelog Preview:${NC}"
398
+ echo -e "$changelog_entry" | head -20
399
+
400
+ if [[ "$INTERACTIVE" == true ]]; then
401
+ echo -e "${YELLOW}Continue with this changelog? (y/N)${NC}"
402
+ read -r response
403
+ if [[ ! "$response" =~ ^[Yy]$ ]]; then
404
+ error "Changelog generation cancelled by user"
405
+ fi
406
+ fi
407
+ }
408
+
409
+ # Function to update version in files
410
+ update_version_files() {
411
+ local new_version="$1"
412
+
413
+ step "Updating version in files..."
414
+
415
+ if [[ "$DRY_RUN" == true ]]; then
416
+ info "Would update version to $new_version in:"
417
+ info " - lib/jekyll-theme-zer0/version.rb"
418
+ info " - package.json"
419
+ return 0
420
+ fi
421
+
422
+ # Update version.rb
423
+ sed -i.bak "s/VERSION = \".*\"/VERSION = \"$new_version\"/" lib/jekyll-theme-zer0/version.rb
424
+ rm lib/jekyll-theme-zer0/version.rb.bak 2>/dev/null || true
425
+
426
+ # Update package.json if it exists
427
+ if [[ -f "package.json" ]]; then
428
+ jq ".version = \"$new_version\"" package.json > package.json.tmp && mv package.json.tmp package.json
429
+ fi
430
+
431
+ success "Version files updated to $new_version"
432
+ }
433
+
434
+ # Function to run tests
435
+ run_tests() {
436
+ if [[ "$SKIP_TESTS" == true ]]; then
437
+ warn "Skipping tests as requested"
438
+ return 0
439
+ fi
440
+
441
+ step "Running test suite..."
442
+
443
+ if [[ "$DRY_RUN" == true ]]; then
444
+ info "Would run: bundle exec rspec"
445
+ return 0
446
+ fi
447
+
448
+ # Install dependencies
449
+ bundle install --quiet
450
+
451
+ # Run tests
452
+ if bundle exec rspec; then
453
+ success "All tests passed"
454
+ else
455
+ error "Tests failed. Fix issues before proceeding."
456
+ fi
457
+ }
458
+
459
+ # Function to build gem
460
+ build_gem() {
461
+ local version="$1"
462
+
463
+ step "Building gem..."
464
+
465
+ if [[ "$DRY_RUN" == true ]]; then
466
+ info "Would build jekyll-theme-zer0-${version}.gem"
467
+ return 0
468
+ fi
469
+
470
+ # Clean up old gem files
471
+ rm -f jekyll-theme-zer0-*.gem
472
+
473
+ # Validate gemspec
474
+ ruby -c jekyll-theme-zer0.gemspec > /dev/null
475
+
476
+ # Build gem
477
+ if gem build jekyll-theme-zer0.gemspec; then
478
+ success "Successfully built jekyll-theme-zer0-${version}.gem"
479
+
480
+ # Show gem contents summary
481
+ info "Gem contents summary:"
482
+ local file_count=$(tar -tzf "jekyll-theme-zer0-${version}.gem" | wc -l)
483
+ info " Total files: $file_count"
484
+ info " Gem size: $(ls -lh jekyll-theme-zer0-${version}.gem | awk '{print $5}')"
485
+ else
486
+ error "Failed to build gem"
487
+ fi
488
+ }
489
+
490
+ # Function to publish gem
491
+ publish_gem() {
492
+ local version="$1"
493
+
494
+ if [[ "$SKIP_PUBLISH" == true ]]; then
495
+ warn "Skipping gem publication as requested"
496
+ return 0
497
+ fi
498
+
499
+ step "Publishing gem to RubyGems..."
500
+
501
+ if [[ "$DRY_RUN" == true ]]; then
502
+ info "Would publish jekyll-theme-zer0-${version}.gem to RubyGems"
503
+ return 0
504
+ fi
505
+
506
+ # Check if version already exists
507
+ if gem list --remote jekyll-theme-zer0 | grep -q "jekyll-theme-zer0 (${version})"; then
508
+ error "Version ${version} already exists on RubyGems"
509
+ fi
510
+
511
+ # Publish
512
+ if confirm "Publish jekyll-theme-zer0-${version}.gem to RubyGems?"; then
513
+ if gem push "jekyll-theme-zer0-${version}.gem"; then
514
+ success "Successfully published to RubyGems"
515
+ info "Gem available at: https://rubygems.org/gems/jekyll-theme-zer0"
516
+ else
517
+ error "Failed to publish gem"
518
+ fi
519
+ else
520
+ warn "Gem publication cancelled by user"
521
+ fi
522
+ }
523
+
524
+ # Function to commit and tag
525
+ commit_and_tag() {
526
+ local version="$1"
527
+
528
+ step "Committing changes and creating tag..."
529
+
530
+ if [[ "$DRY_RUN" == true ]]; then
531
+ info "Would commit changes and create tag v$version"
532
+ return 0
533
+ fi
534
+
535
+ # Add files to git
536
+ git add lib/jekyll-theme-zer0/version.rb CHANGELOG.md
537
+ [[ -f "package.json" ]] && git add package.json
538
+
539
+ # Commit
540
+ git commit -m "chore: release version $version
541
+
542
+ - Version bump to $version
543
+ - Updated changelog with commit history
544
+ - Automated release via gem-publish script"
545
+
546
+ # Create tag
547
+ git tag -a "v$version" -m "Release version $version"
548
+
549
+ success "Created commit and tag v$version"
550
+ }
551
+
552
+ # Function to create GitHub release
553
+ create_github_release() {
554
+ local version="$1"
555
+
556
+ if [[ "$CREATE_GITHUB_RELEASE" != true ]]; then
557
+ warn "Skipping GitHub release creation as requested"
558
+ return 0
559
+ fi
560
+
561
+ step "Creating GitHub release..."
562
+
563
+ if [[ "$DRY_RUN" == true ]]; then
564
+ info "Would create GitHub release for v$version"
565
+ return 0
566
+ fi
567
+
568
+ # Check if gh CLI is available
569
+ if ! command -v gh &> /dev/null; then
570
+ warn "GitHub CLI (gh) not found. Skipping GitHub release creation."
571
+ info "You can create the release manually at: https://github.com/bamr87/zer0-mistakes/releases/new"
572
+ return 0
573
+ fi
574
+
575
+ # Extract changelog for this version
576
+ local release_notes=$(awk "/^## \[$version\]/{flag=1; next} /^## \[/{flag=0} flag" CHANGELOG.md)
577
+
578
+ # Create release
579
+ if gh release create "v$version" \
580
+ --title "Release v$version" \
581
+ --notes "$release_notes" \
582
+ "jekyll-theme-zer0-${version}.gem"; then
583
+ success "GitHub release created successfully"
584
+ else
585
+ warn "Failed to create GitHub release"
586
+ fi
587
+ }
588
+
589
+ # Function to push changes
590
+ push_changes() {
591
+ step "Pushing changes to repository..."
592
+
593
+ if [[ "$DRY_RUN" == true ]]; then
594
+ info "Would push changes and tags to origin"
595
+ return 0
596
+ fi
597
+
598
+ if confirm "Push changes and tags to repository?"; then
599
+ git push origin main --tags
600
+ success "Changes and tags pushed to repository"
601
+ else
602
+ warn "Repository push cancelled by user"
603
+ fi
604
+ }
605
+
606
+ # Function to cleanup
607
+ cleanup() {
608
+ step "Cleaning up temporary files..."
609
+
610
+ if [[ "$DRY_RUN" != true ]]; then
611
+ # Remove gem file after successful publication
612
+ if [[ "$SKIP_PUBLISH" != true ]] && [[ -f "jekyll-theme-zer0-${NEW_VERSION}.gem" ]]; then
613
+ if confirm "Remove local gem file?"; then
614
+ rm -f "jekyll-theme-zer0-${NEW_VERSION}.gem"
615
+ info "Local gem file removed"
616
+ fi
617
+ fi
618
+ fi
619
+ }
620
+
621
+ # Main execution function
622
+ main() {
623
+ # Check if help was requested
624
+ if [[ "${SHOW_HELP:-false}" == true ]]; then
625
+ show_usage
626
+ exit 0
627
+ fi
628
+
629
+ if [[ "$AUTOMATED_RELEASE" == true ]]; then
630
+ echo -e "${CYAN}🤖 Automated Release Mode${NC}"
631
+ echo -e "${CYAN}Version: $VERSION_TYPE bump (automatic)${NC}"
632
+ else
633
+ echo -e "${PURPLE}🚀 Comprehensive Gem Publication Script${NC}"
634
+ echo -e "${PURPLE}Version: $VERSION_TYPE bump${NC}"
635
+ fi
636
+ echo ""
637
+
638
+ # Validate environment
639
+ validate_environment
640
+
641
+ # Get current version
642
+ local current_version=$(get_current_version)
643
+ info "Current version: $current_version"
644
+
645
+ # Calculate new version
646
+ local new_version=$(calculate_new_version "$current_version" "$VERSION_TYPE")
647
+ info "New version: $new_version"
648
+
649
+ # Get last version tag for changelog
650
+ local last_tag=$(get_last_version_tag)
651
+ info "Last version tag: $last_tag"
652
+
653
+ if [[ "$DRY_RUN" == true ]]; then
654
+ echo -e "${YELLOW}🔍 DRY RUN MODE - No changes will be made${NC}"
655
+ echo ""
656
+ fi
657
+
658
+ # Show summary
659
+ echo -e "${CYAN}📋 Release Summary:${NC}"
660
+ echo -e " Current Version: $current_version"
661
+ echo -e " New Version: $new_version"
662
+ echo -e " Version Type: $VERSION_TYPE"
663
+ echo -e " Last Tag: $last_tag"
664
+ echo ""
665
+
666
+ if [[ "$INTERACTIVE" == true ]] && ! confirm "Continue with release?"; then
667
+ info "Release cancelled by user"
668
+ exit 0
669
+ fi
670
+
671
+ # Execute release workflow
672
+ if [[ "$SKIP_CHANGELOG" != true ]]; then
673
+ generate_changelog "$current_version" "$new_version" "$last_tag"
674
+ fi
675
+
676
+ update_version_files "$new_version"
677
+ run_tests
678
+ build_gem "$new_version"
679
+ commit_and_tag "$new_version"
680
+ publish_gem "$new_version"
681
+ create_github_release "$new_version"
682
+ push_changes
683
+ cleanup
684
+
685
+ # Final success message
686
+ echo ""
687
+ echo -e "${GREEN}🎉 Release Complete!${NC}"
688
+ echo -e "${GREEN}Version $new_version has been successfully released${NC}"
689
+ echo ""
690
+ echo -e "${CYAN}📋 Release Information:${NC}"
691
+ echo -e " 📦 RubyGems: https://rubygems.org/gems/jekyll-theme-zer0"
692
+ echo -e " 🏷️ GitHub Release: https://github.com/bamr87/zer0-mistakes/releases/tag/v$new_version"
693
+ echo -e " 🔄 Repository: https://github.com/bamr87/zer0-mistakes"
694
+ echo ""
695
+
696
+ export NEW_VERSION="$new_version"
697
+ }
698
+
699
+ # Run main function
700
+ main "$@"