Skip to content

Commit a28e3d6

Browse files
authored
Add simplified gem release process (#187)
* Add simplified gem release process This commit adds a streamlined release process for the cypress-on-rails gem, removing the npm package release steps that were present in the react_on_rails version. Key changes: - Add lib/tasks/release.rake with gem-only release automation - Add docs/RELEASE.md with comprehensive release documentation - Simplify process by removing release-it and npm publishing steps - Keep essential features: version bumping, git tagging, and gem publishing The release task handles: - Checking for uncommitted changes - Pulling latest changes - Bumping version using gem-release - Publishing to RubyGems with OTP support - Providing post-release instructions for CHANGELOG updates
1 parent 5cea37d commit a28e3d6

File tree

3 files changed

+236
-0
lines changed

3 files changed

+236
-0
lines changed

docs/RELEASE.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Release Process
2+
3+
This document describes how to release a new version of the `cypress-on-rails` gem.
4+
5+
## Prerequisites
6+
7+
1. Install the `gem-release` gem globally:
8+
```bash
9+
gem install gem-release
10+
```
11+
12+
2. Ensure you have write access to the rubygems.org package
13+
14+
3. Set up two-factor authentication (2FA) for RubyGems and have your OTP generator ready
15+
16+
## Release Steps
17+
18+
### 1. Prepare for Release
19+
20+
Ensure your working directory is clean:
21+
```bash
22+
git status
23+
```
24+
25+
If you have uncommitted changes, commit or stash them first.
26+
27+
### 2. Pull Latest Changes
28+
29+
```bash
30+
git pull --rebase
31+
```
32+
33+
### 3. Run the Release Task
34+
35+
To release a specific version:
36+
```bash
37+
rake release[1.19.0]
38+
```
39+
40+
To automatically bump the patch version:
41+
```bash
42+
rake release
43+
```
44+
45+
To perform a dry run (without actually publishing):
46+
```bash
47+
rake release[1.19.0,true]
48+
```
49+
50+
### 4. Enter Your OTP
51+
52+
When prompted, enter your one-time password (OTP) from your authenticator app for RubyGems.
53+
54+
If you get an error during gem publishing, you can run `gem release` manually to retry.
55+
56+
### 5. Update the CHANGELOG
57+
58+
After successfully publishing the gem, update the CHANGELOG:
59+
60+
```bash
61+
bundle exec rake update_changelog
62+
# This will:
63+
# - Add a new version header with the release date
64+
# - Add version comparison links
65+
# - Prompt you to move content from [Unreleased] to the new version
66+
67+
# Edit CHANGELOG.md to move unreleased changes to the new version section
68+
git commit -a -m 'Update CHANGELOG.md'
69+
git push
70+
```
71+
72+
## Version Numbering
73+
74+
Follow [Semantic Versioning](https://semver.org/):
75+
76+
- **Major version** (X.0.0): Breaking changes
77+
- **Minor version** (0.X.0): New features, backwards compatible
78+
- **Patch version** (0.0.X): Bug fixes, backwards compatible
79+
- **Pre-release versions**: Use dot notation, not dashes (e.g., `2.0.0.beta.1`, not `2.0.0-beta.1`)
80+
81+
## What the Release Task Does
82+
83+
The release task automates the following steps:
84+
85+
1. Checks for uncommitted changes (will abort if found)
86+
2. Pulls the latest changes from the repository
87+
3. Bumps the version number in `lib/cypress_on_rails/version.rb`
88+
4. Creates a git commit with the version bump
89+
5. Creates a git tag for the new version
90+
6. Pushes the commit and tag to GitHub
91+
7. Builds the gem
92+
8. Publishes the gem to RubyGems
93+
94+
## Troubleshooting
95+
96+
### Authentication Error
97+
98+
If you get an authentication error with RubyGems:
99+
1. Verify your OTP is correct and current
100+
2. Ensure your RubyGems API key is valid
101+
3. Run `gem release` manually to retry
102+
103+
### Version Already Exists
104+
105+
If the version already exists on RubyGems:
106+
1. Bump to a higher version number
107+
2. Or fix the version in `lib/cypress_on_rails/version.rb` and try again
108+
109+
### Uncommitted Changes Error
110+
111+
If you have uncommitted changes:
112+
1. Review your changes with `git status`
113+
2. Commit them with `git commit -am "Your message"`
114+
3. Or stash them with `git stash`
115+
4. Then retry the release
116+
117+
## Post-Release
118+
119+
After releasing:
120+
121+
1. Announce the release on relevant channels (Slack, forum, etc.)
122+
2. Update any documentation that references version numbers
123+
3. Consider creating a GitHub release with release notes

lib/tasks/release.rake

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# frozen_string_literal: true
2+
3+
desc("Releases the gem using the given version.
4+
5+
IMPORTANT: the gem version must be in valid rubygem format (no dashes).
6+
7+
This task depends on the gem-release ruby gem which is installed via `bundle install`
8+
9+
1st argument: The new version in rubygem format (no dashes). Pass no argument to
10+
automatically perform a patch version bump.
11+
2nd argument: Perform a dry run by passing 'true' as a second argument.
12+
13+
Example: `rake release[1.19.0,false]`")
14+
task :release, %i[gem_version dry_run] do |_t, args|
15+
def sh_in_dir(dir, command)
16+
puts "Running in #{dir}: #{command}"
17+
system("cd #{dir} && #{command}") || raise("Command failed: #{command}")
18+
end
19+
20+
def gem_root
21+
File.expand_path('..', __dir__)
22+
end
23+
24+
# Check if there are uncommitted changes
25+
unless `git status --porcelain`.strip.empty?
26+
raise "You have uncommitted changes. Please commit or stash them before releasing."
27+
end
28+
29+
args_hash = args.to_hash
30+
is_dry_run = args_hash[:dry_run] == 'true'
31+
gem_version = args_hash.fetch(:gem_version, "")
32+
33+
# See https://github.com/svenfuchs/gem-release
34+
sh_in_dir(gem_root, "git pull --rebase")
35+
sh_in_dir(gem_root, "gem bump --no-commit #{%(--version #{gem_version}) unless gem_version.strip.empty?}")
36+
37+
# Release the new gem version
38+
puts "Carefully add your OTP for Rubygems. If you get an error, run 'gem release' again."
39+
sh_in_dir(gem_root, "gem release") unless is_dry_run
40+
41+
msg = <<~MSG
42+
Once you have successfully published, update CHANGELOG.md:
43+
44+
bundle exec rake update_changelog
45+
# Edit CHANGELOG.md to move unreleased changes to the new version section
46+
git commit -a -m 'Update CHANGELOG.md'
47+
git push
48+
MSG
49+
puts msg
50+
end

lib/tasks/update_changelog.rake

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# frozen_string_literal: true
2+
3+
require "English"
4+
5+
desc "Updates CHANGELOG.md inserting headers for the new version.
6+
7+
Argument: Git tag. Defaults to the latest tag."
8+
9+
task :update_changelog, %i[tag] do |_, args|
10+
tag = args[:tag] || `git describe --tags --abbrev=0`.strip
11+
12+
# Remove 'v' prefix if present (e.g., v1.18.0 -> 1.18.0)
13+
version = tag.start_with?('v') ? tag[1..-1] : tag
14+
anchor = "[#{version}]"
15+
16+
changelog = File.read("CHANGELOG.md")
17+
18+
if changelog.include?(anchor)
19+
puts "Tag #{version} is already documented in CHANGELOG.md, update manually if needed"
20+
next
21+
end
22+
23+
tag_date_output = `git show -s --format=%cs #{tag} 2>&1`
24+
if $CHILD_STATUS.success?
25+
tag_date = tag_date_output.split("\n").last.strip
26+
else
27+
abort("Failed to find tag #{tag}")
28+
end
29+
30+
# After "## [Unreleased]", insert new version header
31+
unreleased_section = "## [Unreleased]"
32+
new_version_header = "\n\n## #{anchor} - #{tag_date}"
33+
34+
if changelog.include?(unreleased_section)
35+
changelog.sub!(unreleased_section, "#{unreleased_section}#{new_version_header}")
36+
else
37+
abort("Could not find '## [Unreleased]' section in CHANGELOG.md")
38+
end
39+
40+
# Find and update version comparison links at the bottom
41+
# Pattern: [1.18.0]: https://github.com/shakacode/cypress-playwright-on-rails/compare/v1.17.0...v1.18.0
42+
compare_link_prefix = "https://github.com/shakacode/cypress-playwright-on-rails/compare"
43+
44+
# Find the last version link to determine the previous version
45+
last_version_match = changelog.match(/\[(\d+\.\d+\.\d+(?:\.\w+)?)\]:.*?compare\/v(\d+\.\d+\.\d+(?:\.\w+)?)\.\.\.v(\d+\.\d+\.\d+(?:\.\w+)?)/)
46+
47+
if last_version_match
48+
last_version = last_version_match[1]
49+
# Add new version link at the top of the version list
50+
new_link = "#{anchor}: #{compare_link_prefix}/v#{last_version}...v#{version}"
51+
# Insert after the "<!-- Version diff reference list -->" comment
52+
changelog.sub!("<!-- Version diff reference list -->", "<!-- Version diff reference list -->\n#{new_link}")
53+
else
54+
puts "Warning: Could not find version comparison links. You may need to add the link manually."
55+
end
56+
57+
File.write("CHANGELOG.md", changelog)
58+
puts "Updated CHANGELOG.md with an entry for #{version}"
59+
puts "\nNext steps:"
60+
puts "1. Edit CHANGELOG.md to add release notes under the [#{version}] section"
61+
puts "2. Move content from [Unreleased] to [#{version}] if applicable"
62+
puts "3. Review and commit the changes"
63+
end

0 commit comments

Comments
 (0)