This is the README for Ruby Rules for the Bazel Build system.
We recently switched from the base branch of develop
to the base of master
. Please update your local repos accordingly.
To regenerate:
gem install github_changelog_generator
github_changelog_generator -u bazelruby -p rules_ruby
Readiness | Types of Applications |
---|---|
ruby apps, ruby gems, micro-services, ideally in a mono-repo | |
medium-sized Ruby on Rails apps, ideally in a mono-repo | |
complex Ruby on Rails monoliths, single-repo |
Note: we have a short guide on Building your first Ruby Project on the Wiki. We encourage you to check it out.
workspace(name = "my_ruby_project")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
#———————————————————————————————————————————————————————————————————————
# To get the latest ruby rules, grab the 'develop' branch.
#———————————————————————————————————————————————————————————————————————
git_repository(
name = "bazelruby_rules_ruby",
remote = "https://github.com/bazelruby/rules_ruby.git",
branch = "master"
)
load(
"@bazelruby_rules_ruby//ruby:deps.bzl",
"rules_ruby_dependencies",
"rules_ruby_select_sdk",
)
rules_ruby_dependencies()
#———————————————————————————————————————————————————————————————————————
# Specify Ruby version — this will either build Ruby or use a local
# RBENV installation if the Ruby version matches.
#———————————————————————————————————————————————————————————————————————
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()
rules_ruby_select_sdk(version = "2.7.1")
#———————————————————————————————————————————————————————————————————————
# Now, load the ruby_bundle rule & install gems specified in the Gemfile
#———————————————————————————————————————————————————————————————————————
load(
"@bazelruby_rules_ruby//ruby:defs.bzl",
"ruby_bundle",
)
ruby_bundle(
name = "bundle",
excludes = {
"mini_portile": ["test/**/*"],
},
gemfile = "//:Gemfile",
gemfile_lock = "//:Gemfile.lock",
)
# You can specify more than one bundle in the WORKSPACE file
ruby_bundle(
name = "bundle_app_shopping",
gemfile = "//apps/shopping:Gemfile",
gemfile_lock = "//apps/shopping:Gemfile.lock",
)
Any of the project BUILD
files can now reference any gems included in the Gemfile
referenced by the ruby_bundle
rule, and defined in the project's WORKSPACE
file.
Add ruby_library
, ruby_binary
, ruby_rspec
or ruby_test
into your BUILD.bazel
files.
#———————————————————————————————————————————————————————————————————————
# Define Ruby executable, test, spec and package a gem
#———————————————————————————————————————————————————————————————————————
load(
"@bazelruby_rules_ruby//ruby:defs.bzl",
"ruby_binary",
"ruby_library",
"ruby_test",
"ruby_rspec",
)
ruby_library(
name = "foo",
srcs = glob(["lib/**/*.rb"]),
includes = ["lib"],
deps = [
"@bundle//:activesupport",
"@bundle//:awesome_print",
"@bundle//:rubocop",
]
)
ruby_binary(
name = "bar",
srcs = ["bin/bar"],
deps = [":foo"],
)
ruby_test(
name = "foo-test",
srcs = ["test/foo_test.rb"],
deps = [":foo"],
)
ruby_rspec(
name = "foo-spec",
specs = glob(["spec/**/*.rb"]),
rspec_args = { "--format": "progress" },
deps = [":foo"]
}
Use ruby_gem
rule to package any number of ruby files or folders into a Ruby-Gem compatible ZIP archive.
load(
"@bazelruby_rules_ruby//ruby:defs.bzl",
"ruby_gem",
)
ruby_gem(
name = "awesome-sauce-gem", # name of the build target
gem_name = "awesome-sauce", # name of the gem
gem_version = "0.1.0",
gem_summary = "Example gem to demonstrate Bazel Gem packaging",
gem_description = "Example gem to demonstrate Bazel Gem packaging",
gem_homepage = "https://github.com/bazelruby/rules_ruby",
gem_authors = [
"BazelRuby",
"Konstantin Gredeskoul"
],
gem_author_emails = [
"[email protected]",
],
gem_runtime_dependencies = {
"colored2": "~> 3.1.2",
"hashie": "",
},
gem_development_dependencies = {
"rspec": "",
"rspec-its": "",
"rubocop": "",
},
srcs = [
glob("{bin,exe,lib,spec}/**/*.rb")
],
deps = [
"//lib:example_gem",
],
)
NOTE: this diagram is slightly outdated.
The following diagram attempts to capture the implementation behind ruby_library
that depends on the result of bundle install
, and a ruby_binary
that depends on both:
ruby_library(
name,
deps,
srcs,
data,
compatible_with,
deprecation,
distribs,
features,
licenses,
restricted_to,
tags,
testonly,
toolchains,
visibility)
Attributes | |
---|---|
name |
Name, required
A unique name for this rule. |
srcs |
List of Labels, optional
List of At least |
deps |
List of labels, optional
List of targets that are required by the At least |
includes |
List of strings, optional
List of paths to be added to |
rubyopt |
List of strings, optional
List of options to be passed to the Ruby interpreter at runtime.
NOTE: |
And other common attributes |
ruby_binary(
name,
deps,
srcs,
data,
main,
compatible_with,
deprecation,
distribs,
features,
licenses,
restricted_to,
tags,
testonly,
toolchains,
visibility,
args,
output_licenses
)
Attributes | |
---|---|
name |
Name, required
A unique name for this rule. |
srcs |
List of Labels, required
List of |
deps |
List of labels, optional
List of targets that are required by the |
main |
Label, optional
The entrypoint file. It must be also in If not specified, |
includes |
List of strings, optional
List of paths to be added to |
rubyopt |
List of strings, optional
List of options to be passed to the Ruby interpreter at runtime.
NOTE: |
And other common attributes |
ruby_test(
name,
deps,
srcs,
data,
main,
compatible_with,
deprecation,
distribs,
features,
licenses,
restricted_to,
tags,
testonly,
toolchains,
visibility,
args,
size,
timeout,
flaky,
local, shard_count)
Attributes | |
---|---|
name |
Name, required
A unique name for this rule. |
srcs |
List of Labels, required
List of |
deps |
List of labels, optional
List of targets that are required by the |
main |
Label, optional
The entrypoint file. It must be also in If not specified, |
includes |
List of strings, optional
List of paths to be added to |
rubyopt |
List of strings, optional
List of options to be passed to the Ruby interpreter at runtime.
NOTE: |
And other common attributes |
NOTE: This is a repository rule, and can only be used in a WORKSPACE
file.
This rule installs gems defined in a Gemfile using Bundler, and exports individual gems from the bundle, as well as the entire bundle, available as a ruby_library
that can be depended upon from other targets.
ruby_bundle(
name,
gemfile,
gemfile_lock,
bundler_version = "2.1.2",
excludes = [],
ruby_sdk = "@org_ruby_lang_ruby_toolchain",
ruby_interpreter = "@org_ruby_lang_ruby_toolchain//:ruby",
)
Attributes | |
---|---|
name |
Name, required
A unique name for this rule. |
gemfile |
Label, required
The |
gemfile_lock |
Label, required
The NOTE: This rule never updates the |
bundler_version |
String, optional
The Version of Bundler to use. Defaults to 2.1.2. NOTE: This rule never updates the |
Installing using a Gemfile
that uses the gemspec
keyword is not currently supported.
ruby_bundle
creates several targets that can be used downstream. In the examples below we assume that your ruby_bundle
has a name app_bundle
:
@app_bundle//:bundler
— references just the Bundler from the bundle.@app_bundle//:gems
— references all gems in the bundle (i.e. "the entire bundle").@app_bundle//:gem-name
— references just the specified gem in the bundle, eg.@app_bundle//:awesome_print
.@app_bundle//:bin
— references to all installed executables from this bundle, with individual executables accessible via eg.@app_bundle//:bin/rubocop
load("@bazelruby_rules_ruby//ruby:defs.bzl", "ruby_bundle")
ruby_bundle(
name = "gems",
bundler_version = '2.1.2',
gemfile = "//:Gemfile",
gemfile_lock = "//:Gemfile.lock",
)
# Reference the entire bundle with :gems
ruby_library(
name = "foo",
srcs = ["foo.rb"],
deps = ["@gems//:gems"],
)
# Or, reference specific gems from the bundle like so:
ruby_binary(
name = "rubocop",
srcs = [":foo", ".rubocop.yml"],
args = ["-P", "-D", "-c" ".rubocop.yml"],
main = "@gems//:bin/rubocop",
deps = ["@gems//:rubocop"],
)
ruby_rspec(
name,
deps,
srcs,
data,
main,
rspec_args,
bundle,
compatible_with,
deprecation,
distribs,
features,
licenses,
restricted_to,
tags,
testonly,
toolchains,
visibility,
args,
size,
timeout,
flaky,
local,
shard_count
)
Attributes | |
---|---|
name |
Name, required
A unique name for this rule. |
srcs |
List of Labels, required
List of |
deps |
List of labels, optional
List of targets that are required by the |
main |
Label, optional
The entrypoint file. It must be also in If not specified, |
rspec_args |
List of strings, optional
Command line arguments to the If not specified, the default arguments defined in `constants.bzl` are used: |
includes |
List of strings, optional
List of paths to be added to |
rubyopt |
List of strings, optional
List of options to be passed to the Ruby interpreter at runtime.
NOTE: |
And other common attributes |
Used to generate a zipped gem containing its srcs, dependencies and a gemspec.
ruby_gem(
name,
gem_name,
gem_version,
gem_summary,
gem_description,
gem_homepage,
gem_authors,
gem_author_emails,
gem_runtime_dependencies,
gem_development_dependencies,
require_paths = ["lib"],
srcs = srcs,
deps = deps,
data = data
)
Attributes | |
---|---|
name |
Name, required
A unique name for this build target. |
gem_name |
Name of the gem, required
The name of the gem to be generated. |
gem_version |
String, optional
The version of the gem. Is used to name the output file,
which becomes |
gem_summary |
String, optional
One line summary of the gem purpose. |
gem_description |
String, required
Single-line, paragraph-sized description text for the gem. |
gem_homepage |
String, optional
Homepage URL of the gem. |
gem_authors |
List of Strings, required
List of human readable names of the gem authors. Required to generate a valid gemspec. |
gem_author_emails |
List of Strings, optional
List of email addresses of the authors. |
srcs |
List of Labels, optional
List of At least |
deps |
List of labels, optional
List of targets that are required by the At least |
require_paths |
List of Strings, optional
List of paths to be added to the Ruby LOAD_PATH when using this gem. Typically this value is just `lib` (which is also the default). |
gem_runtime_dependencies |
String Dictionary, optional
This is a dictionary where keys are gem names, and values are either an empty
string or a gem version specification.
For instance, the pessimistic version specifier |
gem_development_dependencies |
String Dictionary, optional
Similar to the above, this specifies gems necessary for the development of the above gem, such as testing gems, linters, code coverage and more. |
- Building native extensions in gems with Bazel
- Using a specified version of Ruby.
- Releasing your gems with Bazel
We welcome contributions to RulesRuby. Please make yourself familiar with the CODE_OF_CONDUCT document.
You may notice that there is more than one Bazel WORKSPACE inside this repo. There is one in examples/simple_script
for instance, because
we use this example to validate and test the rules. So be mindful whether your current directory contains WORKSPACE
file or not.
You will need Homebrew installed prior to running the script.
After that, cd into the top level folder and run the setup script in your Terminal:
❯ bin/setup
This runs a complete setup, shouldn't take too long. You can explore various script options with the help
command:
❯ bin/setup help
USAGE
# without any arguments runs a complete setup.
bin/setup
# alternatively, a sub-setup function name can be passed:
bin/setup [ gems | git-hook | help | os-specific | main | remove-git-hook ]
DESCRIPTION:
Runs full setup without any arguments.
Accepts one optional argument — one of the actions that typically run
as part of setup, with one exception — remove-git-hook.
This action removes the git commit hook installed by the setup.
EXAMPLES:
bin/setup — runs the entire setup.
Note that the setup contains os-specific
section. This is because there are two extension scripts:
bin/setup-linux
bin/setup-darwin
Those will install Bazel and everything else you need on either platform. In fact, we use the linux version on CI.
Please report any errors to bin/setup
as Issues on Github. You can assign them to @kigster.
Besides making yourself familiar with the existing code, and Bazel documentation on writing rules, you might want to follow this order:
- Setup dev tools as described in the setup section.
- hack, hack, hack...
- Make sure all tests pass — you can run a single command for that (but see more on it below.
```bash
bin/test-suite
```
OR you can run individual Bazel test commands from the inside.
bazel test //...
cd examples/simple_script && bazel test //...
- Open a pull request in Github, and please be as verbose as possible in your description.
In general, it's always a good idea to ask questions first — you can do so by creating an issue.
After running setup, and since this is a bazel repo you can use Bazel commands:
bazel build //...:all
bazel query //...:all
bazel test //...:all
But to run tests inside each sub-WORKSPACE, you will need to repeat that in each sub-folder. Luckily, there is a better way.
This script runs all tests (including sub-workspaces) when ran without arguments:
bin/test-suite
Run it with help
command to see other options, and to see what parts you can run individually. At the moment they are:
# alternatively, a partial test name can be passed:
bin/test-suite [ all | bazel-info | buildifier | help | rspec | rubocop | simple-script | workspace ]
On a MacBook Pro it takes about 3 minutes to run.
We are using RuboCop for ruby and Buildifier for Bazel. Both are represented by a single script bin/linter
, which just like the scripts above runs ALL linters when ran without arguments, accepts help
commnd, and can be run on a subset of linting strategies:
bin/linter
The following are the partial linting functions you can run:
# alternatively, a partial linter name can be passed:
bin/linter [ all | buildifier | help | rubocop ]
© 2018-2019 Yuki Yugui Sonoda & BazelRuby Authors
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
- [Build Status](#build-status)
- [Change Log](#change-logchangelogmd)