How to Manually Release a Gem in rubygems.com
I’ve always wanted to create a gem that becomes popular enough to be well known and everybody speaks about it. Unfortunately, until now it has been only a dream. In the meantime, I’ve learned how to create and release gems manually and I’d like to share that with you. Maybe somehow your gem could be the next most popular gem and I’ll be super proud of that if your first step was to read this blog post.
Index
Create a Gem
While writing the Release a Gem Manually section I realized that you may not have your gem yet. That is the reason I’ll share with you how to create it.
Everywhere you see
fastruby_test
, feel free to replace it with your gem’s name
A gem could be generated by manually creating each file or using a command. Let’s use the command.
bundle gem fastruby_test
The above command will prompt you with several questions and the answers those depend on your preferences. In our case we picked:
- RSpec for testing
- GitHub for CI
- MIT as license
- Yes, include the changelog file
- Add rubocop as a linter.
tree
.
├── bin
│ ├── console
│ └── setup
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── fastruby_test.gemspec
├── Gemfile
├── lib
│ ├── fastruby_test
│ │ └── version.rb
│ └── fastruby_test.rb
├── LICENSE.txt
├── Rakefile
├── README.md
└── spec
├── fastruby_test_spec.rb
└── spec_helper.rb
4 directories, 13 files
Nice! You just created a new Gem! Isn’t it incredibly easy? It’s time to prepare the gem to be deployed.
Let’s run the RSpec tests and linter with the rake
command
cd fastruby_test
rake
It returns that the fastruby_test.gemspec
is not valid.
You need to open that file and change the items that have the TODO:
word, like so:
# frozen_string_literal: true
require_relative "lib/fastruby_test/version"
Gem::Specification.new do |spec|
spec.name = "fastruby_test"
spec.version = FastrubyTest::VERSION
spec.authors = ["Juan Vasquez"]
spec.email = ["juan@ombulabs.com"]
spec.summary = "This is an interesting gem"
spec.description = "This is an interesting gem's description"
spec.homepage = "https://github.com/fastruby/fastruby_test"
spec.license = "MIT"
spec.required_ruby_version = ">= 2.6.0"
spec.metadata["allowed_push_host"] = "https://rubygems.org"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
spec.files = Dir.chdir(File.expand_path(__dir__)) do
`git ls-files -z`.split("\x0").reject do |f|
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
end
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
# Uncomment to register a new dependency of your gem
# spec.add_dependency "example-gem", "~> 1.0"
# For more information and examples about making a new gem, checkout our
# guide at: https://bundler.io/guides/creating_gem.html
end
Once you fixed the gemspec
file,
run the tests again and you will see that the test is still failing.
This is due to the scaffold creating a failing test by default.
Let’s remove it or fix it.
# frozen_string_literal: true
RSpec.describe FastrubyTest do
it "has a version number" do
expect(FastrubyTest::VERSION).not_to be nil
end
it "does something useful" do
expect(true).to eq(true)
end
end
$ rspec
FastrubyTest
has a version number
does something useful
Finished in 0.00172 seconds (files took 0.05799 seconds to load)
2 examples, 0 failures
Release a Gem Manually
You’ll need to have a rubygems.org account. If you haven’t created one yet, here you have the link to do it.
Then we need to login to rubygems.org from the command line, by running the following command:
gem signin
It will prompt you to answer some questions, be aware that you cannot mark everything as y
.
Enter your RubyGems.org credentials.
Don't have an account yet? Create one at https://rubygems.org/sign_up
Email: me@example.com
Password: your_secure_password
API Key name [computer-name-20220727155644]:
Please select scopes you want to enable for the API key (y/n)
index_rubygems [y/N]: y
push_rubygem [y/N]: y
yank_rubygem [y/N]: y
add_owner [y/N]: y
remove_owner [y/N]: y
access_webhooks [y/N]: y
show_dashboard [y/N]: n
You have enabled multi-factor authentication. Please enter OTP code.
Code: 000000
Signed in with API key: computer-name-20220727155644.
Just to confirm you added it successfully, go to the following route https://rubygems.org/profile/api_keys and the new api key’s name should be there.
The next step is to build the gem, running the following command:
gem build fastruby_test
The gem build fastruby_test
command created a new file,
in my case it’s called fastruby_test-0.1.0.gem
(the version could vary on your side).
Let’s push it to the https://rubygems.org page with the following command:
gem push fastruby_test-0.1.0.gem
Pushing gem to https://rubygems.org...
Successfully registered gem: fastruby_test (0.1.1)
If everything was good, you should be able to navigate to the gem url https://rubygems.org/gems/fastruby_test .
And we are done. That’s it. We are planning on posting an automated release in the future, let’s keep in touch if you are interested.
Extra Info
Naming a Gem
I wanted to jump into the Generate a Gem section but naming your gem is a super important step. Before you pick a name for your gem, do a quick search on https://rubygems.org/ and https://github.com/ to see if someone else has taken it or run the following command:
gem search next_rails
# where `next_rails` is your desired gem name
Every published gem must have a unique name.
Removing a Gem
Because of several reasons you may want/need to remove a gem’s release. Take into account that we won’t be able to use the same previous gem’s version. In our case it was only for learning purposes.
You can execute the following command:
gem yank fastruby_test -v 0.1.1
Yanking gem from https://rubygems.org...
Successfully deleted gem: fastruby_test (0.1.1)