rules.md

March 3, 2026 ยท View on GitHub

Public API for rules

rb_binary

load("@rules_ruby//ruby:defs.bzl", "rb_binary")

rb_binary(name, deps, srcs, data, coverage_filters, env, env_inherit, main, ruby)

Runs a Ruby binary.

Suppose you have the following Ruby gem, where rb_library() is used in BUILD files to define the packages for the gem.

|-- BUILD
|-- Gemfile
|-- WORKSPACE
|-- gem.gemspec
`-- lib
    |-- BUILD
    |-- gem
    |   |-- BUILD
    |   |-- add.rb
    |   |-- subtract.rb
    |   `-- version.rb
    `-- gem.rb

One of the files can be run as a Ruby script:

lib/gem/version.rb:

module GEM
  VERSION = '0.1.0'
end

puts "Version is: #{GEM::VERSION}" if __FILE__ == $PROGRAM_NAME

You can run this script by defining a target:

lib/gem/BUILD:

load("@rules_ruby//ruby:defs.bzl", "rb_binary", "rb_library")

rb_library(
    name = "version",
    srcs = ["version.rb"],
)

rb_binary(
    name = "print-version",
    args = ["lib/gem/version.rb"],
    deps = [":version"],
)
$ bazel run lib/gem:print-version
...
Version is: 0.1.0

You can also run general purpose Ruby scripts that rely on a Ruby interpreter in PATH:

lib/gem/add.rb:

#!/usr/bin/env ruby

a, b = *ARGV
puts Integer(a) + Integer(b)

lib/gem/BUILD:

load("@rules_ruby//ruby:defs.bzl", "rb_binary", "rb_library")

rb_library(
    name = "add",
    srcs = ["add.rb"],
)

rb_binary(
    name = "add-numbers",
    main = "add.rb",
    deps = [":add"],
)
$ bazel run lib/gem:add-numbers 1 2
...
3

You can also run a Ruby binary script available in Gemfile dependencies, by passing bin argument with a path to a Bundler binary stub:

BUILD:

load("@rules_ruby//ruby:defs.bzl", "rb_binary")

package(default_visibility = ["//:__subpackages__"])

rb_binary(
    name = "rake",
    main = "@bundle//bin:rake",
    deps = [
        "//lib:gem",
        "@bundle",
    ],
)
$ bazel run :rake -- --version
...
rake, version 13.1.0

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsList of other Ruby libraries the target depends on.List of labelsoptional[]
srcsList of Ruby source files used to build the library.List of labelsoptional[]
dataList of runtime dependencies needed by a program that depends on this library.List of labelsoptional[]
coverage_filtersAdditional coverage filters to add to SimpleCov. Only applied during 'bazel coverage'.List of stringsoptional[]
envEnvironment variables to use during execution.

Supports $(location) expansion for targets from srcs, data and deps.
Dictionary: String -> Stringoptional{}
env_inheritList of environment variable names to be inherited by the test runner.List of stringsoptional[]
mainRuby script to run. It may also be a binary stub generated by Bundler. If omitted, it defaults to the Ruby interpreter.

Use a built-in args attribute to pass extra arguments to the script.
LabeloptionalNone
rubyOverride Ruby toolchain to use when running the script.LabeloptionalNone

rb_bundle_install

load("@rules_ruby//ruby:defs.bzl", "rb_bundle_install")

rb_bundle_install(name, srcs, env, gemfile, gemfile_lock, gems, jars, jars_path, ruby)

Installs Bundler dependencies from cached gems.

You normally don't need to call this rule directly as it's an internal one used by rb_bundle_fetch().

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
srcsList of Ruby source files used to build the library.List of labelsoptional[]
envEnvironment variables to use during installation.Dictionary: String -> Stringoptional{}
gemfileGemfile to install dependencies from.Labelrequired
gemfile_lockGemfile.lock to install dependencies from.Labelrequired
gemsList of gems in vendor/cache that are used to install dependencies from.List of labelsrequired
jarsJAR dependencies for JRuby gems.List of labelsoptional[]
jars_pathPath to the directory containing JAR dependencies (set as JARS_HOME).Stringoptional""
rubyOverride Ruby toolchain to use when installing the gem.LabeloptionalNone

rb_gem

load("@rules_ruby//ruby:defs.bzl", "rb_gem")

rb_gem(name, gem)

Exposes a Ruby gem file.

You normally don't need to call this rule directly as it's an internal one used by rb_bundle_fetch().

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
gemGem file.Labelrequired

rb_gem_build

load("@rules_ruby//ruby:defs.bzl", "rb_gem_build")

rb_gem_build(name, deps, srcs, data, bundle_env, gemspec, ruby)

Builds a Ruby gem.

Suppose you have the following Ruby gem, where rb_library() is used in BUILD files to define the packages for the gem.

|-- BUILD
|-- Gemfile
|-- WORKSPACE
|-- gem.gemspec
`-- lib
    |-- BUILD
    |-- gem
    |   |-- BUILD
    |   |-- add.rb
    |   |-- subtract.rb
    |   `-- version.rb
    `-- gem.rb

