skip to content

In RubyGems, what is a .gemspec file, which fields must it set, and what does gem build produce from it?

level: juniorimportance: must knowfreq 52%

answer

  1. Gem::Specification.new block
  2. name, version, summary, authors
  3. errors stop the build, warnings do not
  4. name-version.gem
  5. gem build --strict

basics

~10 s

A .gemspec is Ruby code that builds a Gem::Specification: name, version, summary, authors, files, require_paths and dependencies. gem build validates it and packages the listed files into name-version.gem, the file gem push uploads.

solid answer

~30 s

A `.gemspec` is a Ruby file whose `Gem::Specification.new do |spec| ... end` block describes the gem. RubyGems **requires** `name`, `version` and `summary`, a non-empty `authors`, and at least one entry in `require_paths` (default `["lib"]`); `files` lists what gets packaged. `gem build hue_palette.gemspec` validates the spec: missing required values, a listed path that is not a file, or TODO placeholders are **errors**, while no `license`, no `homepage` or no `required_ruby_version` are **warnings**. On success it prints `Successfully built RubyGem` and writes `hue_palette-1.0.0.gem`. `--strict` turns warnings into errors, and `metadata` adds string links such as `source_code_uri` that rubygems.org shows.

code

ruby · 18 lines
ruby
# hue_palette.gemspec
require_relative "lib/hue_palette/version"   # defines HuePalette::VERSION = "1.0.0"

Gem::Specification.new do |spec|
  spec.name     = "hue_palette"
  spec.version  = HuePalette::VERSION
  spec.authors  = ["Ada Example"]
  spec.summary  = "Build harmonious colour palettes from a base hue"
  spec.homepage = "https://example.com/hue_palette"
  spec.license  = "MIT"
  spec.required_ruby_version = ">= 3.2"

  spec.files         = Dir["lib/**/*.rb", "LICENSE.txt", "README.md"]
  spec.require_paths = ["lib"]

  spec.metadata["source_code_uri"] = "https://example.com/hue_palette/src"
  spec.metadata["changelog_uri"]   = "https://example.com/hue_palette/CHANGELOG.md"
end

go deeper

for a junior

Know that a gemspec is Ruby code building a Gem::Specification, the required fields, and that gem build writes name-version.gem.

for a middle

Explain which problems are build errors versus warnings, how metadata links work, and how to inspect a built .gem before pushing it.

for a senior

Make release builds strict, verify the packaged file list, and keep the gemspec free of side effects so every machine builds the same archive.

for a principal

Set a team standard for gemspec fields and metadata across many gems, and decide which validations release automation must enforce.

## What a gemspec is A **gem** is a packaged Ruby library, and its **specification** says what it is: name, version, authors, which files it contains, which directory to load code from, what it depends on and which Ruby it supports. The `.gemspec` file is plain **Ruby code** that builds a `Gem::Specification` object: - the file usually sits at the root of the project, named after the gem (`hue_palette.gemspec`); - it typically `require_relative`s the gem's `version.rb`, so the version lives in one place (`HuePalette::VERSION`); - because it is Ruby, it can compute values, for example building `files` from `Dir[...]` or from `git ls-files`. ## Required and recommended fields `Gem::Specification` validation distinguishes **errors**, which stop the build, from **warnings**, which only print. | Field | If missing or wrong | |---|---| | `name`, `version`, `summary` | error: `missing value for attribute ...` | | `authors` | error: `authors may not be empty` | | `require_paths` | error if empty; default is `["lib"]` | | `files` | warning `no files specified`; an entry that is not a file is an error | | `license` / `licenses` | warning recommending an SPDX identifier | | `homepage` | warning `no homepage specified`; must be an HTTP(S) URI if set | | `required_ruby_version` | warning asking you to state the oldest supported Ruby | Other checks worth knowing: - An author, email, summary or description that still starts with a `TODO` or `FIXME` placeholder is an **error**, which catches half-edited generated gemspecs. - A `description` identical to the `summary` is a warning. - The gem must not list its own `.gem` file in `files`. ## metadata `spec.metadata` is a Hash of **string keys to string values** (keys up to 128 bytes, values up to 1024). RubyGems recognises link keys such as `homepage_uri`, `source_code_uri`, `changelog_uri`, `documentation_uri`, `bug_tracker_uri`, `wiki_uri`, `mailing_list_uri`, `download_uri` and `funding_uri`; each must be a valid `http(s)` URL, and rubygems.org shows them on the gem's page. Other keys, such as `allowed_push_host` and `rubygems_mfa_required`, control publishing. ## What gem build does `gem build hue_palette.gemspec` (or plain `gem build` when exactly one gemspec is in the current directory): 1. loads the gemspec, which runs its Ruby code; 2. validates it, printing warnings and stopping on errors; 3. writes a `.gem` archive holding the files from `files` plus the serialised specification; 4. prints `Successfully built RubyGem`, the name, the version and the file name, `hue_palette-1.0.0.gem`. Useful options: - `--strict` treats every warning as an error (`specification has warnings`), a good setting for release automation. - `--force` skips validation entirely, which is rarely a good idea. - `-o, --output FILE` chooses the output file name. RubyGems 4.0 removed the old `-C` option of `gem build`; change into the directory first instead. ## Common gemspec mistakes - **Leaving generated placeholders.** A summary or author that still begins with `TODO` fails the build; a description identical to the summary only warns. - **A files list that matches nothing.** `Dir["lib/**/*.rb"]` in a gem whose code lives elsewhere produces an almost empty gem, with at most a `no files specified` warning. - **Loading the gem's own code.** `require "hue_palette"` inside the gemspec runs library code (and its dependencies) at build time; `require_relative` of just the version file avoids that. - **Side effects.** Shelling out to tools the build machine may lack, or reading environment variables, makes builds differ between machines. - **Symbols in metadata.** `spec.metadata[:source_code_uri] = ...` fails validation, because keys must be Strings. ## Checking the result before publishing - `gem spec hue_palette-1.0.0.gem` prints the specification stored inside the archive. - `gem unpack hue_palette-1.0.0.gem` extracts it so you can see exactly which files shipped. - `gem install ./hue_palette-1.0.0.gem` installs the local file for a smoke test. Only after that does `gem push hue_palette-1.0.0.gem` upload it to rubygems.org.

  • Why is a .gemspec written in Ruby rather than as a static data file?
    Because values are often computed: the version comes from `require_relative "lib/.../version"`, and `files` is built from `Dir[...]` or `git ls-files`. The flip side is that the gemspec runs as code whenever it is loaded, so it should stay free of side effects and must not depend on anything the build machine lacks.
  • What does gem build --strict change?
    Normally warnings, such as a missing license, homepage or `required_ruby_version`, are printed and the build still succeeds. With `--strict`, any warning fails the build with `specification has warnings`, which suits release automation that should never publish a gem with an incomplete spec.

saying these in an interview costs you the question

  • Thinks a gemspec is YAML or JSON rather than Ruby code
  • Believes license and homepage are required by gem build
  • Assumes gem build packages every file in the project directory
  • Treats metadata values as any Ruby object rather than strings
  • Still uses gem build -C, removed in RubyGems 4.0