Open-Source Wikis

/

Ruby

/

How to contribute

/

Development workflow

ruby/ruby

Development workflow

The day-to-day cycle of editing, building, and testing in ruby/ruby.

Branching

  • The default branch is master. There is no main.
  • Stable release branches use the ruby_X_Y naming convention (ruby_3_4, ruby_3_3, ruby_3_2, ...).
  • For your own work, create a topic branch off master. The maintainers don't require a particular naming scheme.

A typical edit-build-test loop

# 1. Edit source, e.g. compile.c
$EDITOR compile.c

# 2. Incremental build (parallel jobs).
make -j$(nproc)

# 3. Smoke test
make btest

# 4. Targeted test
./tool/runruby.rb test/ruby/test_compile.rb
# or
make test-all TESTS="test/ruby/test_compile.rb"

# 5. Spec test (slower)
make test-spec

make miniruby rebuilds just the bootstrap interpreter — useful while iterating on the parser or VM since a full make rebuilds all extensions.

Faster iteration tricks

  • ./miniruby -I./lib -I. runs the in-tree interpreter without installing. Most pure-Ruby tests work, but C extensions don't load.
  • tool/runruby.rb wraps ./ruby with the right -I flags so require 'fileutils' etc. find the in-tree library.
  • make run runs tool/runruby.rb for you with whatever's in RUNOPT. make run RUNOPT="-e 'p RUBY_DESCRIPTION'" is a common pattern.
  • make exam is check + linting + leak checks. Pre-PR sanity check.
  • make update-deps regenerates the per-file dependency lists in depend. Touching most C files requires this.
  • make update-bundled_gems refreshes the pinned versions in gems/bundled_gems.

Touching the parser

If you modify parse.y:

make srcs    # regenerates parse.c via Lrama
make

If you modify Prism (prism/):

  • The C sources under prism/ are mostly upstream from the standalone ruby/prism repo.
  • Local edits should be paired with an upstream PR; tool/sync_default_gems.rb prism re-syncs.

Touching VM instructions

If you modify insns.def:

make srcs
make
make btest

tool/ruby_vm/ regenerates vm_exec.c, vmtc.inc, the JIT interface, and per-instruction dispatch helpers. Touching insns.def therefore touches a lot of generated code; run the whole bootstrap test suite afterwards.

Touching YJIT / ZJIT

yjit/ and zjit/ are Cargo workspaces. To rebuild without going through make:

cargo build --release -p yjit
cargo build --release -p zjit

But the production build ties Rust output back through Make:

make -j$(nproc)              # builds yjit + zjit static libs and links them in
make test-all TESTS="test/ruby/test_yjit.rb"

ZJIT has helper scripts:

  • tool/zjit_bisect.rb — bisect a misbehaving JIT change.
  • tool/zjit_diff.rb — diff IR between two compilations.
  • tool/zjit_iongraph.rb (+ zjit_iongraph.html) — render the IR graph in a browser.

Pull request checklist

  1. Build with default options succeeds.
  2. make check passes.
  3. New tests in test/ or spec/ruby/ if you changed behaviour.
  4. RDoc on any new Ruby API. Doxygen-style comments on any new C API in include/ruby/.
  5. NEWS.md updated for user-visible changes.
  6. PR title matches the convention used in recent commits (e.g., [ruby/<gem>] ... for default-gem syncs).
  7. Sign-off via your normal git config — there's no DCO requirement.

Default-gem PRs

Many libraries in lib/ (e.g., lib/optparse.rb, lib/uri/, lib/prism/) are vendored from upstream gem repos. Patches to those libraries should normally be opened against the upstream repo (e.g., ruby/optparse) and then synced into this tree by the maintainer who runs tool/sync_default_gems.rb. Patches that go directly to lib/ for those gems are usually closed with a pointer to upstream.

The list of synced gems and their upstream repos is at the top of tool/sync_default_gems.rb in the REPOSITORIES hash.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Development workflow – Ruby wiki | Factory