And a RubyGem specification is:

gem.gemspec:

root = File.expand_path(__dir__)
$LOAD_PATH.push(File.expand_path('lib', root))
require 'gem/version'

Gem::Specification.new do |s|
  s.name = 'example'
  s.version = GEM::VERSION

  s.authors = ['Foo Bar']
  s.email = ['foobar@gmail.com']
  s.homepage = 'http://rubygems.org'
  s.license = 'MIT'

  s.summary = 'Example'
  s.description = 'Example gem'
  s.files = ['Gemfile'] + Dir['lib/**/*']

  s.require_paths = ['lib']
  s.add_dependency 'rake', '~> 10'
  s.add_development_dependency 'rspec', '~> 3.0'
  s.add_development_dependency 'rubocop', '~> 1.10'
end

You can now package everything into a .gem file by defining a target:

BUILD:

load("@rules_ruby//ruby:defs.bzl", "rb_gem_build")

package(default_visibility = ["//:__subpackages__"])

rb_gem_build(
    name = "gem-build",
    gemspec = "gem.gemspec",
    deps = [
        "//lib:gem",
        "@bundle",
    ],
)
$ bazel build :gem-build
...
  Successfully built RubyGem
  Name: example
  Version: 0.1.0
  File: example-0.1.0.gem
...

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsList of other Ruby libraries the target depends on.List of labelsoptional[]
srcsList of Ruby source files used to build the library.List of labelsoptional[]
dataList of runtime dependencies needed by a program that depends on this library.List of labelsoptional[]
bundle_envList of bundle environment variables to set when building the library.Dictionary: String -> Stringoptional{}
gemspecGemspec file to use for gem building.Labelrequired
rubyOverride Ruby toolchain to use when running the script.LabeloptionalNone

rb_gem_install

load("@rules_ruby//ruby:defs.bzl", "rb_gem_install")

rb_gem_install(name, gem, ruby)

Installs a built Ruby gem.

Suppose you have the following Ruby gem, where rb_library() is used in BUILD files to define the packages for the gem and rb_gem_build() is used to build a Ruby gem package from the sources.

|-- BUILD
|-- Gemfile
|-- WORKSPACE
|-- gem.gemspec
`-- lib
    |-- BUILD
    |-- gem
    |   |-- BUILD
    |   |-- add.rb
    |   |-- subtract.rb
    |   `-- version.rb
    `-- gem.rb

You can now install the built .gem file by defining a target:

BUILD:

load("@rules_ruby//ruby:defs.bzl", "rb_gem_build", "rb_gem_install")

package(default_visibility = ["//:__subpackages__"])

rb_gem_build(
    name = "gem-build",
    gemspec = "gem.gemspec",
    deps = ["//lib:gem"],
)

rb_gem_install(
    name = "gem-install",
    gem = ":gem-build",
)
$ bazel build :gem-install
...
Successfully installed example-0.1.0
1 gem installed
...

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
gemGem file to install.Labelrequired
rubyOverride Ruby toolchain to use when installing the gem.LabeloptionalNone

rb_gem_push

load("@rules_ruby//ruby:defs.bzl", "rb_gem_push")

rb_gem_push(name, deps, srcs, data, bundle_env, env, env_inherit, gem, ruby)

Pushes a built Ruby gem.

Suppose you have the following Ruby gem, where rb_library() is used in BUILD files to define the packages for the gem and rb_gem_build() is used to build a Ruby gem package from the sources.

|-- BUILD
|-- Gemfile
|-- WORKSPACE
|-- gem.gemspec
`-- lib
    |-- BUILD
    |-- gem
    |   |-- BUILD
    |   |-- add.rb
    |   |-- subtract.rb
    |   `-- version.rb
    `-- gem.rb

