# rules_ruby **Repository Path**: mirrors_protocolbuffers/rules_ruby ## Basic Information - **Project Name**: rules_ruby - **Description**: Ruby Rules for Bazel. This is a fork of https://github.com/bazelruby/rules_ruby exclusively for protobuf internal usage - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-09-04 - **Last Updated**: 2025-10-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README = Ruby Rules® for Bazel :subtitle: Version 0.5.2 :author: Yuki (Yugui) Sonoda, Konstantin Gredeskoul & Contributors. :doctype: book :source-highlighter: rouge :rouge-style: base16.monokai :toclevels: 5 :toc: :sectnums: 9 :icons: font :license: apache ==== This repo is primarily maintained by https://github.com/kigster[Konstantin Gredeskoul] and https://github.com/yugui[Yuki "Yugui" Sonoda]. We are both very busy and would really love more contributors to join the core team. If you are interested in developing Ruby Rules for Bazel, please submit a couple of PRs and then lets talk! ==== TIP: You can read or print this README in a proper PDF format by grabbing our link:README.pdf[README.pdf]. == Build Status & Activity [cols="3,9",options="header",] |=== | *CI Status* | *Activity & Documentation* | image:https://circleci.com/gh/bazelruby/rules_ruby.svg?style=shield[CircleCI,link=https://circleci.com/gh/bazelruby/rules_ruby]   | image:https://img.shields.io/github/commit-activity/m/bazelruby/rules_ruby?style=for-the-badge[activity]   | image:https://travis-ci.org/bazelruby/rules_ruby.svg?branch=master[Build Status,link=https://travis-ci.org/bazelruby/rules_ruby]   | xref:CHANGELOG.md[image:https://img.shields.io/badge/change-log-brightgreen[changelog\]] link:README.pdf[image:https://img.shields.io/badge/README-pdf-blue[readme.pdf\]] |=== == Rules Development Status [cols="3,9",options="header",] |=== | *Readiness* | *Types of Applications* | image:docs/img/status-ready.svg[Ready] | ruby apps, ruby gems, micro-services, ideally in a mono-repo | image:docs/img/status-ready.svg[Wait] | medium-sized Ruby on Rails apps, ideally in a mono-repo | image:docs/img/status-wait.svg[Not Ready] | complex Ruby on Rails monoliths, single-repo |=== NOTE: we have a short guide on https://github.com/bazelruby/rules_ruby/wiki/Build-your-ruby-project[Building your first Ruby Project] on the Wiki. We encourage you to check it out. == Table of Contents * <> ** <> ** <> ** <> ** <> *** <> *** <> *** <> *** <> ** <> *** <> *** <> *** <> *** <> *** <> *** <> ** <> ** <> *** <> *** <> *** <> *** <> *** <> *** <> ** <> == Usage === `WORKSPACE` File ==== Load dependencies, select Ruby SDK and define one or more Bundles [source,python] ---- 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 'master' branch. #——————————————————————————————————————————————————————————————————————— git_repository( name = "rules_ruby", remote = "https://github.com/bazelruby/rules_ruby.git", branch = "master" ) load("@rules_ruby//ruby:deps.bzl", "rules_ruby_dependencies") 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() load("@rules_ruby//ruby:deps.bzl", "register_toolchain") register_toolchains("ruby-3.0") #——————————————————————————————————————————————————————————————————————— # Now, load the ruby_bundle rule & install gems specified in the Gemfile #——————————————————————————————————————————————————————————————————————— load("@ruby-3.0//:bundle.bzl", "ruby_bundle") ruby_bundle( name = "bundle", # Specify additional paths to be loaded from the gems at runtime, if any. # Since spec.require_paths in Gem specifications are auto-included, directory paths # in spec.require_paths do not need to be listed in includes hash. includes = { "grpc": ["etc"], }, 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", ) # You can also install from Gemfile using `gemspec`. ruby_bundle( name = "bundle_gemspec", srcs = ["//:lib/my_gem/my_gem.gemspec"], gemfile = "//:lib/my_gem/Gemfile", gemfile_lock = "//:lib/my_gem/Gemfile.lock", ) ---- === `BUILD.bazel` file(s) 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. ==== Define Ruby Executable, Library and an RSpec Add `ruby_library`, `ruby_binary`, `ruby_rspec` or `ruby_test` into your `BUILD.bazel` files. [source,python] ---- #——————————————————————————————————————————————————————————————————————— # Define Ruby executable, test, spec and package a gem #——————————————————————————————————————————————————————————————————————— load( "@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"] } ---- ==== Package Ruby files as a Gem Use `ruby_gem` rule to package any number of ruby files or folders into a Ruby-Gem compatible ZIP archive. [source,python] ---- load( "@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 = [ "bazelruby@googlegroups.com", ], 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", ], ) ---- === Tool Specific Setup ==== ASDF If you are using ASDF to manage your ruby installs, you can use them by adding `.bazelrc`: ---- build --test_env=ASDF_DIR --test_env=ASDF_DATA_DIR build --action_env=ASDF_DIR --test_env=ASDF_DATA_DIR ---- You will have to be sure to export the `ASDF_DATA_DIR` in your profile since it's not set by default. e.g. `export ASDF_DATA_DIR="$HOME/.asdf"` === Rule Dependency Diagram NOTE: this diagram is somewhat 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: image::docs/img/ruby_rules.png[Ruby Rules] == Rules === `ruby_library` [source,python] ---- ruby_library( name, deps, srcs, data, compatible_with, deprecation, distribs, features, licenses, restricted_to, tags, testonly, toolchains, visibility) ---- [cols="15,85",options="header",] |=== |Attributes | |`name` a| `Name, required` A unique name for this rule. |`srcs` a| `List of Labels, optional` List of `.rb` files. At least `srcs` or `deps` must be present |`deps` a| `List of labels, optional` List of targets that are required by the `srcs` Ruby files. At least `srcs` or `deps` must be present |`includes` a| `List of strings, optional` List of paths to be added to `$LOAD_PATH` at runtime. The paths must be relative to the the workspace which this rule belongs to. |`rubyopt` a| `List of strings, optional` List of options to be passed to the Ruby interpreter at runtime. NOTE: `-I` option should usually go to `includes` attribute. 2+ 3.0` means that all versions up to `4.0` are accepted. |`gem_development_dependencies` a| `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. 2+<|And other https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes[common attributes]. |=== == Potential Future Features ==== icon:check-square[fw] Using various versions of Ruby installed locally icon:square[fw] Building native extensions in gems with Bazel icon:square[fw] Releasing your gems with Bazel (https://github.com/coinbase/rules_ruby[Coinbase fork] might have this feature, worth checking) ==== == Contributing We welcome contributions to RulesRuby. Please make yourself familiar with the xref:CODE_OF_CONDUCT.adoc[code of conduct], which basically says -- don't be an a-hole. 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. === Setup ==== Using the Script 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: [source,bash] ---- ❯ bin/setup ---- This runs a complete setup, shouldn't take too long. You can explore various script options with the `help` command: [source,bash] ---- ❯ bin/setup -h 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 | main | os-specific | rbenv | 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 Or, to run only one of the sub-functions (actions), pass it as an argument: bin/setup help bin/setup remove-git-hook ---- ==== OS-Specific 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. === Verifying Your Environment We provided a handy script `bin/show-env` to display where your dependencies are coming from. Here is an example of running it on a Mac OS-X system: [source,bash] ---- ❯ bin/show-env ---- image::docs/img/env.png[bin/show-env] ==== Issues During Setup ____ *Please report any errors to `bin/setup` as Issues on Github. You can assign them to @kigster.* If I am not responding fast enough, and you are in a hurry, please email kigster AT gmail directly. ____ === Developing Rules Besides making yourself familiar with the existing code, and https://docs.bazel.build/versions/master/skylark/concepts.html[Bazel documentation on writing rules], you might want to follow this order: . Setup dev tools as described in the <> section. . hack, hack, hack... . Make sure all tests pass -- you can run a single command for that (but see more on it <>. [source,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. === Running Tests After running setup, and since this is a bazel repo you can use Bazel commands: [source,python] ---- 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. ==== Test Script This script runs all tests (including sub-workspaces) when ran without arguments: [source,bash] ---- 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: [source,bash] ---- # 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. === Linter 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: [source,bash] ---- bin/linter ---- The following are the partial linting functions you can run: [source,bash] ---- # alternatively, a partial linter name can be passed: bin/linter [ all | buildifier | help | rubocop ] ---- === Regenerating README.pdf & Changelog To regenerate, first you may need to grab an https://github.com/settings/tokens[API token] and export the `GITHUB_TOKEN` variable: [source,bash] ---- export GITHUB_TOKEN=.... ---- Then use the `make` target: [source,bash] ---- make update ---- Or, manually: [source,bash] ---- gem install github_changelog_generator github_changelog_generator -u bazelruby -p rules_ruby -t your-github-token ---- == Copyright © 2018-2021 BazelRuby Contributors. Core Team: * https://github.com/yugui/[Yuki Yugui Sonoda] * https://kig.re/[Konstantin Gredeskoul] Core Team (Emeritus): * https://github.com/grahamjenson[Graham Jenson] Licensed under the http://www.apache.org/licenses/LICENSE-2.0[Apache License, Version 2.0 (the "License")]. 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.