You can now release the built .gem file to RubyGems by defining a target:

BUILD:

load("@rules_ruby//ruby:defs.bzl", "rb_gem_build", "rb_gem_push")

package(default_visibility = ["//:__subpackages__"])

rb_gem_build(
    name = "gem-build",
    gemspec = "gem.gemspec",
    deps = ["//lib:gem"],
)

rb_gem_push(
    name = "gem-release",
    gem = ":gem-build",
)
$ bazel run :gem-release
...
Pushing gem to https://rubygems.org...
Successfully registered gem: example (0.1.0)

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsList of other Ruby libraries the target depends on.List of labelsoptional[]
srcsList of Ruby source files used to build the library.List of labelsoptional[]
dataList of runtime dependencies needed by a program that depends on this library.List of labelsoptional[]
bundle_envList of bundle environment variables to set when building the library.Dictionary: String -> Stringoptional{}
envEnvironment variables to use during execution.

Supports $(location) expansion for targets from srcs, data and deps.
Dictionary: String -> Stringoptional{}
env_inheritList of environment variable names to be inherited by the test runner.List of stringsoptional[]
gemGem file to push to RubyGems. You would usually use an output of rb_gem_build() target here.Labelrequired
rubyOverride Ruby toolchain to use when running the script.LabeloptionalNone

rb_library

load("@rules_ruby//ruby:defs.bzl", "rb_library")

rb_library(name, deps, srcs, data, bundle_env)

Defines a Ruby library.

Suppose you have the following Ruby gem:

|-- BUILD
|-- Gemfile
|-- WORKSPACE
|-- gem.gemspec
`-- lib
    |-- BUILD
    |-- gem
    |   |-- BUILD
    |   |-- add.rb
    |   |-- subtract.rb
    |   `-- version.rb
    `-- gem.rb

You can define packages for the gem source files:

BUILD:

load("@rules_ruby//ruby:defs.bzl", "rb_library")

package(default_visibility = ["//:__subpackages__"])

rb_library(
    name = "gem",
    deps = ["//lib:gem"],
)

lib/BUILD:

load("@rules_ruby//ruby:defs.bzl", "rb_library")

package(default_visibility = ["//:__subpackages__"])

rb_library(
    name = "gem",
    srcs = ["gem.rb"],
    deps = [
        "//lib/gem:add",
        "//lib/gem:subtract",
        "//lib/gem:version",
    ],
)

lib/gem/BUILD:

load("@rules_ruby//ruby:defs.bzl", "rb_library")

package(default_visibility = ["//:__subpackages__"])

rb_library(
    name = "add",
    srcs = ["add.rb"],
)

rb_library(
    name = "subtract",
    srcs = ["subtract.rb"],
)

rb_library(
    name = "version",
    srcs = ["version.rb"],
)

Once the packages are defined, you can use them in other targets such as rb_gem_build() to build a Ruby gem. See examples of using other rules.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsList of other Ruby libraries the target depends on.List of labelsoptional[]
srcsList of Ruby source files used to build the library.List of labelsoptional[]
dataList of runtime dependencies needed by a program that depends on this library.List of labelsoptional[]
bundle_envList of bundle environment variables to set when building the library.Dictionary: String -> Stringoptional{}

rb_test

load("@rules_ruby//ruby:defs.bzl", "rb_test")

rb_test(name, deps, srcs, data, coverage_filters, env, env_inherit, main, ruby)

Runs a Ruby test.

Suppose you have the following Ruby gem, where rb_library() is used in BUILD files to define the packages for the gem.

|-- BUILD
|-- Gemfile
|-- WORKSPACE
|-- gem.gemspec
|-- lib
|   |-- BUILD
|   |-- gem
|   |   |-- BUILD
|   |   |-- add.rb
|   |   |-- subtract.rb
|   |   `-- version.rb
|   `-- gem.rb
`-- spec
    |-- BUILD
    |-- add_spec.rb
    |-- spec_helper.rb
    `-- subtract_spec.rb

You can run all tests inside spec/ by defining individual targets:

spec/BUILD:

load("@rules_ruby//ruby:defs.bzl", "rb_library", "rb_test")

rb_library(
    name = "spec_helper",
    srcs = ["spec_helper.rb"],
)

rb_test(
    name = "add",
    srcs = ["add_spec.rb"],
    args = ["spec/add_spec.rb"],
    main = "@bundle//bin:rspec",
    deps = [
        ":spec_helper",
        "@bundle",
    ],
)

rb_test(
    name = "subtract",
    srcs = ["subtract_spec.rb"],
    args = ["spec/subtract_spec.rb"],
    main = "@bundle//bin:rspec",
    deps = [
        ":spec_helper",
        "@bundle",
    ],
)
$ bazel test spec/...
...
//spec:add                                                               PASSED in 0.4s
//spec:subtract                                                          PASSED in 0.4s

Executed 2 out of 2 tests: 2 tests pass.

Since rb_test() is a wrapper around rb_binary(), you can also use it to run a Ruby binary script available in Gemfile dependencies, by passing main argument with a path to a Bundler binary stub.

BUILD:

load("@rules_ruby//ruby:defs.bzl", "rb_test")

package(default_visibility = ["//:__subpackages__"])

rb_test(
    name = "rubocop",
    args = ["lib/"],
    main = "@bundle//bin:rubocop",
    tags = ["no-sandbox"],
    deps = [
        "//lib:gem",
        "@bundle",
    ],
)
$ bazel test :rubocop
...
//:rubocop                                                               PASSED in 0.8s

Executed 1 out of 1 test: 1 test passes.

Code Coverage

To enable code coverage, run tests with the coverage command:

bazel coverage //...

Note

Code coverage is currently not supported on Windows.

See the README for more details.

Note that you can also run every test target passing extra arguments to the Ruby script. For example, you can re-use :rubocop target to perform autocorrect:

$ bazel run :rubocop -- --autocorrect-all
...
Inspecting 11 files
.C.........

Offenses:

gem.gemspec:1:1: C: [Corrected] Style/FrozenStringLiteralComment: Missing frozen string literal comment.
root = File.expand_path(__dir__)
^
gem.gemspec:2:1: C: [Corrected] Layout/EmptyLineAfterMagicComment: Add an empty line after magic comments.
root = File.expand_path(__dir__)
^

11 files inspected, 2 offenses detected, 2 offenses corrected

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsList of other Ruby libraries the target depends on.List of labelsoptional[]
srcsList of Ruby source files used to build the library.List of labelsoptional[]
dataList of runtime dependencies needed by a program that depends on this library.List of labelsoptional[]
coverage_filtersAdditional coverage filters to add to SimpleCov. Only applied during 'bazel coverage'.List of stringsoptional[]
envEnvironment variables to use during execution.

Supports $(location) expansion for targets from srcs, data and deps.
Dictionary: String -> Stringoptional{}
env_inheritList of environment variable names to be inherited by the test runner.List of stringsoptional[]
mainRuby script to run. It may also be a binary stub generated by Bundler. If omitted, it defaults to the Ruby interpreter.

Use a built-in args attribute to pass extra arguments to the script.
LabeloptionalNone
rubyOverride Ruby toolchain to use when running the script.LabeloptionalNone