├── WORKSPACE ├── .bazelversion ├── .bazelignore ├── examples ├── rails │ ├── .ruby-version │ ├── people_tracker │ │ ├── script │ │ │ └── .keep │ │ ├── vendor │ │ │ └── .keep │ │ ├── lib │ │ │ └── tasks │ │ │ │ └── .keep │ │ ├── test │ │ │ ├── mailers │ │ │ │ └── .keep │ │ │ ├── integration │ │ │ │ └── .keep │ │ │ ├── fixtures │ │ │ │ ├── files │ │ │ │ │ └── .keep │ │ │ │ ├── BUILD.bazel │ │ │ │ └── people.yml │ │ │ ├── models │ │ │ │ ├── BUILD.bazel │ │ │ │ └── person_test.rb │ │ │ ├── system │ │ │ │ ├── BUILD.bazel │ │ │ │ └── people_test.rb │ │ │ ├── controllers │ │ │ │ ├── BUILD.bazel │ │ │ │ └── people_controller_test.rb │ │ │ ├── application_system_test_case.rb │ │ │ ├── rails_test.bzl │ │ │ ├── BUILD.bazel │ │ │ └── test_helper.rb │ │ ├── app │ │ │ ├── assets │ │ │ │ ├── images │ │ │ │ │ └── .keep │ │ │ │ ├── tailwind │ │ │ │ │ └── application.css │ │ │ │ ├── BUILD.bazel │ │ │ │ └── stylesheets │ │ │ │ │ └── application.css │ │ │ ├── views │ │ │ │ ├── layouts │ │ │ │ │ ├── mailer.text.erb │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── mailer.html.erb │ │ │ │ │ └── application.html.erb │ │ │ │ ├── people │ │ │ │ │ ├── show.json.jbuilder │ │ │ │ │ ├── index.json.jbuilder │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── _person.json.jbuilder │ │ │ │ │ ├── _person.html.erb │ │ │ │ │ ├── new.html.erb │ │ │ │ │ ├── edit.html.erb │ │ │ │ │ ├── show.html.erb │ │ │ │ │ ├── _form.html.erb │ │ │ │ │ └── index.html.erb │ │ │ │ ├── pwa │ │ │ │ │ ├── BUILD.bazel │ │ │ │ │ ├── manifest.json.erb │ │ │ │ │ └── service-worker.js │ │ │ │ └── BUILD.bazel │ │ │ ├── models │ │ │ │ ├── concerns │ │ │ │ │ └── BUILD.bazel │ │ │ │ ├── application_record.rb │ │ │ │ ├── BUILD.bazel │ │ │ │ └── person.rb │ │ │ ├── controllers │ │ │ │ ├── concerns │ │ │ │ │ └── BUILD.bazel │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── application_controller.rb │ │ │ │ └── people_controller.rb │ │ │ ├── helpers │ │ │ │ ├── people_helper.rb │ │ │ │ ├── application_helper.rb │ │ │ │ └── BUILD.bazel │ │ │ ├── mailers │ │ │ │ ├── application_mailer.rb │ │ │ │ └── BUILD.bazel │ │ │ ├── javascript │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── application.js │ │ │ │ └── controllers │ │ │ │ │ ├── application.js │ │ │ │ │ └── index.js │ │ │ ├── jobs │ │ │ │ ├── BUILD.bazel │ │ │ │ └── application_job.rb │ │ │ └── BUILD.bazel │ │ ├── config │ │ │ ├── master.key │ │ │ ├── environment.rb │ │ │ ├── locales │ │ │ │ ├── BUILD.bazel │ │ │ │ └── en.yml │ │ │ ├── boot.rb │ │ │ ├── environments │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── test.rb │ │ │ │ ├── development.rb │ │ │ │ └── production.rb │ │ │ ├── initializers │ │ │ │ ├── BUILD.bazel │ │ │ │ ├── assets.rb │ │ │ │ ├── filter_parameter_logging.rb │ │ │ │ ├── inflections.rb │ │ │ │ ├── bazel_ruby_patches.rb │ │ │ │ └── content_security_policy.rb │ │ │ ├── cable.yml │ │ │ ├── importmap.rb │ │ │ ├── credentials.yml.enc │ │ │ ├── BUILD.bazel │ │ │ ├── routes.rb │ │ │ ├── storage.yml │ │ │ ├── database.yml │ │ │ ├── application.rb │ │ │ ├── puma.rb │ │ │ └── deploy.yml │ │ ├── Procfile.dev │ │ ├── bin │ │ │ ├── rake │ │ │ ├── thrust │ │ │ ├── rails │ │ │ ├── brakeman │ │ │ ├── rubocop │ │ │ ├── BUILD.bazel │ │ │ ├── dev │ │ │ ├── docker-entrypoint │ │ │ └── setup │ │ ├── public │ │ │ ├── icon.png │ │ │ ├── robots.txt │ │ │ └── icon.svg │ │ ├── config.ru │ │ ├── db │ │ │ ├── migrate │ │ │ │ ├── BUILD.bazel │ │ │ │ └── 20250821215024_create_people.rb │ │ │ ├── BUILD.bazel │ │ │ ├── seeds.rb │ │ │ └── schema.rb │ │ ├── Rakefile │ │ ├── .rubocop.yml │ │ ├── BUILD.bazel │ │ ├── .dockerignore │ │ ├── .envrc │ │ ├── Dockerfile │ │ └── Gemfile │ ├── .standard.yml │ ├── Gemfile │ ├── do_test │ ├── .envrc │ ├── .bazelrc │ ├── BUILD.bazel │ └── README.md ├── gem │ ├── .bazelversion │ ├── .ruby-version │ ├── spec │ │ ├── support │ │ │ ├── file.txt │ │ │ └── BUILD │ │ ├── spec_helper.rb │ │ ├── support_spec.rb │ │ ├── add_spec.rb │ │ ├── subtract_spec.rb │ │ ├── env_spec.rb │ │ └── BUILD │ ├── Rakefile │ ├── lib │ │ ├── gem.rb │ │ ├── gem │ │ │ ├── subtract.rb │ │ │ ├── version.rb │ │ │ ├── add.rb │ │ │ └── BUILD │ │ └── BUILD │ ├── WORKSPACE.bzlmod │ ├── Gemfile │ ├── .rubocop.yml │ ├── wrapper.tpl.sh │ ├── gem.gemspec │ ├── .bazelrc │ ├── BUILD │ ├── Gemfile.lock │ ├── WORKSPACE │ └── MODULE.bazel ├── jekyll │ ├── .bazelversion │ ├── .gitignore │ ├── index.md │ ├── 404.html │ ├── about.md │ ├── _posts │ │ └── 2024-02-03-welcome-to-jekyll.markdown │ ├── Gemfile │ ├── _config.yml │ ├── BUILD │ ├── Gemfile.lock │ └── MODULE.bazel ├── deep_gem │ ├── .bazelversion │ ├── .ruby-version │ ├── BUILD │ ├── hello_world │ │ ├── BUILD.bazel │ │ ├── .rspec │ │ ├── lib │ │ │ ├── hello_world │ │ │ │ ├── version.rb │ │ │ │ ├── speaker.rb │ │ │ │ └── BUILD.bazel │ │ │ ├── hello_world.rb │ │ │ └── BUILD.bazel │ │ ├── Gemfile │ │ ├── spec │ │ │ ├── hello_world_spec.rb │ │ │ ├── spec_helper.rb │ │ │ ├── BUILD.bazel │ │ │ └── speaker_spec.rb │ │ ├── hello_world.gemspec │ │ ├── Gemfile.lock │ │ └── .bazelrc │ ├── do_test │ ├── .bazelrc │ ├── MODULE.bazel │ └── README.md └── native_ext │ ├── .bazelversion │ ├── .ruby-version │ ├── ext │ ├── c │ │ ├── native_ext.h │ │ └── native_ext.c │ └── java │ │ └── Dummy.java │ ├── .bazelrc │ ├── MODULE.bazel │ └── BUILD ├── ruby ├── private │ ├── gem_build │ │ ├── BUILD │ │ └── gem_builder.rb.tpl │ ├── binary │ │ ├── BUILD │ │ ├── binary.cmd.tpl │ │ └── binary.sh.tpl │ ├── gem_install │ │ ├── BUILD │ │ ├── gem_install.cmd.tpl │ │ └── gem_install.sh.tpl │ ├── bundle_install │ │ ├── BUILD │ │ ├── bundle_install.cmd.tpl │ │ └── bundle_install.sh.tpl │ ├── toolchain │ │ ├── repository_proxy │ │ │ └── BUILD.tpl │ │ ├── BUILD │ │ └── repository_proxy.bzl │ ├── bundle_fetch │ │ ├── BUILD │ │ ├── bin │ │ │ └── BUILD.tpl │ │ └── BUILD.tpl │ ├── bundle │ │ └── BUILD.tpl │ ├── download │ │ ├── BUILD.engine.tpl │ │ └── BUILD.tpl │ ├── gem.bzl │ ├── BUILD │ ├── toolchain.bzl │ ├── gem_push.bzl │ ├── test.bzl │ ├── providers.bzl │ ├── library.bzl │ └── gem_install.bzl ├── tests │ ├── BUILD │ └── utils_tests.bzl ├── deps.bzl ├── defs.bzl ├── toolchain.bzl └── BUILD ├── .gitattributes ├── rails ├── rails_test_factory.bzl ├── private │ └── BUILD.bazel └── BUILD.bazel ├── .gitignore ├── .bazelrc ├── CONTRIBUTING.md ├── renovate.json ├── .bcr ├── source.template.json ├── metadata.template.json ├── config.yml ├── README.md └── presubmit.yml ├── .github └── workflows │ ├── ci.bazelrc │ └── release_prep.sh ├── BUILD ├── docs ├── BUILD └── rails.md ├── .pre-commit-config.yaml └── MODULE.bazel /WORKSPACE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.bazelversion: -------------------------------------------------------------------------------- 1 | 8.4.2 2 | -------------------------------------------------------------------------------- /.bazelignore: -------------------------------------------------------------------------------- 1 | examples 2 | -------------------------------------------------------------------------------- /examples/rails/.ruby-version: -------------------------------------------------------------------------------- 1 | 3.4.5 2 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/script/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/vendor/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/gem/.bazelversion: -------------------------------------------------------------------------------- 1 | ../../.bazelversion -------------------------------------------------------------------------------- /examples/gem/.ruby-version: -------------------------------------------------------------------------------- 1 | jruby-10.0.2.0 2 | -------------------------------------------------------------------------------- /examples/gem/spec/support/file.txt: -------------------------------------------------------------------------------- 1 | File! 2 | -------------------------------------------------------------------------------- /examples/jekyll/.bazelversion: -------------------------------------------------------------------------------- 1 | ../../.bazelversion -------------------------------------------------------------------------------- /examples/rails/people_tracker/lib/tasks/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/deep_gem/.bazelversion: -------------------------------------------------------------------------------- 1 | ../../.bazelversion -------------------------------------------------------------------------------- /examples/deep_gem/.ruby-version: -------------------------------------------------------------------------------- 1 | jruby-10.0.2.0 2 | -------------------------------------------------------------------------------- /examples/deep_gem/BUILD: -------------------------------------------------------------------------------- 1 | # Intentionally blank 2 | -------------------------------------------------------------------------------- /examples/native_ext/.bazelversion: -------------------------------------------------------------------------------- 1 | ../../.bazelversion -------------------------------------------------------------------------------- /examples/native_ext/.ruby-version: -------------------------------------------------------------------------------- 1 | jruby-10.0.2.0 2 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/assets/images/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/integration/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/fixtures/files/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/jekyll/.gitignore: -------------------------------------------------------------------------------- 1 | bazel-* 2 | MODULE.bazel.lock 3 | -------------------------------------------------------------------------------- /examples/rails/.standard.yml: -------------------------------------------------------------------------------- 1 | # Config file for Standardrb 2 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/BUILD.bazel: -------------------------------------------------------------------------------- 1 | # Intentionally blank 2 | -------------------------------------------------------------------------------- /ruby/private/gem_build/BUILD: -------------------------------------------------------------------------------- 1 | exports_files(["gem_builder.rb.tpl"]) 2 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/master.key: -------------------------------------------------------------------------------- 1 | 7a77b7a551c74939a2d64605d80d07a8 -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/models/concerns/BUILD.bazel: -------------------------------------------------------------------------------- 1 | # Intentionally empty 2 | -------------------------------------------------------------------------------- /examples/gem/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'gem' 4 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/assets/tailwind/application.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/controllers/concerns/BUILD.bazel: -------------------------------------------------------------------------------- 1 | # Intentionally blank 2 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/helpers/people_helper.rb: -------------------------------------------------------------------------------- 1 | module PeopleHelper 2 | end 3 | -------------------------------------------------------------------------------- /ruby/tests/BUILD: -------------------------------------------------------------------------------- 1 | load(":utils_tests.bzl", "utils_test_suite") 2 | 3 | utils_test_suite() 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # In code review, collapse generated files 2 | docs/*.md linguist-generated=true 3 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | --require spec_helper 4 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /ruby/private/binary/BUILD: -------------------------------------------------------------------------------- 1 | exports_files([ 2 | "binary.cmd.tpl", 3 | "binary.sh.tpl", 4 | ]) 5 | -------------------------------------------------------------------------------- /examples/gem/Rakefile: -------------------------------------------------------------------------------- 1 | desc "say goodnight to bash" 2 | task "goodnight" do 3 | puts "exit 0" 4 | end 5 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/Procfile.dev: -------------------------------------------------------------------------------- 1 | web: bin/rails server 2 | css: bin/rails tailwindcss:watch 3 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/people/show.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.partial! "people/person", person: @person 2 | -------------------------------------------------------------------------------- /ruby/private/gem_install/BUILD: -------------------------------------------------------------------------------- 1 | exports_files([ 2 | "gem_install.cmd.tpl", 3 | "gem_install.sh.tpl", 4 | ]) 5 | -------------------------------------------------------------------------------- /ruby/private/bundle_install/BUILD: -------------------------------------------------------------------------------- 1 | exports_files([ 2 | "bundle_install.cmd.tpl", 3 | "bundle_install.sh.tpl", 4 | ]) 5 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/people/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.array! @people, partial: "people/person", as: :person 2 | -------------------------------------------------------------------------------- /examples/gem/lib/gem.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'gem/add' 4 | require 'gem/subtract' 5 | require 'gem/version' 6 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | primary_abstract_class 3 | end 4 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative "../config/boot" 3 | require "rake" 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/lib/hello_world/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module HelloWorld 4 | VERSION = "0.0.0" 5 | end 6 | -------------------------------------------------------------------------------- /examples/native_ext/ext/c/native_ext.h: -------------------------------------------------------------------------------- 1 | #ifndef NATIVE_EXT_H 2 | #define NATIVE_EXT_H 1 3 | 4 | #include "ruby.h" 5 | 6 | #endif /* NATIVE_EXT_H */ 7 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazel-contrib/rules_ruby/HEAD/examples/rails/people_tracker/public/icon.png -------------------------------------------------------------------------------- /examples/rails/people_tracker/public/robots.txt: -------------------------------------------------------------------------------- 1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | -------------------------------------------------------------------------------- /examples/gem/WORKSPACE.bzlmod: -------------------------------------------------------------------------------- 1 | # Marker file that this is the root of a Bazel workspace. 2 | # This file replaces WORKSPACE.bazel under --enable_bzlmod. 3 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/bin/thrust: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "rubygems" 3 | require "bundler/setup" 4 | 5 | load Gem.bin_path("thruster", "thrust") 6 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/lib/hello_world.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "hello_world/version" 4 | require_relative "hello_world/speaker" 5 | -------------------------------------------------------------------------------- /examples/gem/spec/support/BUILD: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//spec:__subpackages__"]) 2 | 3 | filegroup( 4 | name = "file", 5 | srcs = ["file.txt"], 6 | ) 7 | -------------------------------------------------------------------------------- /ruby/private/bundle_install/bundle_install.cmd.tpl: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | {env} 4 | 5 | {ruby_path} {bundler_exe} install --standalone --local 6 | 7 | :: vim: ft=dosbatch 8 | -------------------------------------------------------------------------------- /ruby/private/bundle_install/bundle_install.sh.tpl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | {env} 4 | 5 | {ruby_path} {bundler_exe} install --standalone --local 6 | 7 | # vim: ft=bash 8 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: "from@example.com" 3 | layout "mailer" 4 | end 5 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/public/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | # Specify your gem's dependencies in hello_world.gemspec 6 | gemspec 7 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/pwa/BUILD.bazel: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "files", 3 | srcs = glob(["*"]), 4 | visibility = ["//people_tracker:__subpackages__"], 5 | ) 6 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/assets/BUILD.bazel: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "files", 3 | srcs = glob(["**/*.css"]), 4 | visibility = ["//people_tracker:__subpackages__"], 5 | ) 6 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/people/BUILD.bazel: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "files", 3 | srcs = glob(["*"]), 4 | visibility = ["//people_tracker:__subpackages__"], 5 | ) 6 | -------------------------------------------------------------------------------- /examples/rails/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | # Rails for generating and running the People Tracker Rails application 6 | gem "rails", "~> 8.0" -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/javascript/BUILD.bazel: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "files", 3 | srcs = glob(["**/*.js"]), 4 | visibility = ["//people_tracker:__subpackages__"], 5 | ) 6 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/layouts/BUILD.bazel: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "files", 3 | srcs = glob(["*.erb"]), 4 | visibility = ["//people_tracker:__subpackages__"], 5 | ) 6 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/people/_person.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.extract! person, :id, :first_name, :last_name, :created_at, :updated_at 2 | json.url person_url(person, format: :json) 3 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path("../config/application", __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/fixtures/BUILD.bazel: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "files", 3 | srcs = glob(["*.yml"]), 4 | visibility = ["//people_tracker/test:__subpackages__"], 5 | ) 6 | -------------------------------------------------------------------------------- /examples/native_ext/ext/java/Dummy.java: -------------------------------------------------------------------------------- 1 | import org.jruby.*; 2 | import org.jruby.anno.JRubyClass; 3 | 4 | @JRubyClass(name = "Dummy") 5 | public class Dummy { 6 | public Dummy() { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative "application" 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/locales/BUILD.bazel: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "files", 3 | srcs = glob(["*.yml"]), 4 | visibility = ["//people_tracker/config:__subpackages__"], 5 | ) 6 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/models/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("//people_tracker/test:rails_test.bzl", "rails_test") 2 | 3 | rails_test( 4 | name = "person_test", 5 | src = "person_test.rb", 6 | ) 7 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/bin/brakeman: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "rubygems" 3 | require "bundler/setup" 4 | 5 | ARGV.unshift("--ensure-latest") 6 | 7 | load Gem.bin_path("brakeman", "brakeman") 8 | -------------------------------------------------------------------------------- /examples/jekyll/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | # Feel free to add content and custom Front Matter to this file. 3 | # To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults 4 | 5 | layout: home 6 | --- 7 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative "config/environment" 4 | 5 | run Rails.application 6 | Rails.application.load_server 7 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/system/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("//people_tracker/test:rails_test.bzl", "rails_system_test") 2 | 3 | rails_system_test( 4 | name = "people_test", 5 | src = "people_test.rb", 6 | ) 7 | -------------------------------------------------------------------------------- /ruby/private/toolchain/repository_proxy/BUILD.tpl: -------------------------------------------------------------------------------- 1 | toolchain( 2 | name = "{name}", 3 | toolchain = "{toolchain}", 4 | toolchain_type = "{toolchain_type}", 5 | visibility = ["//visibility:public"], 6 | ) 7 | -------------------------------------------------------------------------------- /examples/native_ext/ext/c/native_ext.c: -------------------------------------------------------------------------------- 1 | #include "native_ext.h" 2 | 3 | VALUE rb_mNativeExt; 4 | 5 | RUBY_FUNC_EXPORTED void 6 | Init_native_ext(void) 7 | { 8 | rb_mNativeExt = rb_define_module("NativeExt"); 9 | } 10 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/javascript/application.js: -------------------------------------------------------------------------------- 1 | // Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails 2 | import "@hotwired/turbo-rails"; 3 | import "controllers"; 4 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/controllers/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("//people_tracker/test:rails_test.bzl", "rails_test") 2 | 3 | rails_test( 4 | name = "people_controller_test", 5 | src = "people_controller_test.rb", 6 | ) 7 | -------------------------------------------------------------------------------- /ruby/private/toolchain/BUILD: -------------------------------------------------------------------------------- 1 | load("@bazel_skylib//:bzl_library.bzl", "bzl_library") 2 | 3 | bzl_library( 4 | name = "repository_proxy", 5 | srcs = ["repository_proxy.bzl"], 6 | visibility = ["//ruby:__subpackages__"], 7 | ) 8 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/jobs/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | rb_library( 4 | name = "jobs", 5 | srcs = glob(["*.rb"]), 6 | visibility = ["//people_tracker/app:__subpackages__"], 7 | ) 8 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/helpers/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | rb_library( 4 | name = "helpers", 5 | srcs = glob(["*.rb"]), 6 | visibility = ["//people_tracker/app:__subpackages__"], 7 | ) 8 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/mailers/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | rb_library( 4 | name = "mailers", 5 | srcs = glob(["*.rb"]), 6 | visibility = ["//people_tracker/app:__subpackages__"], 7 | ) 8 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/models/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | rb_library( 4 | name = "models", 5 | srcs = glob(["*.rb"]), 6 | visibility = ["//people_tracker/app:__subpackages__"], 7 | ) 8 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/db/migrate/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | rb_library( 4 | name = "migrate", 5 | srcs = glob(["*.rb"]), 6 | visibility = ["//people_tracker/db:__subpackages__"], 7 | ) 8 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/application_system_test_case.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase 4 | driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400] 5 | end 6 | -------------------------------------------------------------------------------- /ruby/private/bundle_fetch/BUILD: -------------------------------------------------------------------------------- 1 | load("@bazel_skylib//:bzl_library.bzl", "bzl_library") 2 | 3 | bzl_library( 4 | name = "gemfile_lock_parser", 5 | srcs = ["gemfile_lock_parser.bzl"], 6 | visibility = ["//ruby:__subpackages__"], 7 | ) 8 | -------------------------------------------------------------------------------- /examples/gem/spec/support_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'spec_helper' 4 | 5 | RSpec.describe File do 6 | specify do 7 | expect(File.read('spec/support/file.txt').chomp).to eq('File!') 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /rails/rails_test_factory.bzl: -------------------------------------------------------------------------------- 1 | """Public definition for `rails_test_factory`.""" 2 | 3 | load( 4 | "//rails/private:rails_test_factory.bzl", 5 | _rails_test_factory = "rails_test_factory", 6 | ) 7 | 8 | rails_test_factory = _rails_test_factory 9 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/controllers/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | rb_library( 4 | name = "controllers", 5 | srcs = glob(["*.rb"]), 6 | visibility = ["//people_tracker/app:__subpackages__"], 7 | ) 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore all Bazel symlinks 2 | bazel-* 3 | 4 | # Ignore Bazel lock file. 5 | MODULE.bazel.lock 6 | 7 | 8 | examples/rails/people_tracker/log/** 9 | examples/rails/people_tracker/storage/** 10 | examples/rails/people_tracker/tmp/*** 11 | 12 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 2 | 3 | require "bundler/setup" # Set up gems listed in the Gemfile. 4 | require "bootsnap/setup" # Speed up boot time by caching expensive operations. 5 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/environments/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | rb_library( 4 | name = "environments", 5 | srcs = glob(["*.rb"]), 6 | visibility = ["//people_tracker/config:__subpackages__"], 7 | ) 8 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/initializers/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | rb_library( 4 | name = "initializers", 5 | srcs = glob(["*.rb"]), 6 | visibility = ["//people_tracker/config:__subpackages__"], 7 | ) 8 | -------------------------------------------------------------------------------- /rails/private/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_skylib//:bzl_library.bzl", "bzl_library") 2 | 3 | bzl_library( 4 | name = "rails_test_factory", 5 | srcs = ["rails_test_factory.bzl"], 6 | visibility = ["//rails:__subpackages__"], 7 | deps = ["//ruby:defs"], 8 | ) 9 | -------------------------------------------------------------------------------- /examples/gem/spec/add_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'spec_helper' 4 | 5 | RSpec.describe GEM::Add do 6 | describe '#result' do 7 | specify do 8 | expect(GEM::Add.new(2, 2).result).to eq(4) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /examples/gem/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | gemspec 5 | 6 | gem 'debug', '>= 1.0.0', platforms: %i[mri mswin64] 7 | gem 'psych', '~> 5.1' # Gem with native extensions. 8 | gem 'rspec', '~> 3.0' 9 | gem 'rubocop', '~> 1.64' 10 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative "config/application" 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | # Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has. 3 | allow_browser versions: :modern 4 | end 5 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: test 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: people_tracker_production 11 | -------------------------------------------------------------------------------- /ruby/private/bundle_fetch/bin/BUILD.tpl: -------------------------------------------------------------------------------- 1 | """@generated by @rules_ruby//:ruby/private/bundle_fetch.bzl""" 2 | 3 | load("@rules_ruby//ruby:defs.bzl", "rb_binary") 4 | 5 | package(default_visibility = ["//visibility:public"]) 6 | 7 | {gem_binary_fragments} 8 | 9 | # vim: ft=bzl 10 | -------------------------------------------------------------------------------- /.bazelrc: -------------------------------------------------------------------------------- 1 | # This file contains Bazel settings to apply on Release only. 2 | # It is referenced with a --bazelrc option in the call to bazel in release.yaml 3 | # 4 | # Not ready for the MODULE.lock file yet, as of Bazel 7.0.0 there are still some stability issues. 5 | common --lockfile_mode=off 6 | -------------------------------------------------------------------------------- /examples/gem/spec/subtract_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'spec_helper' 4 | 5 | RSpec.describe GEM::Subtract do 6 | describe '#result' do 7 | specify do 8 | expect(GEM::Subtract.new(2, 2).result).to eq(0) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | TODO 4 | 5 | ## Releasing 6 | 7 | To perform a release, simply tag the commit you wish to release, for example: 8 | 9 | ``` 10 | rules_ruby$ git fetch 11 | rules_ruby$ git tag v1.2.3 origin/main 12 | rules_ruby$ git push origin v1.2.3 13 | ``` -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ], 6 | "ignoreDeps": [ 7 | "bazel_features", 8 | "bazel_skylib", 9 | "platforms", 10 | "rules_cc", 11 | "rules_java" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/db/migrate/20250821215024_create_people.rb: -------------------------------------------------------------------------------- 1 | class CreatePeople < ActiveRecord::Migration[8.0] 2 | def change 3 | create_table :people do |t| 4 | t.string :first_name 5 | t.string :last_name 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/db/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | rb_library( 4 | name = "db", 5 | srcs = glob(["*.rb"]), 6 | visibility = ["//people_tracker:__subpackages__"], 7 | deps = [ 8 | "//people_tracker/db/migrate", 9 | ], 10 | ) 11 | -------------------------------------------------------------------------------- /.bcr/source.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "integrity": "**leave this alone**", 3 | "strip_prefix": "{REPO}-{VERSION}", 4 | "docs_url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/{REPO}-{TAG}.docs.tar.gz", 5 | "url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/{REPO}-{TAG}.tar.gz" 6 | } 7 | -------------------------------------------------------------------------------- /examples/deep_gem/do_test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o pipefail 4 | 5 | # Use the Bazel binary specified by the integration test. Otherise, fall back 6 | # to bazel. 7 | bazel="${BIT_BAZEL_BINARY:-bazel}" 8 | 9 | # Ensure that it builds and tests pass 10 | "${bazel}" test //... 11 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/spec/hello_world_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "spec_helper" 4 | require_relative "../lib/hello_world" 5 | 6 | RSpec.describe HelloWorld do 7 | it "has a version number" do 8 | expect(HelloWorld::VERSION).not_to be nil 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /examples/rails/do_test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o pipefail 4 | 5 | # Use the Bazel binary specified by the integration test. Otherise, fall back 6 | # to bazel. 7 | bazel="${BIT_BAZEL_BINARY:-bazel}" 8 | 9 | # Ensure that it builds and tests pass 10 | "${bazel}" test //... 11 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/.rubocop.yml: -------------------------------------------------------------------------------- 1 | # Omakase Ruby styling for Rails 2 | inherit_gem: {rubocop-rails-omakase: rubocop.yml} 3 | 4 | # Overwrite or add rules to create your own house style 5 | # 6 | # # Use `[a, [b, c]]` not `[ a, [ b, c ] ]` 7 | # Layout/SpaceInsideArrayLiteralBrackets: 8 | # Enabled: false 9 | -------------------------------------------------------------------------------- /examples/gem/lib/gem/subtract.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module GEM 4 | class Subtract # :nodoc: 5 | def initialize(a, b) # rubocop:disable Naming/MethodParameterName 6 | @a = a 7 | @b = b 8 | end 9 | 10 | def result 11 | @a - @b 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/models/person.rb: -------------------------------------------------------------------------------- 1 | class Person < ApplicationRecord 2 | after_commit -> { broadcast_refresh_later_to "people" } 3 | 4 | validates :first_name, :last_name, presence: true 5 | 6 | def full_name 7 | [first_name, last_name].select(&:present?).join(" ") 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /examples/rails/.envrc: -------------------------------------------------------------------------------- 1 | bazel_env_dir="bazel-out/bazel_env-opt/bin/bazel_env/bin" 2 | 3 | watch_file "${bazel_env_dir}" 4 | PATH_add "${bazel_env_dir}" 5 | 6 | if [ ! -d "${bazel_env_dir}" ]; then 7 | log_error "ERROR[bazel_env.bzl]: Run 'bazel run //:bazel_env' to" \ 8 | "regenerate ${bazel_env_dir}" 9 | fi 10 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/javascript/controllers/application.js: -------------------------------------------------------------------------------- 1 | import { Application } from "@hotwired/stimulus"; 2 | 3 | const application = Application.start(); 4 | 5 | // Configure Stimulus development experience 6 | application.debug = false; 7 | window.Stimulus = application; 8 | 9 | export { application }; 10 | -------------------------------------------------------------------------------- /.bcr/metadata.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "homepage": "https://github.com/bazel-contrib/rules_ruby", 3 | "maintainers": [ 4 | { 5 | "github": "p0deje", 6 | "name": "Alex Rodionov" 7 | } 8 | ], 9 | "repository": ["github:bazel-contrib/rules_ruby"], 10 | "versions": [], 11 | "yanked_versions": {} 12 | } 13 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/bin/rubocop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "rubygems" 3 | require "bundler/setup" 4 | 5 | # explicit rubocop config increases performance slightly while avoiding config confusion. 6 | ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__)) 7 | 8 | load Gem.bin_path("rubocop", "rubocop") 9 | -------------------------------------------------------------------------------- /.bcr/config.yml: -------------------------------------------------------------------------------- 1 | # See https://github.com/bazel-contrib/publish-to-bcr#a-note-on-release-automation 2 | # Our releases are created by github actions based on pushing a tag, so they don't have an author. 3 | # This person's fork of BCR will be used to originate pull requests. 4 | fixedReleaser: 5 | login: alexeagle 6 | email: alex@aspect.dev 7 | -------------------------------------------------------------------------------- /examples/gem/lib/BUILD: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | package(default_visibility = ["//:__subpackages__"]) 4 | 5 | rb_library( 6 | name = "gem", 7 | srcs = ["gem.rb"], 8 | deps = [ 9 | "//lib/gem:add", 10 | "//lib/gem:subtract", 11 | "//lib/gem:version", 12 | ], 13 | ) 14 | -------------------------------------------------------------------------------- /examples/native_ext/.bazelrc: -------------------------------------------------------------------------------- 1 | # Not ready for the MODULE.lock file yet, as of Bazel 7.0.0 there are still some stability issues. 2 | common --lockfile_mode=off 3 | 4 | # Allow to run Bazel without pre-installed JDK. 5 | # Docs: https://bazel.build/reference/command-line-reference#flag--java_runtime_version 6 | build --java_runtime_version=remotejdk_21 7 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | # Automatically retry jobs that encountered a deadlock 3 | # retry_on ActiveRecord::Deadlocked 4 | 5 | # Most jobs are safe to ignore if the underlying records are no longer available 6 | # discard_on ActiveJob::DeserializationError 7 | end 8 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/importmap.rb: -------------------------------------------------------------------------------- 1 | # Pin npm packages by running ./bin/importmap 2 | 3 | pin "application" 4 | pin "@hotwired/turbo-rails", to: "turbo.min.js" 5 | pin "@hotwired/stimulus", to: "stimulus.min.js" 6 | pin "@hotwired/stimulus-loading", to: "stimulus-loading.js" 7 | pin_all_from "app/javascript/controllers", under: "controllers" -------------------------------------------------------------------------------- /ruby/private/gem_install/gem_install.cmd.tpl: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | {env} 4 | 5 | {gem_binary} ^ 6 | install ^ 7 | {gem} ^ 8 | --wrappers ^ 9 | --ignore-dependencies ^ 10 | --local ^ 11 | --no-document ^ 12 | --no-env-shebang ^ 13 | --install-dir {install_dir} ^ 14 | --bindir {install_dir}/bin 15 | 16 | :: vim: ft=dosbatch 17 | -------------------------------------------------------------------------------- /ruby/private/gem_install/gem_install.sh.tpl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | {env} 4 | 5 | {gem_binary} \ 6 | install \ 7 | {gem} \ 8 | --wrappers \ 9 | --ignore-dependencies \ 10 | --local \ 11 | --no-document \ 12 | --no-env-shebang \ 13 | --install-dir {install_dir} \ 14 | --bindir {install_dir}/bin 15 | 16 | # vim: ft=bash 17 | -------------------------------------------------------------------------------- /examples/gem/lib/gem/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module GEM 4 | VERSION = '0.1.0' 5 | end 6 | 7 | if __FILE__ == $PROGRAM_NAME 8 | puts "Ruby is: #{RUBY_ENGINE}/#{RUBY_VERSION}" 9 | puts "Java version is: #{ENV_JAVA['java.version']}" if Object.const_defined?(:ENV_JAVA) 10 | puts "Version is: #{GEM::VERSION}" 11 | end 12 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/BUILD.bazel: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "files", 3 | srcs = [ 4 | "//people_tracker/app/views/layouts:files", 5 | "//people_tracker/app/views/people:files", 6 | "//people_tracker/app/views/pwa:files", 7 | ], 8 | visibility = ["//people_tracker/app:__subpackages__"], 9 | ) 10 | -------------------------------------------------------------------------------- /examples/gem/.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | NewCops: enable 3 | SuggestExtensions: false 4 | TargetRubyVersion: 3.0 5 | Exclude: 6 | - 'external/**/*' 7 | 8 | # There is a difference in line endings between 9 | # GitHub Actions and Bazel CI. 10 | # https://github.com/bazel-contrib/rules_ruby/issues/27 11 | Layout/EndOfLine: 12 | Enabled: false 13 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/bin/BUILD.bazel: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "files", 3 | srcs = [ 4 | "brakeman", 5 | "dev", 6 | "docker-entrypoint", 7 | "rails", 8 | "rake", 9 | "rubocop", 10 | "setup", 11 | "thrust", 12 | ], 13 | visibility = ["//people_tracker:__subpackages__"], 14 | ) 15 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = "1.0" 5 | 6 | # Add additional assets to the asset load path. 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/lib/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | rb_library( 4 | name = "hello_world", 5 | srcs = ["hello_world.rb"], 6 | visibility = ["//hello_world:__subpackages__"], 7 | deps = [ 8 | "//hello_world/lib/hello_world:speaker", 9 | "//hello_world/lib/hello_world:version", 10 | ], 11 | ) 12 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/lib/hello_world/speaker.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module HelloWorld 4 | class Speaker 5 | attr_reader :name 6 | 7 | def initialize(name = "world") 8 | @name = name 9 | end 10 | 11 | def message 12 | "Hello, #{@name}" 13 | end 14 | 15 | def hi 16 | puts message 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/lib/hello_world/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | rb_library( 4 | name = "version", 5 | srcs = ["version.rb"], 6 | visibility = ["//hello_world:__subpackages__"], 7 | ) 8 | 9 | rb_library( 10 | name = "speaker", 11 | srcs = ["speaker.rb"], 12 | visibility = ["//hello_world:__subpackages__"], 13 | ) 14 | -------------------------------------------------------------------------------- /ruby/private/bundle/BUILD.tpl: -------------------------------------------------------------------------------- 1 | """@generated by @rules_ruby//:ruby/private/binary.bzl""" 2 | 3 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 4 | load("//:defs.bzl", "BUNDLE_ENV") 5 | 6 | package(default_visibility = ["//visibility:public"]) 7 | 8 | rb_library( 9 | name = "bundle", 10 | bundle_env = BUNDLE_ENV, 11 | data = glob(["**/*"]), 12 | ) 13 | 14 | # vim: ft=bzl 15 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/people/_person.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 | First name: 4 | <%= person.first_name %> 5 |
6 |
7 | Last name: 8 | <%= person.last_name %> 9 |
10 |
11 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/rails_test.bzl: -------------------------------------------------------------------------------- 1 | """Module for app-specific rails helpers and macros.""" 2 | 3 | load("@rules_ruby//rails:rails_test_factory.bzl", "rails_test_factory") 4 | 5 | _TEST_PKG = "people_tracker/test" 6 | 7 | rails_test = rails_test_factory.new_test(test_package = _TEST_PKG) 8 | 9 | rails_system_test = rails_test_factory.new_system_test(test_package = _TEST_PKG) 10 | -------------------------------------------------------------------------------- /.bcr/README.md: -------------------------------------------------------------------------------- 1 | # Bazel Central Registry 2 | 3 | When the ruleset is released, we want it to be published to the 4 | Bazel Central Registry automatically: 5 | 6 | 7 | This folder contains configuration files to automate the publish step. 8 | See 9 | for authoritative documentation about these files. 10 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/fixtures/people.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at 2 | # https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 3 | 4 | john_doe: 5 | first_name: John 6 | last_name: Doe 7 | 8 | jane_smith: 9 | first_name: Jane 10 | last_name: Smith 11 | 12 | bob_johnson: 13 | first_name: Bob 14 | last_name: Johnson 15 | 16 | alice_brown: 17 | first_name: Alice 18 | last_name: Brown 19 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/javascript/controllers/index.js: -------------------------------------------------------------------------------- 1 | // Import and register all your controllers from the importmap via controllers/**/*_controller 2 | import { application } from "controllers/application"; 3 | 4 | // Eager load all controllers defined in the import map under controllers/**/*_controller 5 | import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"; 6 | eagerLoadControllersFrom("controllers", application); 7 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/people/new.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, "New person" %> 2 | 3 |
4 |

New person

5 | 6 | <%= render "form", person: @person %> 7 | 8 | <%= link_to "Back to people", people_path, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> 9 |
10 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.configure do |config| 4 | # Enable flags like --only-failures and --next-failure 5 | config.example_status_persistence_file_path = ".rspec_status" 6 | 7 | # Disable RSpec exposing methods globally on `Module` and `main` 8 | config.disable_monkey_patching! 9 | 10 | config.expect_with :rspec do |c| 11 | c.syntax = :expect 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/bin/dev: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | if ! gem list foreman -i --silent; then 4 | echo "Installing foreman..." 5 | gem install foreman 6 | fi 7 | 8 | # Default to port 3000 if not specified 9 | export PORT="${PORT:-3000}" 10 | 11 | # Let the debug gem allow remote connections, 12 | # but avoid loading until `debugger` is called 13 | export RUBY_DEBUG_OPEN="true" 14 | export RUBY_DEBUG_LAZY="true" 15 | 16 | exec foreman start -f Procfile.dev "$@" 17 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/bin/docker-entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Enable jemalloc for reduced memory usage and latency. 4 | if [ -z "${LD_PRELOAD+x}" ]; then 5 | LD_PRELOAD=$(find /usr/lib -name libjemalloc.so.2 -print -quit) 6 | export LD_PRELOAD 7 | fi 8 | 9 | # If running the rails server then create or migrate existing database 10 | if [ "${@: -2:1}" == "./bin/rails" ] && [ "${@: -1:1}" == "server" ]; then 11 | ./bin/rails db:prepare 12 | fi 13 | 14 | exec "${@}" 15 | -------------------------------------------------------------------------------- /.github/workflows/ci.bazelrc: -------------------------------------------------------------------------------- 1 | # This file contains Bazel settings to apply on Release only. 2 | # It is referenced with a --bazelrc option in the call to bazel in release.yaml 3 | 4 | # Debug where options came from 5 | build --announce_rc 6 | # Don't rely on test logs being easily accessible from the test runner, 7 | # though it makes the log noisier. 8 | test --test_output=errors 9 | # Allows tests to run bazelisk-in-bazel, since this is the cache folder used 10 | test --test_env=XDG_CACHE_HOME 11 | -------------------------------------------------------------------------------- /BUILD: -------------------------------------------------------------------------------- 1 | load("@buildifier_prebuilt//:rules.bzl", "buildifier") 2 | load("@gazelle//:def.bzl", "gazelle", "gazelle_binary") 3 | 4 | gazelle_binary( 5 | name = "gazelle_bin", 6 | languages = ["@bazel_skylib_gazelle_plugin//bzl"], 7 | ) 8 | 9 | gazelle( 10 | name = "gazelle", 11 | gazelle = "gazelle_bin", 12 | ) 13 | 14 | buildifier( 15 | name = "buildifier.check", 16 | diff_command = "diff -u", 17 | exclude_patterns = ["./.git/*"], 18 | lint_mode = "warn", 19 | mode = "diff", 20 | ) 21 | -------------------------------------------------------------------------------- /examples/gem/wrapper.tpl.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | @@rlocation_lib@@ 4 | 5 | set -euo pipefail 6 | 7 | rake_binary_expansion=(@@rake_binary@@) 8 | 9 | echo "calling the rake binary" 10 | rake="$(rlocation @@rake_binary@@)" 11 | rakefile="$(rlocation @@rakefile@@)" 12 | "$rake" -f "$rakefile" goodnight 13 | set -x 14 | eval "$("$rake" -f "$rakefile" goodnight)" 15 | set +x 16 | 17 | echo "rake failed to fail" 18 | echo "rlocationpaths for rake binary:" 19 | printf ' %s\n' "${rake_binary_expansion[@]}" 20 | exit 1 21 | -------------------------------------------------------------------------------- /examples/jekyll/404.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | 18 | 19 |
20 |

404

21 | 22 |

Page not found :(

23 |

The requested page could not be found.

24 |
25 | -------------------------------------------------------------------------------- /rails/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_skylib//:bzl_library.bzl", "bzl_library") 2 | 3 | exports_files(["rails_test_factory.bzl"]) 4 | 5 | bzl_library( 6 | name = "rails_test_factory", 7 | srcs = ["rails_test_factory.bzl"], 8 | visibility = ["//visibility:public"], 9 | deps = [ 10 | "//rails/private:rails_test_factory", 11 | ], 12 | ) 13 | 14 | starlark_doc_extract( 15 | name = "rails_test_factory.doc_extract", 16 | src = "rails_test_factory.bzl", 17 | deps = [":rails_test_factory"], 18 | ) 19 | -------------------------------------------------------------------------------- /examples/rails/.bazelrc: -------------------------------------------------------------------------------- 1 | # Verbose Failures 2 | build --verbose_failures 3 | 4 | # Test output information 5 | test --test_output=errors --test_summary=detailed 6 | 7 | # Strict PATH. Helps prevent build cache invalidation due to PATH differences. 8 | build --incompatible_strict_action_env=true 9 | 10 | # Don't allow empty glob patterns by default 11 | build --incompatible_disallow_empty_glob 12 | 13 | # Enable bzlmod 14 | common --enable_bzlmod 15 | 16 | # Download the JDK to run Bazel 17 | build --java_runtime_version=remotejdk_11 18 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file. 4 | # Use this to limit dissemination of sensitive information. 5 | # See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. 6 | Rails.application.config.filter_parameters += [ 7 | :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, :cvv, :cvc 8 | ] 9 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/pwa/manifest.json.erb: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PeopleTracker", 3 | "icons": [ 4 | { 5 | "src": "/icon.png", 6 | "type": "image/png", 7 | "sizes": "512x512" 8 | }, 9 | { 10 | "src": "/icon.png", 11 | "type": "image/png", 12 | "sizes": "512x512", 13 | "purpose": "maskable" 14 | } 15 | ], 16 | "start_url": "/", 17 | "display": "standalone", 18 | "scope": "/", 19 | "description": "People Tracker.", 20 | "theme_color": "red", 21 | "background_color": "red" 22 | } 23 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should ensure the existence of records required to run the application in every environment (production, 2 | # development, test). The code here should be idempotent so that it can be executed at any point in every environment. 3 | # The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). 4 | # 5 | # Example: 6 | # 7 | # ["Action", "Comedy", "Drama", "Horror"].each do |genre_name| 8 | # MovieGenre.find_or_create_by!(name: genre_name) 9 | # end 10 | -------------------------------------------------------------------------------- /ruby/private/bundle_fetch/BUILD.tpl: -------------------------------------------------------------------------------- 1 | """@generated by @rules_ruby//:ruby/private/bundle_fetch.bzl""" 2 | 3 | load("@rules_ruby//ruby:defs.bzl", "rb_bundle_install", "rb_gem", "rb_gem_install") 4 | 5 | package(default_visibility = ["//visibility:public"]) 6 | 7 | rb_bundle_install( 8 | name = "{name}", 9 | srcs = {srcs}, 10 | env = {env}, 11 | gemfile = "{gemfile_path}", 12 | gemfile_lock = "{gemfile_lock_path}", 13 | gems = {gems}, 14 | ruby = {ruby}, 15 | ) 16 | 17 | {gem_fragments} 18 | 19 | {gem_install_fragments} 20 | 21 | # vim: ft=bzl 22 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/credentials.yml.enc: -------------------------------------------------------------------------------- 1 | PqmOA8TR9Gz0FHOtrpuxYnAcDkoD6JDBjedD4uIrTyM3Q+ve2QgCHRin45b3vySwJ4Ao437LiMYyCYuqGBHhc047AAGkxdmbbNkal5rmojfdgQ3HAgUfP0QZcKcUOQYtehN21MKXVXsrTzOLQjtktGADUpUI94+7g6GZzI/KRMW23c5MT9t5C5+umH3lFuk5shEDwkkwETezL4e5Bxl/QZmF3Eft0GWtSVQvWsN09Lls1w1hbvJ99PMs+5I+towYDt0bmbh4SArg87gcChupyCWHT5S43B/nD64Z0llyBnGtmmcHwLX6poeWtFNMx7wbJNWlSrJJGVkA0ypa/JMOK/Py9V9pIezHWRYfziHFCd0azLLdIgJTd03p2H+a+doXrNDvJSfeIDgw+HU6UCvnlFw0iGsANCJUFHYIDjPp93FsCTLqPmlyKZQHmvapaZ8Bhn0MUo/eozASLdgj0Xj99OV/axmLepdU8BmNUR8dnxs6NzlkrfY7/oBA--BSW+HirppL4YcBWZ--chud7xgdM5nvnYFjLmI5Vw== -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css. 3 | * 4 | * With Propshaft, assets are served efficiently without preprocessing steps. You can still include 5 | * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard 6 | * cascading order, meaning styles declared later in the document or manifest will override earlier ones, 7 | * depending on specificity. 8 | * 9 | * Consider organizing styles into separate files for maintainability. 10 | */ 11 | -------------------------------------------------------------------------------- /.bcr/presubmit.yml: -------------------------------------------------------------------------------- 1 | # https://github.com/bazel-contrib/publish-to-bcr/tree/main/templates#presubmityml 2 | bcr_test_module: 3 | module_path: "examples/gem" 4 | matrix: 5 | bazel: ["8.x", "7.x", "6.x"] 6 | # NB: Windows is removed due to https://github.com/bazel-contrib/rules_ruby/issues/64 7 | platform: ["debian10", "macos", "ubuntu2004"] 8 | tasks: 9 | run_tests: 10 | name: "Run test module" 11 | platform: ${{ platform }} 12 | bazel: ${{ bazel }} 13 | test_flags: 14 | - "--test_tag_filters=-bcr-presubmit-failure" 15 | test_targets: 16 | - "//..." 17 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | rb_library( 4 | name = "app", 5 | data = [ 6 | "//people_tracker/app/assets:files", 7 | "//people_tracker/app/javascript:files", 8 | "//people_tracker/app/views:files", 9 | ], 10 | visibility = ["//people_tracker:__subpackages__"], 11 | deps = [ 12 | "//people_tracker/app/controllers", 13 | "//people_tracker/app/helpers", 14 | "//people_tracker/app/jobs", 15 | "//people_tracker/app/mailers", 16 | "//people_tracker/app/models", 17 | ], 18 | ) 19 | -------------------------------------------------------------------------------- /docs/BUILD: -------------------------------------------------------------------------------- 1 | # This load statement must be in the docs/ package rather than anything users depend on 2 | # so that the dependency on stardoc doesn't leak to them. 3 | load("@aspect_bazel_lib//lib:docs.bzl", "stardoc_with_diff_test", "update_docs") 4 | 5 | stardoc_with_diff_test( 6 | name = "rules", 7 | bzl_library_target = "//ruby:defs", 8 | ) 9 | 10 | stardoc_with_diff_test( 11 | name = "repository_rules", 12 | bzl_library_target = "//ruby:deps", 13 | ) 14 | 15 | stardoc_with_diff_test( 16 | name = "rails", 17 | bzl_library_target = "//rails:rails_test_factory", 18 | ) 19 | 20 | update_docs(name = "update") 21 | -------------------------------------------------------------------------------- /examples/jekyll/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: About 4 | permalink: /about/ 5 | --- 6 | 7 | This is the base Jekyll theme. You can find out more info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at [jekyllrb.com](https://jekyllrb.com/) 8 | 9 | You can find the source code for Minima at GitHub: 10 | [jekyll][jekyll-organization] / 11 | [minima](https://github.com/jekyll/minima) 12 | 13 | You can find the source code for Jekyll at GitHub: 14 | [jekyll][jekyll-organization] / 15 | [jekyll](https://github.com/jekyll/jekyll) 16 | 17 | 18 | [jekyll-organization]: https://github.com/jekyll 19 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/people/edit.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, "Editing person" %> 2 | 3 |
4 |

Editing person

5 | 6 | <%= render "form", person: @person %> 7 | 8 | <%= link_to "Show this person", @person, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> 9 | <%= link_to "Back to people", people_path, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> 10 |
11 | -------------------------------------------------------------------------------- /examples/gem/lib/gem/add.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'i18n' 5 | 6 | module GEM 7 | class Add # :nodoc: 8 | def initialize(a, b) # rubocop:disable Naming/MethodParameterName 9 | @a = a 10 | @b = b 11 | end 12 | 13 | def result 14 | @a + @b 15 | end 16 | end 17 | end 18 | 19 | if __FILE__ == $PROGRAM_NAME 20 | raise "Pass two numbers to sum: #{ARGV}" if ARGV.size < 2 21 | 22 | one, two, output = *ARGV 23 | result = GEM::Add.new(Integer(one), Integer(two)).result 24 | if output 25 | File.write(output, result) 26 | else 27 | puts result 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # See CONTRIBUTING.md for instructions. 2 | # See https://pre-commit.com for more information 3 | # See https://pre-commit.com/hooks.html for more hooks 4 | 5 | repos: 6 | # Check formatting and lint for starlark code 7 | - repo: https://github.com/keith/pre-commit-buildifier 8 | rev: 8.2.0 9 | hooks: 10 | - id: buildifier 11 | - id: buildifier-lint 12 | # Check that commit messages follow https://www.conventionalcommits.org 13 | - repo: https://github.com/compilerla/conventional-pre-commit 14 | rev: v3.0.0 15 | hooks: 16 | - id: conventional-pre-commit 17 | stages: 18 | - commit-msg 19 | args: [] 20 | -------------------------------------------------------------------------------- /examples/gem/spec/env_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'spec_helper' 4 | 5 | RSpec.describe ENV do 6 | specify do 7 | expect(ENV.fetch('EXAMPLE')).to eq('ENV') 8 | end 9 | 10 | specify do 11 | expect(ENV).to have_key('USER').or have_key('USERNAME') 12 | end 13 | 14 | specify do 15 | expect(ENV.fetch('BUNDLE_BUILD__FOO')).to eq('bar') 16 | end 17 | 18 | specify do 19 | expect(File).to exist(ENV.fetch('LOCATION_SRC')) 20 | expect(File).to exist(ENV.fetch('LOCATION_DATA')) 21 | expect(File).to exist(ENV.fetch('LOCATION_DEP')) 22 | end 23 | 24 | specify do 25 | expect(ENV.fetch('RUBY_ENGINE')).to eq(RUBY_ENGINE) 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/hello_world.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "lib/hello_world/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "hello_world" 7 | s.version = HelloWorld::VERSION 8 | 9 | s.authors = ["Foo Bar"] 10 | s.email = ["foobar@gmail.com"] 11 | s.homepage = "http://rubygems.org" 12 | s.license = "MIT" 13 | s.metadata["rubygems_mfa_required"] = "true" 14 | 15 | s.summary = "Example" 16 | s.description = "Example gem" 17 | s.files = Dir["lib/**/*"] 18 | 19 | s.require_paths = ["lib"] 20 | s.required_ruby_version = Gem::Requirement.new(">= 2.6") 21 | 22 | s.add_dependency "irb" 23 | s.add_dependency "rspec", "~> 3.0" 24 | end 25 | -------------------------------------------------------------------------------- /examples/native_ext/MODULE.bazel: -------------------------------------------------------------------------------- 1 | "Bazel dependencies" 2 | 3 | bazel_dep(name = "platforms", version = "0.0.10", dev_dependency = True) 4 | bazel_dep(name = "rules_cc", version = "0.1.1", dev_dependency = True) 5 | bazel_dep(name = "rules_java", version = "8.7.1", dev_dependency = True) 6 | bazel_dep(name = "rules_ruby", version = "0.0.0", dev_dependency = True) 7 | local_path_override( 8 | module_name = "rules_ruby", 9 | path = "../..", 10 | ) 11 | 12 | ruby = use_extension("@rules_ruby//ruby:extensions.bzl", "ruby") 13 | ruby.toolchain( 14 | name = "ruby", 15 | version_file = "//:.ruby-version", 16 | ) 17 | use_repo(ruby, "ruby", "ruby_toolchains") 18 | 19 | register_toolchains("@ruby_toolchains//:all") 20 | -------------------------------------------------------------------------------- /examples/native_ext/BUILD: -------------------------------------------------------------------------------- 1 | load("@rules_cc//cc:defs.bzl", "cc_library") 2 | load("@rules_java//java:defs.bzl", "java_library") 3 | 4 | cc_library( 5 | name = "ext_c", 6 | srcs = glob([ 7 | "ext/**/*.c", 8 | "ext/**/*.h", 9 | ]), 10 | target_compatible_with = select({ 11 | "@ruby//engine:ruby": [], 12 | "//conditions:default": ["@platforms//:incompatible"], 13 | }), 14 | deps = ["@ruby//:headers"], 15 | ) 16 | 17 | java_library( 18 | name = "ext_java", 19 | srcs = glob(["ext/**/*.java"]), 20 | target_compatible_with = select({ 21 | "@ruby//engine:jruby": [], 22 | "//conditions:default": ["@platforms//:incompatible"], 23 | }), 24 | deps = ["@ruby//:jars"], 25 | ) 26 | -------------------------------------------------------------------------------- /examples/gem/gem.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | root = File.expand_path(__dir__) 4 | $LOAD_PATH.push(File.expand_path('lib', root)) 5 | require 'gem/version' 6 | 7 | Gem::Specification.new do |s| 8 | s.name = 'example' 9 | s.version = GEM::VERSION 10 | 11 | s.authors = ['Foo Bar'] 12 | s.email = ['foobar@gmail.com'] 13 | s.homepage = 'http://rubygems.org' 14 | s.license = 'MIT' 15 | s.metadata['rubygems_mfa_required'] = 'true' 16 | 17 | s.summary = 'Example' 18 | s.description = 'Example gem' 19 | s.files = Dir['lib/**/*'] 20 | 21 | s.require_paths = ['lib'] 22 | s.required_ruby_version = Gem::Requirement.new('>= 2.6') 23 | 24 | s.add_dependency 'i18n', '~> 1.14' 25 | s.add_dependency 'rake', '~> 13' 26 | end 27 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 2 | 3 | package(default_visibility = ["//people_tracker:__subpackages__"]) 4 | 5 | rb_library( 6 | name = "config", 7 | srcs = glob(["*.rb"]), 8 | data = [ 9 | ":files", 10 | "//people_tracker/config/locales:files", 11 | ], 12 | deps = [ 13 | "//people_tracker/app", 14 | "//people_tracker/config/environments", 15 | "//people_tracker/config/initializers", 16 | "//people_tracker/db", 17 | "@people_tracker_bundle", 18 | ], 19 | ) 20 | 21 | filegroup( 22 | name = "files", 23 | srcs = glob( 24 | [ 25 | "*", 26 | ], 27 | exclude = ["*.rb"], 28 | ), 29 | ) 30 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, "\\1en" 8 | # inflect.singular /^(ox)en/i, "\\1" 9 | # inflect.irregular "person", "people" 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym "RESTful" 16 | # end 17 | -------------------------------------------------------------------------------- /ruby/private/download/BUILD.engine.tpl: -------------------------------------------------------------------------------- 1 | load("@bazel_skylib//rules:common_settings.bzl", "string_flag") 2 | 3 | package(default_visibility = ["//visibility:public"]) 4 | 5 | string_flag( 6 | name = "engine", 7 | values = [ 8 | "jruby", 9 | "truffleruby", 10 | "ruby", 11 | ], 12 | build_setting_default = "{ruby_engine}", 13 | ) 14 | 15 | config_setting( 16 | name = "jruby", 17 | flag_values = { 18 | ":engine": "jruby", 19 | }, 20 | ) 21 | 22 | config_setting( 23 | name = "truffleruby", 24 | flag_values = { 25 | ":engine": "truffleruby", 26 | }, 27 | ) 28 | 29 | config_setting( 30 | name = "ruby", 31 | flag_values = { 32 | ":engine": "ruby", 33 | }, 34 | ) 35 | 36 | # vim: ft=bzl 37 | -------------------------------------------------------------------------------- /ruby/deps.bzl: -------------------------------------------------------------------------------- 1 | "Public API for repository rules" 2 | 3 | load("//ruby/private:bundle.bzl", _rb_bundle = "rb_bundle") 4 | load("//ruby/private:bundle_fetch.bzl", _rb_bundle_fetch = "rb_bundle_fetch") 5 | load("//ruby/private:toolchain.bzl", _rb_register_toolchains = "rb_register_toolchains") 6 | 7 | def rb_bundle(toolchain = "@ruby//:BUILD", **kwargs): 8 | """ 9 | Wraps `rb_bundle_rule()` providing default toolchain name. 10 | 11 | Args: 12 | toolchain: default Ruby toolchain BUILD 13 | **kwargs: underlying attrs passed to rb_bundle_rule() 14 | """ 15 | _rb_bundle( 16 | toolchain = toolchain, 17 | **kwargs 18 | ) 19 | 20 | rb_register_toolchains = _rb_register_toolchains 21 | rb_bundle_fetch = _rb_bundle_fetch 22 | rb_bundle_rule = _rb_bundle 23 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | resources :people 3 | # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html 4 | 5 | # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. 6 | # Can be used by load balancers and uptime monitors to verify that the app is live. 7 | get "up" => "rails/health#show", :as => :rails_health_check 8 | 9 | # Render dynamic PWA files from app/views/pwa/* (remember to link manifest in application.html.erb) 10 | # get "manifest" => "rails/pwa#manifest", as: :pwa_manifest 11 | # get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker 12 | 13 | # Defines the root path route ("/") 14 | # root "posts#index" 15 | end 16 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_skylib//:bzl_library.bzl", "bzl_library") 2 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 3 | 4 | rb_library( 5 | name = "test_helper", 6 | srcs = ["test_helper.rb"], 7 | visibility = ["//people_tracker/test:__subpackages__"], 8 | deps = [ 9 | "//people_tracker/config", 10 | ], 11 | ) 12 | 13 | rb_library( 14 | name = "application_system_test_case", 15 | srcs = ["application_system_test_case.rb"], 16 | visibility = ["//people_tracker/test:__subpackages__"], 17 | deps = [ 18 | ":test_helper", 19 | ], 20 | ) 21 | 22 | bzl_library( 23 | name = "rails_test", 24 | srcs = ["rails_test.bzl"], 25 | visibility = ["//visibility:public"], 26 | deps = ["@rules_ruby//rails:rails_test_factory"], 27 | ) 28 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/spec/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library", "rb_test") 2 | 3 | rb_library( 4 | name = "spec_helper", 5 | srcs = ["spec_helper.rb"], 6 | deps = [ 7 | "@bundle", 8 | ], 9 | ) 10 | 11 | rb_test( 12 | name = "hello_world_spec", 13 | srcs = ["hello_world_spec.rb"], 14 | args = ["hello_world/spec/hello_world_spec.rb"], 15 | main = "@bundle//bin:rspec", 16 | deps = [ 17 | ":spec_helper", 18 | "//hello_world/lib:hello_world", 19 | ], 20 | ) 21 | 22 | rb_test( 23 | name = "speaker_spec", 24 | srcs = ["speaker_spec.rb"], 25 | args = ["hello_world/spec/speaker_spec.rb"], 26 | main = "@bundle//bin:rspec", 27 | deps = [ 28 | ":spec_helper", 29 | "//hello_world/lib:hello_world", 30 | ], 31 | ) 32 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require_relative "../config/initializers/bazel_ruby_patches" 2 | 3 | ENV["RAILS_ENV"] ||= "test" 4 | require_relative "../config/environment" 5 | require "rails/test_help" 6 | 7 | # Load schema once for in-memory database before fixtures 8 | ActiveRecord::Tasks::DatabaseTasks.load_schema_current 9 | 10 | module ActiveSupport 11 | class TestCase 12 | # Run tests in parallel with specified workers 13 | parallelize(workers: :number_of_processors) 14 | 15 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. 16 | fixtures :all 17 | 18 | # Use transactional tests for automatic rollback (this is the default) 19 | self.use_transactional_tests = true 20 | 21 | # Add more helper methods to be used by all tests here... 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /ruby/defs.bzl: -------------------------------------------------------------------------------- 1 | "Public API for rules" 2 | 3 | load("//ruby/private:binary.bzl", _rb_binary = "rb_binary") 4 | load("//ruby/private:bundle_install.bzl", _rb_bundle_install = "rb_bundle_install") 5 | load("//ruby/private:gem.bzl", _rb_gem = "rb_gem") 6 | load("//ruby/private:gem_build.bzl", _rb_gem_build = "rb_gem_build") 7 | load("//ruby/private:gem_install.bzl", _rb_gem_install = "rb_gem_install") 8 | load("//ruby/private:gem_push.bzl", _rb_gem_push = "rb_gem_push") 9 | load("//ruby/private:library.bzl", _rb_library = "rb_library") 10 | load("//ruby/private:test.bzl", _rb_test = "rb_test") 11 | 12 | rb_binary = _rb_binary 13 | rb_bundle_install = _rb_bundle_install 14 | rb_gem = _rb_gem 15 | rb_gem_build = _rb_gem_build 16 | rb_gem_install = _rb_gem_install 17 | rb_gem_push = _rb_gem_push 18 | rb_library = _rb_library 19 | rb_test = _rb_test 20 | -------------------------------------------------------------------------------- /ruby/private/gem.bzl: -------------------------------------------------------------------------------- 1 | "Implementation details for rb_gem" 2 | 3 | load("//ruby/private:providers.bzl", "GemInfo") 4 | 5 | def _rb_gem_impl(ctx): 6 | gem = ctx.file.gem 7 | name, _, version = ctx.attr.name.rpartition("-") 8 | 9 | return [ 10 | DefaultInfo(files = depset([gem])), 11 | GemInfo( 12 | name = name, 13 | version = version, 14 | ), 15 | ] 16 | 17 | rb_gem = rule( 18 | _rb_gem_impl, 19 | attrs = { 20 | "gem": attr.label( 21 | allow_single_file = [".gem"], 22 | mandatory = True, 23 | doc = "Gem file.", 24 | ), 25 | }, 26 | doc = """ 27 | Exposes a Ruby gem file. 28 | 29 | You normally don't need to call this rule directly as it's an internal one 30 | used by `rb_bundle_fetch()`. 31 | """, 32 | ) 33 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_env.bzl", "bazel_env") 2 | load("@bazel_skylib//rules:build_test.bzl", "build_test") 3 | load("@cgrindel_bazel_starlib//bzltidy:defs.bzl", "tidy") 4 | 5 | # This is a runnable target that is used to configure direnv to make the listed 6 | # tools available at the command-line. 7 | bazel_env( 8 | name = "bazel_env", 9 | tools = { 10 | "rails": "@people_tracker_bundle//bin:rails", 11 | }, 12 | ) 13 | 14 | tidy( 15 | name = "all_bazel_env", 16 | targets = [ 17 | # Use fully-qualified labels here. There may be a bug in tidy that does 18 | # not resolve relative labels properly. 19 | "//:bazel_env", 20 | "//people_tracker:bazel_env", 21 | ], 22 | ) 23 | 24 | build_test( 25 | name = "bazel_env_build_test", 26 | targets = [ 27 | ":bazel_env", 28 | ], 29 | ) 30 | -------------------------------------------------------------------------------- /ruby/tests/utils_tests.bzl: -------------------------------------------------------------------------------- 1 | """Unit tests for utils.""" 2 | 3 | load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest") 4 | load( 5 | "//ruby/private:utils.bzl", 6 | _normalize_bzlmod_repository_name = "normalize_bzlmod_repository_name", 7 | ) 8 | 9 | def _normalize_bzlmod_repository_name_test_impl(ctx): 10 | env = unittest.begin(ctx) 11 | asserts.equals(env, _normalize_bzlmod_repository_name("bundle"), "bundle") 12 | asserts.equals(env, _normalize_bzlmod_repository_name("rules_ruby+override+ruby+bundle"), "bundle") 13 | asserts.equals(env, _normalize_bzlmod_repository_name("rules_ruby~override~ruby~bundle"), "bundle") 14 | return unittest.end(env) 15 | 16 | normalize_bzlmod_repository_name_test = unittest.make(_normalize_bzlmod_repository_name_test_impl) 17 | 18 | def utils_test_suite(): 19 | unittest.suite("utils_tests", normalize_bzlmod_repository_name_test) 20 | -------------------------------------------------------------------------------- /examples/rails/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_env.bzl", "bazel_env") 2 | load("@bazel_skylib//rules:build_test.bzl", "build_test") 3 | 4 | # MARK: - bazel_env 5 | 6 | _RUBY_BINARIES = [ 7 | "bundle", 8 | "bundler", 9 | "erb", 10 | "gem", 11 | "irb", 12 | "racc", 13 | "rake", 14 | "rbs", 15 | "rdbg", 16 | "rdoc", 17 | "ri", 18 | "ruby", 19 | ] 20 | 21 | # This is a runnable target that is used to configure direnv to make the listed 22 | # tools available at the command-line. 23 | bazel_env( 24 | name = "bazel_env", 25 | tools = { 26 | "buildifier": "@buildifier_prebuilt//:buildifier", 27 | "rails": "@root_bundle//bin:rails", 28 | } | { 29 | rbin: "@ruby//:{}".format(rbin) 30 | for rbin in _RUBY_BINARIES 31 | }, 32 | visibility = ["//:__subpackages__"], 33 | ) 34 | 35 | build_test( 36 | name = "bazel_env_build_test", 37 | targets = [ 38 | ":bazel_env", 39 | ], 40 | ) 41 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/pwa/service-worker.js: -------------------------------------------------------------------------------- 1 | // Add a service worker for processing Web Push notifications: 2 | // 3 | // self.addEventListener("push", async (event) => { 4 | // const { title, options } = await event.data.json() 5 | // event.waitUntil(self.registration.showNotification(title, options)) 6 | // }) 7 | // 8 | // self.addEventListener("notificationclick", function(event) { 9 | // event.notification.close() 10 | // event.waitUntil( 11 | // clients.matchAll({ type: "window" }).then((clientList) => { 12 | // for (let i = 0; i < clientList.length; i++) { 13 | // let client = clientList[i] 14 | // let clientPath = (new URL(client.url)).pathname 15 | // 16 | // if (clientPath == event.notification.data.path && "focus" in client) { 17 | // return client.focus() 18 | // } 19 | // } 20 | // 21 | // if (clients.openWindow) { 22 | // return clients.openWindow(event.notification.data.path) 23 | // } 24 | // }) 25 | // ) 26 | // }) 27 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/people/show.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, "Showing person" %> 2 | 3 |
4 | <% if notice.present? %> 5 |

<%= notice %>

6 | <% end %> 7 | 8 |

Showing person

9 | 10 | <%= render @person %> 11 | 12 | <%= link_to "Edit this person", edit_person_path(@person), class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> 13 | <%= link_to "Back to people", people_path, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> 14 | <%= button_to "Destroy this person", @person, method: :delete, form_class: "sm:inline-block mt-2 sm:mt-0 sm:ml-2", class: "w-full rounded-md px-3.5 py-2.5 text-white bg-red-600 hover:bg-red-500 font-medium cursor-pointer", data: { turbo_confirm: "Are you sure?" } %> 15 |
16 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/db/schema.rb: -------------------------------------------------------------------------------- 1 | # This file is auto-generated from the current state of the database. Instead 2 | # of editing this file, please use the migrations feature of Active Record to 3 | # incrementally modify your database, and then regenerate this schema definition. 4 | # 5 | # This file is the source Rails uses to define your schema when running `bin/rails 6 | # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to 7 | # be faster and is potentially less error prone than running all of your 8 | # migrations from scratch. Old migrations may fail to apply correctly if those 9 | # migrations use external dependencies or application code. 10 | # 11 | # It's strongly recommended that you check this file into your version control system. 12 | 13 | ActiveRecord::Schema[8.0].define(version: 2025_09_05_170124) do 14 | create_table "people", force: :cascade do |t| 15 | t.string "first_name" 16 | t.string "last_name" 17 | t.datetime "created_at", null: false 18 | t.datetime "updated_at", null: false 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /examples/gem/lib/gem/BUILD: -------------------------------------------------------------------------------- 1 | load("@bazel_skylib//rules:run_binary.bzl", "run_binary") 2 | load("@rules_ruby//ruby:defs.bzl", "rb_binary", "rb_library") 3 | 4 | package(default_visibility = ["//:__subpackages__"]) 5 | 6 | rb_library( 7 | name = "add", 8 | srcs = ["add.rb"], 9 | ) 10 | 11 | rb_library( 12 | name = "subtract", 13 | srcs = ["subtract.rb"], 14 | ) 15 | 16 | rb_library( 17 | name = "version", 18 | srcs = ["version.rb"], 19 | ) 20 | 21 | rb_binary( 22 | name = "add-numbers", 23 | args = ["1"], # pass 1 argument here and 1 extra in CI 24 | main = "add.rb", 25 | deps = [ 26 | ":add", 27 | "@bundle", 28 | ], 29 | ) 30 | 31 | rb_binary( 32 | name = "print-version", 33 | args = ["lib/gem/version.rb"], 34 | deps = [":version"], 35 | ) 36 | 37 | run_binary( 38 | name = "perform-addition", 39 | srcs = [":add"], 40 | outs = ["addition-result"], 41 | args = [ 42 | "1", 43 | "2", 44 | "$(location :addition-result)", 45 | ], 46 | tool = ":add-numbers", 47 | ) 48 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization and 2 | # are automatically loaded by Rails. If you want to use locales other than 3 | # English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t "hello" 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t("hello") %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more about the API, please read the Rails Internationalization guide 20 | # at https://guides.rubyonrails.org/i18n.html. 21 | # 22 | # Be aware that YAML interprets the following case-insensitive strings as 23 | # booleans: `true`, `false`, `on`, `off`, `yes`, `no`. Therefore, these strings 24 | # must be quoted to be interpreted as strings. For example: 25 | # 26 | # en: 27 | # "yes": yup 28 | # enabled: "ON" 29 | 30 | en: 31 | hello: "Hello world" 32 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/initializers/bazel_ruby_patches.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Bazel Ruby patches for Rails tests 4 | # 5 | # These patches fix issues with require_relative and __dir__ in Bazel's 6 | # sandboxed environment. Without these patches, require_relative bypasses 7 | # the sandbox by reading files directly from the source tree instead of 8 | # the runfiles tree. 9 | # 10 | # See: https://github.com/bazel-contrib/rules_ruby/issues/225 11 | 12 | module Kernel 13 | unless respond_to?(:bazel_ruby_patches_applied?) 14 | def bazel_ruby_patches_applied? 15 | true 16 | end 17 | 18 | alias_method :brp_original_require_relative, :require_relative 19 | alias_method :brp_original___dir__, :__dir__ 20 | 21 | def require_relative(path) 22 | base = caller_locations(1..1).first&.path 23 | base = "" if base.nil? 24 | base_directory = File.dirname(base) 25 | require File.expand_path(path, base_directory) 26 | end 27 | 28 | def __dir__ 29 | File.dirname(caller_locations(1..1).first&.path) 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/.dockerignore: -------------------------------------------------------------------------------- 1 | # See https://docs.docker.com/engine/reference/builder/#dockerignore-file for more about ignoring files. 2 | 3 | # Ignore git directory. 4 | /.git/ 5 | /.gitignore 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore all environment files. 11 | /.env* 12 | 13 | # Ignore all default key files. 14 | /config/master.key 15 | /config/credentials/*.key 16 | 17 | # Ignore all logfiles and tempfiles. 18 | /log/* 19 | /tmp/* 20 | !/log/.keep 21 | !/tmp/.keep 22 | 23 | # Ignore pidfiles, but keep the directory. 24 | /tmp/pids/* 25 | !/tmp/pids/.keep 26 | 27 | # Ignore storage (uploaded files in development and any SQLite databases). 28 | /storage/* 29 | !/storage/.keep 30 | /tmp/storage/* 31 | !/tmp/storage/.keep 32 | 33 | # Ignore assets. 34 | /node_modules/ 35 | /app/assets/builds/* 36 | !/app/assets/builds/.keep 37 | /public/assets 38 | 39 | # Ignore CI service files. 40 | /.github 41 | 42 | # Ignore Kamal files. 43 | /config/deploy*.yml 44 | /.kamal 45 | 46 | # Ignore development files 47 | /.devcontainer 48 | 49 | # Ignore Docker-related files 50 | /.dockerignore 51 | /Dockerfile* 52 | -------------------------------------------------------------------------------- /ruby/private/toolchain/repository_proxy.bzl: -------------------------------------------------------------------------------- 1 | "Repository rule for proxying registering Ruby interpreters" 2 | 3 | def _rb_toolchain_repository_proxy_impl(repository_ctx): 4 | repository_ctx.template( 5 | "BUILD", 6 | repository_ctx.attr._build_tpl, 7 | substitutions = { 8 | "{name}": repository_ctx.attr.name, 9 | "{toolchain}": repository_ctx.attr.toolchain, 10 | "{toolchain_type}": repository_ctx.attr.toolchain_type, 11 | }, 12 | executable = False, 13 | ) 14 | 15 | rb_toolchain_repository_proxy = repository_rule( 16 | implementation = _rb_toolchain_repository_proxy_impl, 17 | attrs = { 18 | "toolchain": attr.string(mandatory = True), 19 | "toolchain_type": attr.string(mandatory = True), 20 | "_build_tpl": attr.label( 21 | allow_single_file = True, 22 | default = "@rules_ruby//:ruby/private/toolchain/repository_proxy/BUILD.tpl", 23 | ), 24 | }, 25 | doc = """ 26 | A proxy repository that contains the toolchain declaration; this indirection 27 | allows the Ruby toolchain to be downloaded lazily. 28 | """, 29 | ) 30 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= content_for(:title) || "People Tracker" %> 5 | 6 | 7 | 8 | <%= csrf_meta_tags %> 9 | <%= csp_meta_tag %> 10 | 11 | <%= yield :head %> 12 | 13 | <%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %> 14 | <%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %> 15 | 16 | 17 | 18 | 19 | 20 | <%# Includes all stylesheet files in app/assets/stylesheets %> 21 | <%= stylesheet_link_tag :app, "data-turbo-track": "reload" %> 22 | <%= javascript_importmap_tags %> 23 | 24 | 25 | 26 |
27 | <%= yield %> 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "fileutils" 3 | 4 | APP_ROOT = File.expand_path("..", __dir__) 5 | 6 | def system!(*args) 7 | system(*args, exception: true) 8 | end 9 | 10 | FileUtils.chdir APP_ROOT do 11 | # This script is a way to set up or update your development environment automatically. 12 | # This script is idempotent, so that you can run it at any time and get an expectable outcome. 13 | # Add necessary setup steps to this file. 14 | 15 | puts "== Installing dependencies ==" 16 | system("bundle check") || system!("bundle install") 17 | 18 | # puts "\n== Copying sample files ==" 19 | # unless File.exist?("config/database.yml") 20 | # FileUtils.cp "config/database.yml.sample", "config/database.yml" 21 | # end 22 | 23 | puts "\n== Preparing database ==" 24 | system! "bin/rails db:prepare" 25 | 26 | puts "\n== Removing old logs and tempfiles ==" 27 | system! "bin/rails log:clear tmp:clear" 28 | 29 | unless ARGV.include?("--skip-server") 30 | puts "\n== Starting development server ==" 31 | STDOUT.flush # flush the output before exec(2) so that it displays 32 | exec "bin/dev" 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide content security policy. 4 | # See the Securing Rails Applications Guide for more information: 5 | # https://guides.rubyonrails.org/security.html#content-security-policy-header 6 | 7 | # Rails.application.configure do 8 | # config.content_security_policy do |policy| 9 | # policy.default_src :self, :https 10 | # policy.font_src :self, :https, :data 11 | # policy.img_src :self, :https, :data 12 | # policy.object_src :none 13 | # policy.script_src :self, :https 14 | # policy.style_src :self, :https 15 | # # Specify URI for violation reports 16 | # # policy.report_uri "/csp-violation-report-endpoint" 17 | # end 18 | # 19 | # # Generate session nonces for permitted importmap, inline scripts, and inline styles. 20 | # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } 21 | # config.content_security_policy_nonce_directives = %w(script-src style-src) 22 | # 23 | # # Report violations without enforcing the policy. 24 | # # config.content_security_policy_report_only = true 25 | # end 26 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/system/people_test.rb: -------------------------------------------------------------------------------- 1 | require "application_system_test_case" 2 | 3 | class PeopleTest < ApplicationSystemTestCase 4 | setup do 5 | @john_doe = people(:john_doe) 6 | end 7 | 8 | test "visiting the index" do 9 | visit people_url 10 | assert_selector "h1", text: "People" 11 | end 12 | 13 | test "should create person" do 14 | visit people_url 15 | click_on "New person" 16 | 17 | fill_in "First name", with: "Bob" 18 | fill_in "Last name", with: "Smith" 19 | click_on "Create Person" 20 | 21 | assert_text "Person was successfully created" 22 | click_on "Back" 23 | end 24 | 25 | test "should update Person" do 26 | visit person_url(@john_doe) 27 | click_on "Edit this person", match: :first 28 | 29 | fill_in "First name", with: @john_doe.first_name + "Suffix" 30 | fill_in "Last name", with: @john_doe.last_name + "Another" 31 | click_on "Update Person" 32 | 33 | assert_text "Person was successfully updated" 34 | click_on "Back" 35 | end 36 | 37 | test "should destroy Person" do 38 | visit person_url(@john_doe) 39 | accept_confirm { click_on "Destroy this person", match: :first } 40 | 41 | assert_text "Person was successfully destroyed" 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket-<%= Rails.env %> 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket-<%= Rails.env %> 23 | 24 | # Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name-<%= Rails.env %> 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /examples/jekyll/_posts/2024-02-03-welcome-to-jekyll.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "Welcome to Jekyll!" 4 | date: 2024-02-03 12:49:25 -0800 5 | categories: jekyll update 6 | --- 7 | You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated. 8 | 9 | To add new posts, simply add a file in the `_posts` directory that follows the convention `YYYY-MM-DD-name-of-post.ext` and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works. 10 | 11 | Jekyll also offers powerful support for code snippets: 12 | 13 | {% highlight ruby %} 14 | def print_hi(name) 15 | puts "Hi, #{name}" 16 | end 17 | print_hi('Tom') 18 | #=> prints 'Hi, Tom' to STDOUT. 19 | {% endhighlight %} 20 | 21 | Check out the [Jekyll docs][jekyll-docs] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekyll’s GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekyll Talk][jekyll-talk]. 22 | 23 | [jekyll-docs]: https://jekyllrb.com/docs/home 24 | [jekyll-gh]: https://github.com/jekyll/jekyll 25 | [jekyll-talk]: https://talk.jekyllrb.com/ 26 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite. Versions 3.8.0 and up are supported. 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem "sqlite3" 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 10 | timeout: 5000 11 | 12 | development: 13 | !!merge <<: *default 14 | database: storage/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | !!merge <<: *default 21 | database: ":memory:" 22 | 23 | # Store production database in the storage/ directory, which by default 24 | # is mounted as a persistent Docker volume in config/deploy.yml. 25 | production: 26 | primary: 27 | !!merge <<: *default 28 | database: storage/production.sqlite3 29 | cache: 30 | !!merge <<: *default 31 | database: storage/production_cache.sqlite3 32 | migrations_paths: db/cache_migrate 33 | queue: 34 | !!merge <<: *default 35 | database: storage/production_queue.sqlite3 36 | migrations_paths: db/queue_migrate 37 | cable: 38 | !!merge <<: *default 39 | database: storage/production_cable.sqlite3 40 | migrations_paths: db/cable_migrate 41 | -------------------------------------------------------------------------------- /ruby/private/binary/binary.cmd.tpl: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enableextensions enabledelayedexpansion 3 | 4 | set RUNFILES_MANIFEST_ONLY=1 5 | {rlocation_function} 6 | 7 | :: Find location of Ruby in runfiles. 8 | call :rlocation {ruby} ruby 9 | for %%a in ("!ruby!\..") do set PATH=%%~fa;%PATH% 10 | 11 | :: Find location of JAVA_HOME in runfiles. 12 | if "{java_bin}" neq "" ( 13 | call :rlocation {java_bin} java_bin 14 | for %%a in ("!java_bin!\..\..") do set JAVA_HOME=%%~fa 15 | ) 16 | 17 | :: Bundler expects the %HOME% directory to be writable and produces misleading 18 | :: warnings if it isn't. This isn't the case in every situation (e.g. remote 19 | :: execution) and Bazel recommends using %TEST_TMPDIR% when it's available: 20 | :: https://bazel.build/reference/test-encyclopedia#initial-conditions 21 | :: 22 | :: We set %HOME% prior to setting environment variables from the target itself 23 | :: so that users can override this behavior if they desire. 24 | if defined TEST_TMPDIR ( 25 | set "HOME=%TEST_TMPDIR%" 26 | ) 27 | 28 | :: Set environment variables. 29 | {env} 30 | 31 | :: Find location of Bundle path in runfiles. 32 | if "{bundler_command}" neq "" ( 33 | call :rlocation "!BUNDLE_GEMFILE!" BUNDLE_GEMFILE 34 | call :rlocation "!BUNDLE_PATH!" BUNDLE_PATH 35 | ) 36 | 37 | {bundler_command} {ruby_binary_name} {binary} {args} %* 38 | 39 | :: vim: ft=dosbatch 40 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/controllers/people_controller_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class PeopleControllerTest < ActionDispatch::IntegrationTest 4 | setup do 5 | @person = people(:john_doe) 6 | end 7 | 8 | test "should get index" do 9 | get people_url 10 | assert_response :success 11 | end 12 | 13 | test "should get new" do 14 | get new_person_url 15 | assert_response :success 16 | end 17 | 18 | test "should create person" do 19 | assert_difference("Person.count") do 20 | post people_url, params: { 21 | person: {first_name: @person.first_name, last_name: @person.last_name} 22 | } 23 | end 24 | 25 | assert_redirected_to person_url(Person.last) 26 | end 27 | 28 | test "should show person" do 29 | get person_url(@person) 30 | assert_response :success 31 | end 32 | 33 | test "should get edit" do 34 | get edit_person_url(@person) 35 | assert_response :success 36 | end 37 | 38 | test "should update person" do 39 | patch person_url(@person), params: { 40 | person: {first_name: @person.first_name, last_name: @person.last_name} 41 | } 42 | assert_redirected_to person_url(@person) 43 | end 44 | 45 | test "should destroy person" do 46 | assert_difference("Person.count", -1) do 47 | delete person_url(@person) 48 | end 49 | 50 | assert_redirected_to people_url 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /ruby/private/gem_build/gem_builder.rb.tpl: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'fileutils' 4 | require 'json' 5 | require 'rubygems/package' 6 | require 'tmpdir' 7 | 8 | gemspec_path = '{gemspec}' 9 | packaged_gem_path = File.expand_path('{gem_filename}', '{bazel_out_dir}') 10 | inputs = JSON.parse('{inputs_manifest}') 11 | 12 | # We need to check if there are inputs which are directories. 13 | # For such cases, we are going to check the contents of the directories 14 | # and add the file to the inputs manifest. 15 | inputs.dup.each do |src, dst| 16 | next unless File.directory?(src) 17 | 18 | inputs.delete(src) 19 | Dir.chdir(src) do 20 | Dir['**/*'].each do |file| 21 | inputs[File.join(src, file)] = File.join(dst, file) 22 | end 23 | end 24 | end 25 | 26 | Dir.mktmpdir do |tmpdir| 27 | inputs.each do |src, dst| 28 | dst = File.join(tmpdir, dst) 29 | FileUtils.mkdir_p(File.dirname(dst)) 30 | FileUtils.cp(src, dst) 31 | end 32 | 33 | Dir.chdir(tmpdir) do 34 | gemspec_dir = File.dirname(gemspec_path) 35 | gemspec_file = File.basename(gemspec_path) 36 | gemspec_code = File.read(gemspec_path) 37 | 38 | Dir.chdir(gemspec_dir) do 39 | spec = binding.eval(gemspec_code, gemspec_file, __LINE__) # rubocop:disable Security/Eval 40 | file = Gem::Package.build(spec) 41 | FileUtils.mv(file, packaged_gem_path) 42 | end 43 | end 44 | end 45 | 46 | # vim: ft=ruby 47 | -------------------------------------------------------------------------------- /ruby/toolchain.bzl: -------------------------------------------------------------------------------- 1 | "Define a Bazel toolchain for a Ruby interpreter" 2 | 3 | def _rb_toolchain_impl(ctx): 4 | return platform_common.ToolchainInfo( 5 | ruby = ctx.executable.ruby, 6 | bundle = ctx.executable.bundle, 7 | gem = ctx.executable.gem, 8 | version = ctx.attr.version, 9 | env = ctx.attr.env, 10 | files = ctx.files.files, 11 | ) 12 | 13 | rb_toolchain = rule( 14 | implementation = _rb_toolchain_impl, 15 | attrs = { 16 | "ruby": attr.label( 17 | doc = "`ruby` binary to execute", 18 | allow_files = True, 19 | executable = True, 20 | cfg = "exec", 21 | ), 22 | "bundle": attr.label( 23 | doc = "`bundle` to execute", 24 | allow_files = True, 25 | executable = True, 26 | cfg = "exec", 27 | ), 28 | "gem": attr.label( 29 | doc = "`gem` to execute", 30 | allow_files = True, 31 | executable = True, 32 | cfg = "exec", 33 | ), 34 | "version": attr.string( 35 | doc = "Ruby version", 36 | ), 37 | "env": attr.string_dict( 38 | doc = "Environment variables required by an interpreter", 39 | ), 40 | "files": attr.label_list( 41 | allow_files = True, 42 | doc = "All files necessary for toolchain", 43 | ), 44 | }, 45 | ) 46 | -------------------------------------------------------------------------------- /MODULE.bazel: -------------------------------------------------------------------------------- 1 | "Define the Bazel module published to the Bazel Central Registry" 2 | 3 | module( 4 | name = "rules_ruby", 5 | # NB: this version will be replaced after a release by the Publish to BCR app 6 | version = "0.0.0", 7 | compatibility_level = 1, 8 | ) 9 | 10 | # Lower-bound dependency versions. 11 | # These should NOT be increased unless needed, as bumping our lower-bound may change 12 | # the versions resolved in users repositories. 13 | bazel_dep(name = "bazel_features", version = "1.9.0") 14 | bazel_dep(name = "bazel_skylib", version = "1.3.0") 15 | bazel_dep(name = "platforms", version = "0.0.5") 16 | bazel_dep(name = "rules_cc", version = "0.0.9") 17 | bazel_dep(name = "rules_java", version = "7.2.0") 18 | 19 | # Ruleset development dependencies. 20 | bazel_dep(name = "aspect_bazel_lib", version = "2.22.0", dev_dependency = True) 21 | bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "1.8.2", dev_dependency = True) 22 | bazel_dep(name = "buildifier_prebuilt", version = "8.2.1.1", dev_dependency = True) 23 | bazel_dep(name = "gazelle", version = "0.47.0", dev_dependency = True) 24 | bazel_dep(name = "rules_go", version = "0.59.0", dev_dependency = True) 25 | bazel_dep(name = "stardoc", version = "0.8.0", dev_dependency = True) 26 | 27 | go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk", dev_dependency = True) 28 | go_sdk.download(version = "1.23.1") 29 | 30 | # TODO: should we register any toolchain by default? 31 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | hello_world (0.0.0) 5 | irb 6 | rspec (~> 3.0) 7 | 8 | GEM 9 | remote: https://rubygems.org/ 10 | specs: 11 | date (3.4.1-java) 12 | diff-lcs (1.6.2) 13 | erb (5.0.2-java) 14 | io-console (0.8.1-java) 15 | irb (1.15.2) 16 | pp (>= 0.6.0) 17 | rdoc (>= 4.0.0) 18 | reline (>= 0.4.2) 19 | jar-dependencies (0.5.5) 20 | pp (0.6.2) 21 | prettyprint 22 | prettyprint (0.2.0) 23 | psych (5.2.6-java) 24 | date 25 | jar-dependencies (>= 0.1.7) 26 | rdoc (6.14.2) 27 | erb 28 | psych (>= 4.0.0) 29 | reline (0.6.2) 30 | io-console (~> 0.5) 31 | rspec (3.13.1) 32 | rspec-core (~> 3.13.0) 33 | rspec-expectations (~> 3.13.0) 34 | rspec-mocks (~> 3.13.0) 35 | rspec-core (3.13.5) 36 | rspec-support (~> 3.13.0) 37 | rspec-expectations (3.13.5) 38 | diff-lcs (>= 1.2.0, < 2.0) 39 | rspec-support (~> 3.13.0) 40 | rspec-mocks (3.13.5) 41 | diff-lcs (>= 1.2.0, < 2.0) 42 | rspec-support (~> 3.13.0) 43 | rspec-support (3.13.4) 44 | 45 | PLATFORMS 46 | arm64-darwin-23 47 | arm64-darwin-24 48 | java 49 | ruby 50 | universal-java-1.8 51 | universal-java-11 52 | universal-java-17 53 | universal-java-18 54 | universal-java-21 55 | x64-mingw32 56 | 57 | DEPENDENCIES 58 | hello_world! 59 | 60 | BUNDLED WITH 61 | 2.3.3 62 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/people/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_with(model: person, class: "contents") do |form| %> 2 | <% if person.errors.any? %> 3 |
4 |

<%= pluralize(person.errors.count, "error") %> prohibited this person from being saved:

5 | 6 |
    7 | <% person.errors.each do |error| %> 8 |
  • <%= error.full_message %>
  • 9 | <% end %> 10 |
11 |
12 | <% end %> 13 | 14 |
15 | <%= form.label :first_name %> 16 | <%= form.text_field :first_name, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": person.errors[:first_name].none?, "border-red-400 focus:outline-red-600": person.errors[:first_name].any?}] %> 17 |
18 | 19 |
20 | <%= form.label :last_name %> 21 | <%= form.text_field :last_name, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": person.errors[:last_name].none?, "border-red-400 focus:outline-red-600": person.errors[:last_name].any?}] %> 22 |
23 | 24 |
25 | <%= form.submit class: "w-full sm:w-auto rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %> 26 |
27 | <% end %> 28 | -------------------------------------------------------------------------------- /ruby/BUILD: -------------------------------------------------------------------------------- 1 | load("@bazel_skylib//:bzl_library.bzl", "bzl_library") 2 | 3 | package(default_visibility = ["//visibility:public"]) 4 | 5 | exports_files(glob(["*.bzl"])) 6 | 7 | toolchain_type( 8 | name = "toolchain_type", 9 | visibility = ["//visibility:public"], 10 | ) 11 | 12 | bzl_library( 13 | name = "defs", 14 | srcs = ["defs.bzl"], 15 | deps = [ 16 | "//ruby/private:binary", 17 | "//ruby/private:bundle_install", 18 | "//ruby/private:gem", 19 | "//ruby/private:gem_build", 20 | "//ruby/private:gem_install", 21 | "//ruby/private:gem_push", 22 | "//ruby/private:library", 23 | "//ruby/private:test", 24 | ], 25 | ) 26 | 27 | starlark_doc_extract( 28 | name = "defs.doc_extract", 29 | src = "defs.bzl", 30 | deps = [":defs"], 31 | ) 32 | 33 | bzl_library( 34 | name = "deps", 35 | srcs = ["deps.bzl"], 36 | deps = [ 37 | "//ruby/private:bundle", 38 | "//ruby/private:bundle_fetch", 39 | "//ruby/private:toolchain", 40 | ], 41 | ) 42 | 43 | starlark_doc_extract( 44 | name = "deps.doc_extract", 45 | src = "deps.bzl", 46 | deps = [":deps"], 47 | ) 48 | 49 | bzl_library( 50 | name = "extensions", 51 | srcs = ["extensions.bzl"], 52 | deps = [ 53 | ":deps", 54 | "//ruby/private:download", 55 | "//ruby/private:toolchain", 56 | ], 57 | ) 58 | 59 | bzl_library( 60 | name = "toolchain", 61 | srcs = ["toolchain.bzl"], 62 | ) 63 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/test/models/person_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class PersonTest < ActiveSupport::TestCase 4 | test "should be valid with valid attributes" do 5 | person = Person.new(first_name: "John", last_name: "Doe") 6 | assert person.valid? 7 | end 8 | 9 | test "full_name returns concatenated first and last name" do 10 | person = people(:john_doe) 11 | assert_equal "John Doe", person.full_name 12 | end 13 | 14 | test "full_name handles nil first_name" do 15 | person = Person.new(first_name: nil, last_name: "Doe") 16 | assert_equal "Doe", person.full_name 17 | end 18 | 19 | test "full_name handles nil last_name" do 20 | person = Person.new(first_name: "John", last_name: nil) 21 | assert_equal "John", person.full_name 22 | end 23 | 24 | test "full_name handles both names being nil" do 25 | person = Person.new(first_name: nil, last_name: nil) 26 | assert_equal "", person.full_name 27 | end 28 | 29 | test "full_name handles empty strings" do 30 | person = Person.new(first_name: "", last_name: "") 31 | assert_equal "", person.full_name 32 | end 33 | 34 | test "should have timestamps" do 35 | person = people(:john_doe) 36 | assert_not_nil person.created_at 37 | assert_not_nil person.updated_at 38 | end 39 | 40 | test "can create person with minimal attributes" do 41 | person = Person.create(first_name: "Test", last_name: "User") 42 | assert_not_nil person.id 43 | assert_equal "Test", person.first_name 44 | assert_equal "User", person.last_name 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative "boot" 2 | 3 | require "rails/all" 4 | 5 | # Prevent pending migration checks from happening when running tests. We use 6 | # in-memory SQLite databases for our tests. The default pending migration check 7 | # fails if you run `rails test`. 8 | if ENV["RAILS_ENV"] == "test" 9 | module ActiveRecord 10 | class Migration 11 | class << self 12 | def check_pending_migrations 13 | # Do nothing. 14 | end 15 | end 16 | end 17 | end 18 | end 19 | 20 | # Require the gems listed in Gemfile, including any gems 21 | # you've limited to :test, :development, or :production. 22 | Bundler.require(*Rails.groups) 23 | 24 | module PeopleTracker 25 | class Application < Rails::Application 26 | # Initialize configuration defaults for originally generated Rails version. 27 | config.load_defaults 8.0 28 | 29 | # Please, add to the `ignore` list any other `lib` subdirectories that do 30 | # not contain `.rb` files, or that should not be reloaded or eager loaded. 31 | # Common ones are `templates`, `generators`, or `middleware`, for example. 32 | config.autoload_lib(ignore: %w[assets tasks]) 33 | 34 | # Configuration for the application, engines, and railties goes here. 35 | # 36 | # These settings can be overridden in specific environments using the files 37 | # in config/environments, which are processed later. 38 | # 39 | # config.time_zone = "Central Time (US & Canada)" 40 | # config.eager_load_paths << Rails.root.join("extras") 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /examples/jekyll/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | # Hello! This is where you manage which Jekyll version is used to run. 4 | # When you want to use a different version, change it below, save the 5 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so: 6 | # 7 | # bundle exec jekyll serve 8 | # 9 | # This will help ensure the proper Jekyll version is running. 10 | # Happy Jekylling! 11 | gem "jekyll", "~> 3.9.3" 12 | 13 | # This is the default theme for new Jekyll sites. You may change this to anything you like. 14 | gem "minima", "~> 2.0" 15 | 16 | # If you want to use GitHub Pages, remove the "gem "jekyll"" above and 17 | # uncomment the line below. To upgrade, run `bundle update github-pages`. 18 | # gem "github-pages", group: :jekyll_plugins 19 | 20 | # If you have any plugins, put them here! 21 | group :jekyll_plugins do 22 | gem "jekyll-feed", "~> 0.6" 23 | end 24 | 25 | # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem 26 | # and associated library. 27 | platforms :mingw, :x64_mingw, :mswin, :jruby do 28 | gem "tzinfo", ">= 1", "< 3" 29 | gem "tzinfo-data" 30 | end 31 | 32 | # Performance-booster for watching directories on Windows 33 | gem "wdm", "~> 0.1.0", :install_if => Gem.win_platform? 34 | 35 | # kramdown v2 ships without the gfm parser by default. If you're using 36 | # kramdown v1, comment out this line. 37 | gem "kramdown-parser-gfm" 38 | 39 | # Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem 40 | # do not have a Java counterpart. 41 | gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby] 42 | 43 | # `webrick` is a missing dependency needed to run `jekyll serve` 44 | gem "webrick", "~> 1.8" 45 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/spec/speaker_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "spec_helper" 4 | require_relative "../lib/hello_world" 5 | 6 | RSpec.describe HelloWorld::Speaker do 7 | describe "#name" do 8 | context "when no name is provided" do 9 | it "defaults to 'world'" do 10 | speaker = HelloWorld::Speaker.new 11 | expect(speaker.name).to eq("world") 12 | end 13 | end 14 | 15 | context "when a name is provided" do 16 | it "returns the provided name" do 17 | name = "Jimmy" 18 | speaker = HelloWorld::Speaker.new(name) 19 | expect(speaker.name).to eq(name) 20 | end 21 | end 22 | end 23 | 24 | describe "#message" do 25 | context "when using default name" do 26 | it "returns a greeting with the default name" do 27 | speaker = HelloWorld::Speaker.new 28 | expect(speaker.message).to eq("Hello, world") 29 | end 30 | end 31 | 32 | context "when using custom name" do 33 | it "returns a greeting with the custom name" do 34 | speaker = HelloWorld::Speaker.new("Alice") 35 | expect(speaker.message).to eq("Hello, Alice") 36 | end 37 | end 38 | end 39 | 40 | describe "#hi" do 41 | context "when using default name" do 42 | it "outputs the greeting message to stdout" do 43 | speaker = HelloWorld::Speaker.new 44 | expect { speaker.hi }.to output("Hello, world\n").to_stdout 45 | end 46 | end 47 | 48 | context "when using custom name" do 49 | it "outputs the greeting message with custom name to stdout" do 50 | speaker = HelloWorld::Speaker.new("Bob") 51 | expect { speaker.hi }.to output("Hello, Bob\n").to_stdout 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /examples/gem/.bazelrc: -------------------------------------------------------------------------------- 1 | # Enable runfiles on all platforms. Runfiles are on by default on Linux and MacOS but off on 2 | # Windows. 3 | # 4 | # If you are developing on Windows, you must either run bazel with administrator privileges or 5 | # enable developer mode. If you do not you may hit this error on Windows: 6 | # 7 | # Bazel needs to create symlinks to build the runfiles tree. 8 | # Creating symlinks on Windows requires one of the following: 9 | # 1. Bazel is run with administrator privileges. 10 | # 2. The system version is Windows 10 Creators Update (1703) or later 11 | # and developer mode is enabled. 12 | # 13 | # Docs: https://bazel.build/reference/command-line-reference#flag--windows_enable_symlinks 14 | # Docs: https://bazel.build/reference/command-line-reference#flag--enable_runfiles 15 | startup --windows_enable_symlinks 16 | build --enable_runfiles 17 | 18 | # Allow to run Bazel without pre-installed JDK. 19 | # Docs: https://bazel.build/reference/command-line-reference#flag--java_runtime_version 20 | build --java_runtime_version=remotejdk_21 --tool_java_runtime_version=remotejdk_21 21 | 22 | # Not ready for the MODULE.lock file yet, as of Bazel 7.0.0 there are still some stability issues. 23 | common --lockfile_mode=off 24 | 25 | # Ignore timeout different between JRuby and MRI. 26 | test --test_verbose_timeout_warnings=false 27 | 28 | # JRuby needs $HOME for File#expand_path to work: https://github.com/jruby/jruby/issues/5661. 29 | # TruffleRuby needs $HOME too: https://github.com/oracle/truffleruby/issues/2784. 30 | build --action_env=HOME 31 | test --test_env=HOME 32 | 33 | # Allows to run tests with rdbg bundled with Ruby 3.1: 34 | # 1. Add breakpoint with `debugger`. 35 | # 2. Run tests: `bazel test --config debug spec:add`. 36 | # 3. Connect to debugger: `bazel-gem/external/ruby/dist/bin/rdbg -A`. 37 | test:debug --run_under="@ruby//:rdbg --nonstop --open --command" 38 | -------------------------------------------------------------------------------- /examples/deep_gem/.bazelrc: -------------------------------------------------------------------------------- 1 | # Enable runfiles on all platforms. Runfiles are on by default on Linux and MacOS but off on 2 | # Windows. 3 | # 4 | # If you are developing on Windows, you must either run bazel with administrator privileges or 5 | # enable developer mode. If you do not you may hit this error on Windows: 6 | # 7 | # Bazel needs to create symlinks to build the runfiles tree. 8 | # Creating symlinks on Windows requires one of the following: 9 | # 1. Bazel is run with administrator privileges. 10 | # 2. The system version is Windows 10 Creators Update (1703) or later 11 | # and developer mode is enabled. 12 | # 13 | # Docs: https://bazel.build/reference/command-line-reference#flag--windows_enable_symlinks 14 | # Docs: https://bazel.build/reference/command-line-reference#flag--enable_runfiles 15 | startup --windows_enable_symlinks 16 | build --enable_runfiles 17 | 18 | # Allow to run Bazel without pre-installed JDK. 19 | # Docs: https://bazel.build/reference/command-line-reference#flag--java_runtime_version 20 | build --java_runtime_version=remotejdk_21 --tool_java_runtime_version=remotejdk_21 21 | 22 | # Not ready for the MODULE.lock file yet, as of Bazel 7.0.0 there are still some stability issues. 23 | common --lockfile_mode=off 24 | 25 | # Ignore timeout different between JRuby and MRI. 26 | test --test_verbose_timeout_warnings=false 27 | 28 | # JRuby needs $HOME for File#expand_path to work: https://github.com/jruby/jruby/issues/5661. 29 | # TruffleRuby needs $HOME too: https://github.com/oracle/truffleruby/issues/2784. 30 | build --action_env=HOME 31 | test --test_env=HOME 32 | 33 | # Allows to run tests with rdbg bundled with Ruby 3.1: 34 | # 1. Add breakpoint with `debugger`. 35 | # 2. Run tests: `bazel test --config debug spec:add`. 36 | # 3. Connect to debugger: `bazel-gem/external/ruby/dist/bin/rdbg -A`. 37 | test:debug --run_under="@ruby//:rdbg --nonstop --open --command" 38 | -------------------------------------------------------------------------------- /examples/deep_gem/hello_world/.bazelrc: -------------------------------------------------------------------------------- 1 | # Enable runfiles on all platforms. Runfiles are on by default on Linux and MacOS but off on 2 | # Windows. 3 | # 4 | # If you are developing on Windows, you must either run bazel with administrator privileges or 5 | # enable developer mode. If you do not you may hit this error on Windows: 6 | # 7 | # Bazel needs to create symlinks to build the runfiles tree. 8 | # Creating symlinks on Windows requires one of the following: 9 | # 1. Bazel is run with administrator privileges. 10 | # 2. The system version is Windows 10 Creators Update (1703) or later 11 | # and developer mode is enabled. 12 | # 13 | # Docs: https://bazel.build/reference/command-line-reference#flag--windows_enable_symlinks 14 | # Docs: https://bazel.build/reference/command-line-reference#flag--enable_runfiles 15 | startup --windows_enable_symlinks 16 | build --enable_runfiles 17 | 18 | # Allow to run Bazel without pre-installed JDK. 19 | # Docs: https://bazel.build/reference/command-line-reference#flag--java_runtime_version 20 | build --java_runtime_version=remotejdk_21 --tool_java_runtime_version=remotejdk_21 21 | 22 | # Not ready for the MODULE.lock file yet, as of Bazel 7.0.0 there are still some stability issues. 23 | common --lockfile_mode=off 24 | 25 | # Ignore timeout different between JRuby and MRI. 26 | test --test_verbose_timeout_warnings=false 27 | 28 | # JRuby needs $HOME for File#expand_path to work: https://github.com/jruby/jruby/issues/5661. 29 | # TruffleRuby needs $HOME too: https://github.com/oracle/truffleruby/issues/2784. 30 | build --action_env=HOME 31 | test --test_env=HOME 32 | 33 | # Allows to run tests with rdbg bundled with Ruby 3.1: 34 | # 1. Add breakpoint with `debugger`. 35 | # 2. Run tests: `bazel test --config debug spec:add`. 36 | # 3. Connect to debugger: `bazel-gem/external/ruby/dist/bin/rdbg -A`. 37 | test:debug --run_under="@ruby//:rdbg --nonstop --open --command" 38 | -------------------------------------------------------------------------------- /examples/jekyll/_config.yml: -------------------------------------------------------------------------------- 1 | # Welcome to Jekyll! 2 | # 3 | # This config file is meant for settings that affect your whole blog, values 4 | # which you are expected to set up once and rarely edit after that. If you find 5 | # yourself editing this file very often, consider using Jekyll's data files 6 | # feature for the data you need to update frequently. 7 | # 8 | # For technical reasons, this file is *NOT* reloaded automatically when you use 9 | # 'bundle exec jekyll serve'. If you change this file, please restart the server process. 10 | 11 | # Site settings 12 | # These are used to personalize your new site. If you look in the HTML files, 13 | # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on. 14 | # You can create any custom variable you would like, and they will be accessible 15 | # in the templates via {{ site.myvariable }}. 16 | title: Your awesome title 17 | email: your-email@example.com 18 | description: >- # this means to ignore newlines until "baseurl:" 19 | Write an awesome description for your new site here. You can edit this 20 | line in _config.yml. It will appear in your document head meta (for 21 | Google search results) and in your feed.xml site description. 22 | baseurl: "" # the subpath of your site, e.g. /blog 23 | url: "" # the base hostname & protocol for your site, e.g. http://example.com 24 | twitter_username: jekyllrb 25 | github_username: jekyll 26 | 27 | # Build settings 28 | markdown: kramdown 29 | theme: minima 30 | plugins: 31 | - jekyll-feed 32 | 33 | # Exclude from processing. 34 | # The following items will not be processed, by default. Create a custom list 35 | # to override the default setting. 36 | exclude: 37 | - Gemfile 38 | - Gemfile.lock 39 | - bazel-out/ 40 | - external/ 41 | - BUILD 42 | - MODULE.bazel 43 | - MODULE.bazel.lock 44 | - README.md 45 | # - node_modules 46 | # - vendor/bundle/ 47 | # - vendor/cache/ 48 | # - vendor/gems/ 49 | # - vendor/ruby/ 50 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/.envrc: -------------------------------------------------------------------------------- 1 | # NOTE: This file was written to work with bash and zsh. It uses features like 2 | # arrays which POSIX does not support. 3 | 4 | source_up .envrc 5 | 6 | module_bazel="$(find_up "MODULE.bazel")" 7 | wksp_root_dir="$(dirname "${module_bazel}")" 8 | 9 | # MARK - bazel_env Tools 10 | 11 | # Add binaries and toolchains defined in //people_tracker:bazel_env. 12 | bazel_env_dir="${wksp_root_dir}/bazel-out/bazel_env-opt/bin/people_tracker/bazel_env/bin" 13 | watch_file "${bazel_env_dir}" 14 | PATH_add "${bazel_env_dir}" 15 | if [ ! -d "${bazel_env_dir}" ]; then 16 | log_error "ERROR[bazel_env.bzl]: Run 'bazel run //people_tracker:all_bazel_env' to" \ 17 | "regenerate ${bazel_env_dir} and its parent envrcs." 18 | fi 19 | 20 | # MARK - Ruby Gems 21 | 22 | # We configure the environment to use the Gemfile in this directory 23 | # (BUNDLE_GEMFILE) and the Gems installed by Bazel (BUNDLE_PATH). 24 | bundle_repo_name="people_tracker_bundle" 25 | 26 | BUNDLE_GEMFILE="$(expand_path Gemfile)" 27 | export BUNDLE_GEMFILE 28 | 29 | # Look for the bundle path, if we see the convenience symlinks at the root of 30 | # the Bazel workspace. We want to avoid running long-running commands (e.g. 31 | # cquery) if the workspace has not been built. This is not a perfect test but 32 | # should be good enough for most situations. 33 | if [[ -L "${wksp_root_dir}/bazel-out" ]]; then 34 | bundle_files=() 35 | while IFS=$'\n' read -r line; do bundle_files+=("$line"); done < <( 36 | bazel cquery "@${bundle_repo_name}" --output files 2>/dev/null 37 | ) 38 | for file in "${bundle_files[@]}"; do 39 | if [[ "${file}" =~ vendor/bundle$ ]]; then 40 | export BUNDLE_PATH="${wksp_root_dir}/${file}" 41 | break 42 | fi 43 | done 44 | fi 45 | if [[ -z "${BUNDLE_PATH:-}" ]] || [[ ! -e "${BUNDLE_PATH}" ]]; then 46 | log_error "ERROR[bazel_env.bzl]: Run 'bazel run //people_tracker:all_bazel_env' to" \ 47 | "install the gems for this Ruby project." 48 | fi 49 | -------------------------------------------------------------------------------- /examples/jekyll/BUILD: -------------------------------------------------------------------------------- 1 | load("@aspect_bazel_lib//lib:run_binary.bzl", "run_binary") 2 | load("@bazel_skylib//rules:write_file.bzl", "write_file") 3 | load("@rules_shell//shell:sh_binary.bzl", "sh_binary") 4 | 5 | package(default_visibility = ["//visibility:public"]) 6 | 7 | filegroup( 8 | name = "sources", 9 | srcs = glob( 10 | [ 11 | "_posts/**/*", 12 | "_layouts/**/*", 13 | ], 14 | allow_empty = True, 15 | ) + [ 16 | "404.html", 17 | "about.md", 18 | "index.md", 19 | ], 20 | ) 21 | 22 | run_binary( 23 | name = "site_build", 24 | srcs = [ 25 | ":_config.yml", 26 | ":sources", 27 | ], 28 | args = [ 29 | "build", 30 | "--destination", 31 | "$(GENDIR)/_site", 32 | "--config", 33 | "$(location :_config.yml)", 34 | ], 35 | env = { 36 | "LC_ALL": "C.UTF-8", 37 | "LANG": "en_US.UTF-8", 38 | "LANGUAGE": "en_US.UTF-8", 39 | }, 40 | execution_requirements = {"no-sandbox": "1"}, 41 | mnemonic = "JekyllBuild", 42 | out_dirs = [ 43 | "_site", 44 | ], 45 | tool = "@bundle//bin:jekyll", 46 | ) 47 | 48 | write_file( 49 | name = "site_serve_file", 50 | out = "site_serve_file.sh", 51 | content = [ 52 | "#!/bin/bash", 53 | # rules_ruby needs RUNFILES_DIR to be set 54 | "export RUNFILES_DIR=$(readlink -f ../)", 55 | "EXEC_ROOT=$(pwd)", 56 | "$EXEC_ROOT/$1 ${@:2}", 57 | ], 58 | ) 59 | 60 | sh_binary( 61 | name = "site_serve", 62 | srcs = [ 63 | ":site_serve_file", 64 | ], 65 | args = [ 66 | "$(location @bundle//bin:jekyll)", 67 | "serve", 68 | "--destination", 69 | "_site", 70 | "--skip-initial-build", 71 | "--config", 72 | "$(location :_config.yml)", 73 | ], 74 | data = [ 75 | ":_config.yml", 76 | ":site_build", 77 | "@bundle//bin:jekyll", 78 | ], 79 | ) 80 | -------------------------------------------------------------------------------- /ruby/private/download/BUILD.tpl: -------------------------------------------------------------------------------- 1 | load("@rules_cc//cc:defs.bzl", "cc_library") 2 | load("@rules_java//java:defs.bzl", "java_import") 3 | load("@rules_ruby//ruby:defs.bzl", "rb_binary") 4 | load("@rules_ruby//ruby:toolchain.bzl", "rb_toolchain") 5 | 6 | package(default_visibility = ["//visibility:public"]) 7 | 8 | filegroup( 9 | name = "ruby_file", 10 | srcs = select({ 11 | "@platforms//os:windows": ["dist/bin/{ruby_binary_name}.exe"], 12 | "//conditions:default": ["dist/bin/{ruby_binary_name}"], 13 | }), 14 | ) 15 | 16 | rb_binary( 17 | name = "ruby", 18 | main = ":ruby_file", 19 | ) 20 | 21 | cc_library( 22 | name = "headers", 23 | hdrs = glob( 24 | ["dist/include/**/*.h"], 25 | allow_empty = True, 26 | ), 27 | includes = {includes}, 28 | ) 29 | 30 | java_import( 31 | name = "jars", 32 | jars = glob( 33 | ["dist/lib/**/*.jar"], 34 | allow_empty = True, 35 | ), 36 | neverlink = True, 37 | ) 38 | 39 | rb_toolchain( 40 | name = "toolchain", 41 | bundle = select({ 42 | "@platforms//os:windows": "dist/bin/bundle.cmd", 43 | "//conditions:default": "dist/bin/bundle", 44 | }), 45 | env = {env}, 46 | files = glob(["dist/**/*"]), 47 | gem = select({ 48 | "@platforms//os:windows": "dist/bin/{gem_binary_name}.cmd", 49 | "//conditions:default": "dist/bin/{gem_binary_name}", 50 | }), 51 | ruby = ":ruby_file", 52 | version = "{version}", 53 | ) 54 | 55 | [ 56 | rb_binary( 57 | name = file.removeprefix("dist/bin/"), 58 | main = file, 59 | ) 60 | for file in glob( 61 | ["dist/bin/*"], 62 | exclude = [ 63 | "dist/bin/ruby", 64 | "dist/bin/jruby", 65 | ] + glob([ 66 | "dist/bin/*.exe", 67 | ], allow_empty = True) + glob([ 68 | "dist/bin/*.cmd", 69 | ], allow_empty = True) + glob([ 70 | "dist/bin/*.bat", 71 | ], allow_empty = True), 72 | ) 73 | ] 74 | 75 | # vim: ft=bzl 76 | -------------------------------------------------------------------------------- /examples/gem/BUILD: -------------------------------------------------------------------------------- 1 | load("@aspect_bazel_lib//lib:expand_template.bzl", "expand_template") 2 | load("@aspect_bazel_lib//lib:paths.bzl", "BASH_RLOCATION_FUNCTION") 3 | load( 4 | "@rules_ruby//ruby:defs.bzl", 5 | "rb_binary", 6 | "rb_gem_build", 7 | "rb_gem_install", 8 | "rb_gem_push", 9 | "rb_test", 10 | ) 11 | load("@rules_shell//shell:sh_test.bzl", "sh_test") 12 | 13 | package(default_visibility = ["//:__subpackages__"]) 14 | 15 | expand_template( 16 | name = "shell_wrapper", 17 | out = "wrapper.sh", 18 | data = [ 19 | ":Rakefile", 20 | ":rake", 21 | ], 22 | substitutions = { 23 | "@@rlocation_lib@@": BASH_RLOCATION_FUNCTION.replace("$", "$$"), 24 | "@@rake_binary@@": "$(rlocationpaths :rake)", 25 | "@@rakefile@@": "$(rlocationpaths :Rakefile)", 26 | }, 27 | template = "wrapper.tpl.sh", 28 | ) 29 | 30 | sh_test( 31 | name = "shell_wrapper_test", 32 | srcs = [":shell_wrapper"], 33 | data = [ 34 | ":Rakefile", 35 | ":rake", 36 | ], 37 | tags = ["bcr-presubmit-failure"], 38 | deps = ["@bazel_tools//tools/bash/runfiles"], 39 | ) 40 | 41 | rb_binary( 42 | name = "rake", 43 | main = "@bundle//bin:rake", 44 | deps = [ 45 | "//lib:gem", 46 | "@bundle", 47 | ], 48 | ) 49 | 50 | rb_test( 51 | name = "rubocop", 52 | size = "small", 53 | timeout = "moderate", # JRuby startup can be slow 54 | data = [ 55 | ".rubocop.yml", 56 | "Gemfile", 57 | ], 58 | main = "@bundle//bin:rubocop", 59 | tags = ["no-sandbox"], 60 | deps = [ 61 | "//lib:gem", 62 | "//spec:add", 63 | "//spec:env", 64 | "//spec:subtract", 65 | "//spec:support", 66 | "@bundle", 67 | ], 68 | ) 69 | 70 | rb_gem_build( 71 | name = "gem-build", 72 | gemspec = "gem.gemspec", 73 | deps = ["//lib:gem"], 74 | ) 75 | 76 | rb_gem_install( 77 | name = "gem-install", 78 | gem = ":gem-build", 79 | ) 80 | 81 | rb_gem_push( 82 | name = "gem-release", 83 | gem = ":gem-build", 84 | ) 85 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/views/people/index.html.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream_from "people" %> 2 | <%= turbo_refreshes_with method: :morph, scroll: :preserve %> 3 | 4 |
5 | <% if notice.present? %> 6 |

8 | <%= notice %> 9 |

10 | <% end %> 11 | 12 |
13 |

People

14 |
15 | 16 | 17 | 18 | 19 | 27 | 28 | 29 | 30 | 31 | <% @people.each do |person| %> 32 | 33 | 34 | 37 | 38 | 60 | 61 | <% end %> 62 | 63 |
20 |
21 | <%= link_to 'New person', 22 | new_person_path, 23 | class: "inline rounded-lg py-3 px-5 bg-green-600 24 | text-white block font-medium" %> 25 |
26 |
35 |

<%= person.full_name %>

36 |
39 |
    40 |
  • 41 | <%= link_to 'Show', 42 | person, 43 | class: 'hover:underline' %> 44 |
  • 45 |
  • 46 | <%= link_to 'Edit', 47 | edit_person_path(person), 48 | class: 'hover:underline' %> 49 |
  • 50 | 51 |
  • 52 | <%= button_to 'Destroy', 53 | person, 54 | method: :delete, 55 | class: 'hover:underline', 56 | data: { turbo_confirm: "Are you sure?" } %> 57 |
  • 58 |
59 |
64 |
65 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/puma.rb: -------------------------------------------------------------------------------- 1 | # This configuration file will be evaluated by Puma. The top-level methods that 2 | # are invoked here are part of Puma's configuration DSL. For more information 3 | # about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html. 4 | # 5 | # Puma starts a configurable number of processes (workers) and each process 6 | # serves each request in a thread from an internal thread pool. 7 | # 8 | # You can control the number of workers using ENV["WEB_CONCURRENCY"]. You 9 | # should only set this value when you want to run 2 or more workers. The 10 | # default is already 1. 11 | # 12 | # The ideal number of threads per worker depends both on how much time the 13 | # application spends waiting for IO operations and on how much you wish to 14 | # prioritize throughput over latency. 15 | # 16 | # As a rule of thumb, increasing the number of threads will increase how much 17 | # traffic a given process can handle (throughput), but due to CRuby's 18 | # Global VM Lock (GVL) it has diminishing returns and will degrade the 19 | # response time (latency) of the application. 20 | # 21 | # The default is set to 3 threads as it's deemed a decent compromise between 22 | # throughput and latency for the average Rails application. 23 | # 24 | # Any libraries that use a connection pool or another resource pool should 25 | # be configured to provide at least as many connections as the number of 26 | # threads. This includes Active Record's `pool` parameter in `database.yml`. 27 | threads_count = ENV.fetch("RAILS_MAX_THREADS", 3) 28 | threads threads_count, threads_count 29 | 30 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 31 | port ENV.fetch("PORT", 3000) 32 | 33 | # Allow puma to be restarted by `bin/rails restart` command. 34 | plugin :tmp_restart 35 | 36 | # Run the Solid Queue supervisor inside of Puma for single-server deployments 37 | plugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"] 38 | 39 | # Specify the PID file. Defaults to tmp/pids/server.pid in development. 40 | # In other environments, only set the PID file if requested. 41 | pidfile ENV["PIDFILE"] if ENV["PIDFILE"] 42 | -------------------------------------------------------------------------------- /examples/gem/spec/BUILD: -------------------------------------------------------------------------------- 1 | load("@rules_ruby//ruby:defs.bzl", "rb_library", "rb_test") 2 | 3 | package(default_visibility = ["//:__pkg__"]) 4 | 5 | rb_library( 6 | name = "spec_helper", 7 | srcs = ["spec_helper.rb"], 8 | deps = [ 9 | "//lib:gem", 10 | "@bundle", 11 | ], 12 | ) 13 | 14 | rb_test( 15 | name = "add", 16 | size = "small", 17 | timeout = "moderate", # JRuby startup can be slow 18 | srcs = ["add_spec.rb"], 19 | args = ["spec/add_spec.rb"], 20 | main = "@bundle//bin:rspec", 21 | deps = [":spec_helper"], 22 | ) 23 | 24 | rb_library( 25 | name = "env_spec", 26 | srcs = ["env_spec.rb"], 27 | ) 28 | 29 | rb_test( 30 | name = "env", 31 | size = "small", 32 | timeout = "moderate", # JRuby startup can be slow 33 | srcs = [":env_spec"], 34 | args = ["spec/env_spec.rb"], 35 | data = ["//spec/support:file"], 36 | env = { 37 | "EXAMPLE": "ENV", 38 | "LOCATION_SRC": "$(location :env_spec)", 39 | "LOCATION_DEP": "$(location //lib/gem:add)", 40 | "LOCATION_DATA": "$(location //spec/support:file)", 41 | } | select({ 42 | "@ruby//engine:jruby": {"RUBY_ENGINE": "jruby"}, 43 | "@ruby//engine:truffleruby": {"RUBY_ENGINE": "truffleruby"}, 44 | "//conditions:default": {"RUBY_ENGINE": "ruby"}, 45 | }), 46 | env_inherit = [ 47 | "USER", # POSIX 48 | "USERNAME", # Windows 49 | ], 50 | main = "@bundle//bin:rspec", 51 | deps = [ 52 | ":spec_helper", 53 | "//lib/gem:add", 54 | ], 55 | ) 56 | 57 | rb_test( 58 | name = "support", 59 | size = "small", 60 | timeout = "moderate", # JRuby startup can be slow 61 | srcs = ["support_spec.rb"], 62 | args = ["spec/support_spec.rb"], 63 | data = ["//spec/support:file"], 64 | main = "@bundle//bin:rspec", 65 | deps = [":spec_helper"], 66 | ) 67 | 68 | rb_test( 69 | name = "subtract", 70 | size = "small", 71 | timeout = "moderate", # JRuby startup can be slow 72 | srcs = ["subtract_spec.rb"], 73 | args = ["spec/subtract_spec.rb"], 74 | main = "@bundle//bin:rspec", 75 | deps = [":spec_helper"], 76 | ) 77 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/app/controllers/people_controller.rb: -------------------------------------------------------------------------------- 1 | class PeopleController < ApplicationController 2 | before_action :set_person, only: %i[show edit update destroy] 3 | 4 | # GET /people or /people.json 5 | def index 6 | @people = Person.all 7 | end 8 | 9 | # GET /people/1 or /people/1.json 10 | def show 11 | end 12 | 13 | # GET /people/new 14 | def new 15 | @person = Person.new 16 | end 17 | 18 | # GET /people/1/edit 19 | def edit 20 | end 21 | 22 | # POST /people or /people.json 23 | def create 24 | @person = Person.new(person_params) 25 | 26 | respond_to do |format| 27 | if @person.save 28 | format.html { redirect_to @person, notice: "Person was successfully created." } 29 | format.json { render :show, status: :created, location: @person } 30 | else 31 | format.html { render :new, status: :unprocessable_entity } 32 | format.json { render json: @person.errors, status: :unprocessable_entity } 33 | end 34 | end 35 | end 36 | 37 | # PATCH/PUT /people/1 or /people/1.json 38 | def update 39 | respond_to do |format| 40 | if @person.update(person_params) 41 | format.html { redirect_to @person, notice: "Person was successfully updated.", status: :see_other } 42 | format.json { render :show, status: :ok, location: @person } 43 | else 44 | format.html { render :edit, status: :unprocessable_entity } 45 | format.json { render json: @person.errors, status: :unprocessable_entity } 46 | end 47 | end 48 | end 49 | 50 | # DELETE /people/1 or /people/1.json 51 | def destroy 52 | @person.destroy! 53 | 54 | respond_to do |format| 55 | format.html { redirect_to people_path, notice: "Person was successfully destroyed.", status: :see_other } 56 | format.json { head :no_content } 57 | end 58 | end 59 | 60 | private 61 | 62 | # Use callbacks to share common setup or constraints between actions. 63 | def set_person 64 | @person = Person.find(params.expect(:id)) 65 | end 66 | 67 | # Only allow a list of trusted parameters through. 68 | def person_params 69 | params.expect(person: [:first_name, :last_name]) 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /ruby/private/binary/binary.sh.tpl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | {rlocation_function} 4 | 5 | warn() { 6 | if [[ "${#}" -gt 0 ]]; then 7 | echo >&2 "${@}" 8 | else 9 | cat >&2 10 | fi 11 | } 12 | 13 | # shellcheck disable=SC2120 14 | fail() { 15 | local cmd=(warn) 16 | if [[ "${#}" -gt 0 ]]; then 17 | cmd+=("${@}") 18 | fi 19 | "${cmd[@]}" 20 | exit 1 21 | } 22 | 23 | # Provide a realpath implementation for macOS. 24 | realpath() ( 25 | OURPWD=$PWD 26 | cd "$(dirname "$1")" 27 | LINK=$(readlink "$(basename "$1")") 28 | while [ "$LINK" ]; do 29 | cd "$(dirname "$LINK")" 30 | LINK=$(readlink "$(basename "$1")") 31 | done 32 | REALPATH="$PWD/$(basename "$1")" 33 | cd "$OURPWD" 34 | echo "$REALPATH" 35 | ) 36 | 37 | export RUNFILES_DIR="$(realpath "${RUNFILES_DIR:-$0.runfiles}")" 38 | 39 | # Find location of Ruby in runfiles. 40 | export PATH=$(dirname $(rlocation {ruby})):$PATH 41 | 42 | # Find location of JAVA_HOME in runfiles. 43 | if [ -n "{java_bin}" ]; then 44 | export JAVA_HOME=$(dirname $(dirname $(rlocation "{java_bin}"))) 45 | fi 46 | 47 | # Bundler expects the $HOME directory to be writable and produces misleading 48 | # warnings if it isn't. This isn't the case in every situation (e.g. remote 49 | # execution) and Bazel recommends using $TEST_TMPDIR when it's available: 50 | # https://bazel.build/reference/test-encyclopedia#initial-conditions 51 | # 52 | # We set $HOME prior to setting environment variables from the target itself so 53 | # that users can override this behavior if they desire. 54 | if [ -n "${TEST_TMPDIR:-}" ]; then 55 | export HOME=$TEST_TMPDIR 56 | fi 57 | 58 | # Set environment variables. 59 | {env} 60 | 61 | # Find location of Bundle path in runfiles. 62 | if [ -n "{bundler_command}" ]; then 63 | export BUNDLE_GEMFILE=$(rlocation $BUNDLE_GEMFILE) 64 | export BUNDLE_PATH=$(rlocation $BUNDLE_PATH) 65 | fi 66 | 67 | if [ -n "{locate_binary_in_runfiles}" ]; then 68 | binary="$(rlocation "{binary}")" \ 69 | || (fail "Failed to locate {binary} in the runfiles." \ 70 | "Did you forget to add the binary to the deps?") 71 | else 72 | binary="{binary}" 73 | fi 74 | 75 | exec {bundler_command} {ruby_binary_name} $binary {args} "$@" 76 | 77 | # vim: ft=bash 78 | -------------------------------------------------------------------------------- /examples/jekyll/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.8.6) 5 | public_suffix (>= 2.0.2, < 6.0) 6 | colorator (1.1.0) 7 | concurrent-ruby (1.2.3) 8 | em-websocket (0.5.3) 9 | eventmachine (>= 0.12.9) 10 | http_parser.rb (~> 0) 11 | eventmachine (1.2.7) 12 | ffi (1.16.3) 13 | forwardable-extended (2.6.0) 14 | http_parser.rb (0.8.0) 15 | i18n (1.14.1) 16 | concurrent-ruby (~> 1.0) 17 | jekyll (3.9.4) 18 | addressable (~> 2.4) 19 | colorator (~> 1.0) 20 | em-websocket (~> 0.5) 21 | i18n (>= 0.7, < 2) 22 | jekyll-sass-converter (~> 1.0) 23 | jekyll-watch (~> 2.0) 24 | kramdown (>= 1.17, < 3) 25 | liquid (~> 4.0) 26 | mercenary (~> 0.3.3) 27 | pathutil (~> 0.9) 28 | rouge (>= 1.7, < 4) 29 | safe_yaml (~> 1.0) 30 | jekyll-feed (0.17.0) 31 | jekyll (>= 3.7, < 5.0) 32 | jekyll-sass-converter (1.5.2) 33 | sass (~> 3.4) 34 | jekyll-seo-tag (2.8.0) 35 | jekyll (>= 3.8, < 5.0) 36 | jekyll-watch (2.2.1) 37 | listen (~> 3.0) 38 | kramdown (2.4.0) 39 | rexml 40 | kramdown-parser-gfm (1.1.0) 41 | kramdown (~> 2.0) 42 | liquid (4.0.4) 43 | listen (3.8.0) 44 | rb-fsevent (~> 0.10, >= 0.10.3) 45 | rb-inotify (~> 0.9, >= 0.9.10) 46 | mercenary (0.3.6) 47 | minima (2.5.1) 48 | jekyll (>= 3.5, < 5.0) 49 | jekyll-feed (~> 0.9) 50 | jekyll-seo-tag (~> 2.1) 51 | pathutil (0.16.2) 52 | forwardable-extended (~> 2.6) 53 | public_suffix (5.0.4) 54 | rb-fsevent (0.11.2) 55 | rb-inotify (0.10.1) 56 | ffi (~> 1.0) 57 | rexml (3.2.6) 58 | rouge (3.30.0) 59 | safe_yaml (1.0.5) 60 | sass (3.7.4) 61 | sass-listen (~> 4.0.0) 62 | sass-listen (4.0.0) 63 | rb-fsevent (~> 0.9, >= 0.9.4) 64 | rb-inotify (~> 0.9, >= 0.9.7) 65 | wdm (0.1.1) 66 | webrick (1.8.1) 67 | 68 | PLATFORMS 69 | arm64-darwin-23 70 | arm64-darwin-24 71 | x86_64-darwin-21 72 | x86_64-linux 73 | 74 | DEPENDENCIES 75 | http_parser.rb (~> 0.6.0) 76 | jekyll (~> 3.9.3) 77 | jekyll-feed (~> 0.6) 78 | kramdown-parser-gfm 79 | minima (~> 2.0) 80 | tzinfo (>= 1, < 3) 81 | tzinfo-data 82 | wdm (~> 0.1.0) 83 | webrick (~> 1.8) 84 | 85 | BUNDLED WITH 86 | 2.3.3 87 | -------------------------------------------------------------------------------- /examples/deep_gem/MODULE.bazel: -------------------------------------------------------------------------------- 1 | bazel_dep(name = "rules_ruby", version = "0.0.0", dev_dependency = True) 2 | local_path_override( 3 | module_name = "rules_ruby", 4 | path = "../..", 5 | ) 6 | 7 | ruby = use_extension("@rules_ruby//ruby:extensions.bzl", "ruby") 8 | ruby.toolchain( 9 | name = "ruby", 10 | version_file = "//:.ruby-version", 11 | ) 12 | ruby.bundle_fetch( 13 | name = "bundle", 14 | # List the gemspec and any files that it requires. We cannot use an 15 | # rb_library to tidy this up because bundle fetch is executed during the 16 | # loading phase. 17 | srcs = [ 18 | "//hello_world:hello_world.gemspec", 19 | "//hello_world/lib/hello_world:version.rb", 20 | ], 21 | gem_checksums = { 22 | "date-3.4.1-java": "74740d914c65a922a15657c25ff0e203c16f1d0f7aa910a9ebed712afe9819c4", 23 | "diff-lcs-1.6.2": "9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962", 24 | "erb-5.0.2-java": "d000d963afebc166ec7f2499b2b3198d526790cf962c37514d7a85843a60423c", 25 | "io-console-0.8.1-java": "9457a61a7b23aab11e9e9ff67f71ae81d7f1a6a2e582bb5d65d754cbb546c06f", 26 | "irb-1.15.2": "222f32952e278da34b58ffe45e8634bf4afc2dc7aa9da23fed67e581aa50fdba", 27 | "jar-dependencies-0.5.5": "2972b9fcba4b014e6446a84b5c09674a3e8648b95b71768e729f0e8e40568059", 28 | "pp-0.6.2": "947ec3120c6f92195f8ee8aa25a7b2c5297bb106d83b41baa02983686577b6ff", 29 | "prettyprint-0.2.0": "2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193", 30 | "psych-5.2.6-java": "0a5f65d47ed1ae3475d062b254e7b2035a259eac578038016d62172dd4cfbd91", 31 | "rdoc-6.14.2": "9fdd44df130f856ae70cc9a264dfd659b9b40de369b16581f4ab746e42439226", 32 | "reline-0.6.2": "1dad26a6008872d59c8e05244b119347c9f2ddaf4a53dce97856cd5f30a02846", 33 | "rspec-3.13.1": "b9f9a58fa915b8d94a1d6b3195fe6dd28c4c34836a6097015142c4a9ace72140", 34 | "rspec-core-3.13.5": "ab3f682897c6131c67f9a17cfee5022a597f283aebe654d329a565f9937a4fa3", 35 | "rspec-expectations-3.13.5": "33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836", 36 | "rspec-mocks-3.13.5": "e4338a6f285ada9fe56f5893f5457783af8194f5d08884d17a87321d5195ea81", 37 | "rspec-support-3.13.4": "184b1814f6a968102b57df631892c7f1990a91c9a3b9e80ef892a0fc2a71a3f7", 38 | }, 39 | gemfile = "//hello_world:Gemfile", 40 | gemfile_lock = "//hello_world:Gemfile.lock", 41 | ) 42 | use_repo(ruby, "bundle", "ruby", "ruby_toolchains") 43 | 44 | register_toolchains("@ruby_toolchains//:all") 45 | -------------------------------------------------------------------------------- /.github/workflows/release_prep.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o pipefail 4 | 5 | # Set by GH actions, see 6 | # https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables 7 | TAG=${GITHUB_REF_NAME} 8 | # The prefix is chosen to match what GitHub generates for source archives 9 | PREFIX="rules_ruby-${TAG:1}" 10 | ARCHIVE="rules_ruby-$TAG.tar.gz" 11 | 12 | # NB: configuration for 'git archive' is in /.gitattributes 13 | git archive --format=tar --prefix=${PREFIX}/ ${TAG} | gzip > $ARCHIVE 14 | SHA=$(shasum -a 256 $ARCHIVE | awk '{print $1}') 15 | 16 | # Add generated API docs to the release, see https://github.com/bazelbuild/bazel-central-registry/issues/5593 17 | docs="$(mktemp -d)"; targets="$(mktemp)" 18 | bazel --output_base="$docs" query --output=label --output_file="$targets" 'kind("starlark_doc_extract rule", //rails:all //ruby:all)' 19 | bazel --output_base="$docs" build --target_pattern_file="$targets" 20 | tar --create --auto-compress \ 21 | --directory "$(bazel --output_base="$docs" info bazel-bin)" \ 22 | --file "$GITHUB_WORKSPACE/${ARCHIVE%.tar.gz}.docs.tar.gz" . 23 | 24 | # The stdout of this program will be used as the top of the release notes for this release. 25 | cat << EOF 26 | ## Using Bzlmod with Bazel 7-8 27 | 28 | 1. Add to your \`MODULE.bazel\` file: 29 | 30 | \`\`\`starlark 31 | bazel_dep(name = "rules_ruby", version = "${TAG:1}") 32 | \`\`\` 33 | 34 | ## Using Bzlmod with Bazel 6 35 | 36 | 1. Enable with \`common --enable_bzlmod\` in \`.bazelrc\`. 37 | 2. Add to your \`MODULE.bazel\` file: 38 | 39 | \`\`\`starlark 40 | bazel_dep(name = "rules_ruby", version = "${TAG:1}") 41 | \`\`\` 42 | 43 | ## Using WORKSPACE 44 | 45 | Paste this snippet into your \`WORKSPACE.bazel\` file: 46 | 47 | \`\`\`starlark 48 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 49 | 50 | # Skylib is a dependency, remove if you already have it. 51 | http_archive( 52 | name = "bazel_skylib", 53 | sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506", 54 | urls = [ 55 | "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz", 56 | "https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz", 57 | ], 58 | ) 59 | 60 | http_archive( 61 | name = "rules_ruby", 62 | sha256 = "${SHA}", 63 | strip_prefix = "${PREFIX}", 64 | url = "https://github.com/bazel-contrib/rules_ruby/releases/download/${TAG}/${ARCHIVE}", 65 | ) 66 | \`\`\` 67 | EOF 68 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | # check=error=true 3 | 4 | # This Dockerfile is designed for production, not development. Use with Kamal or build'n'run by hand: 5 | # docker build -t people_tracker . 6 | # docker run -d -p 80:80 -e RAILS_MASTER_KEY= --name people_tracker people_tracker 7 | 8 | # For a containerized dev environment, see Dev Containers: https://guides.rubyonrails.org/getting_started_with_devcontainer.html 9 | 10 | # Make sure RUBY_VERSION matches the Ruby version in .ruby-version 11 | ARG RUBY_VERSION=3.4.5 12 | FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base 13 | 14 | # Rails app lives here 15 | WORKDIR /rails 16 | 17 | # Install base packages 18 | RUN apt-get update -qq && \ 19 | apt-get install --no-install-recommends -y curl libjemalloc2 libvips sqlite3 && \ 20 | rm -rf /var/lib/apt/lists /var/cache/apt/archives 21 | 22 | # Set production environment 23 | ENV RAILS_ENV="production" \ 24 | BUNDLE_DEPLOYMENT="1" \ 25 | BUNDLE_PATH="/usr/local/bundle" \ 26 | BUNDLE_WITHOUT="development" 27 | 28 | # Throw-away build stage to reduce size of final image 29 | FROM base AS build 30 | 31 | # Install packages needed to build gems 32 | RUN apt-get update -qq && \ 33 | apt-get install --no-install-recommends -y build-essential git libyaml-dev pkg-config && \ 34 | rm -rf /var/lib/apt/lists /var/cache/apt/archives 35 | 36 | # Install application gems 37 | COPY Gemfile Gemfile.lock ./ 38 | RUN bundle install && \ 39 | rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \ 40 | bundle exec bootsnap precompile --gemfile 41 | 42 | # Copy application code 43 | COPY . . 44 | 45 | # Precompile bootsnap code for faster boot times 46 | RUN bundle exec bootsnap precompile app/ lib/ 47 | 48 | # Precompiling assets for production without requiring secret RAILS_MASTER_KEY 49 | RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile 50 | 51 | 52 | 53 | 54 | # Final stage for app image 55 | FROM base 56 | 57 | # Copy built artifacts: gems, application 58 | COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}" 59 | COPY --from=build /rails /rails 60 | 61 | # Run and own only the runtime files as a non-root user for security 62 | RUN groupadd --system --gid 1000 rails && \ 63 | useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \ 64 | chown -R rails:rails db log storage tmp 65 | USER 1000:1000 66 | 67 | # Entrypoint prepares the database. 68 | ENTRYPOINT ["/rails/bin/docker-entrypoint"] 69 | 70 | # Start server via Thruster by default, this can be overwritten at runtime 71 | EXPOSE 80 72 | CMD ["./bin/thrust", "./bin/rails", "server"] 73 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | # The test environment is used exclusively to run your application's 2 | # test suite. You never need to work with it otherwise. Remember that 3 | # your test database is "scratch space" for the test suite and is wiped 4 | # and recreated between test runs. Don't rely on the data there! 5 | 6 | Rails.application.configure do 7 | # Settings specified here will take precedence over those in config/application.rb. 8 | 9 | # While tests run files are not watched, reloading is not necessary. 10 | config.enable_reloading = false 11 | 12 | # Eager loading loads your entire application. When running a single test locally, 13 | # this is usually not necessary, and can slow down your test suite. However, it's 14 | # recommended that you enable it in continuous integration systems to ensure eager 15 | # loading is working properly before deploying your code. 16 | config.eager_load = ENV["CI"].present? 17 | 18 | # Configure public file server for tests with cache-control for performance. 19 | config.public_file_server.headers = {"cache-control" => "public, max-age=3600"} 20 | 21 | # Show full error reports. 22 | config.consider_all_requests_local = true 23 | config.cache_store = :null_store 24 | 25 | # Render exception templates for rescuable exceptions and raise for other exceptions. 26 | config.action_dispatch.show_exceptions = :rescuable 27 | 28 | # Disable request forgery protection in test environment. 29 | config.action_controller.allow_forgery_protection = false 30 | 31 | # Store uploaded files on the local file system in a temporary directory. 32 | config.active_storage.service = :test 33 | 34 | # Tell Action Mailer not to deliver emails to the real world. 35 | # The :test delivery method accumulates sent emails in the 36 | # ActionMailer::Base.deliveries array. 37 | config.action_mailer.delivery_method = :test 38 | 39 | # Set host to be used by links generated in mailer templates. 40 | config.action_mailer.default_url_options = {host: "example.com"} 41 | 42 | # Print deprecation notices to the stderr. 43 | config.active_support.deprecation = :stderr 44 | 45 | # Configure logging to stderr for Bazel sandboxed environment 46 | config.logger = ActiveSupport::Logger.new($stderr) 47 | config.log_level = :warn 48 | 49 | # Raises error for missing translations. 50 | # config.i18n.raise_on_missing_translations = true 51 | 52 | # Annotate rendered view with file names. 53 | # config.action_view.annotate_rendered_view_with_filenames = true 54 | 55 | # Raise error when a before_action's only/except options reference missing actions. 56 | config.action_controller.raise_on_missing_callback_actions = true 57 | end 58 | -------------------------------------------------------------------------------- /examples/gem/Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | example (0.1.0) 5 | i18n (~> 1.14) 6 | rake (~> 13) 7 | 8 | GEM 9 | remote: https://rubygems.org/ 10 | specs: 11 | ast (2.4.2) 12 | concurrent-ruby (1.3.5) 13 | date (3.4.1) 14 | date (3.4.1-java) 15 | debug (1.10.0) 16 | irb (~> 1.10) 17 | reline (>= 0.3.8) 18 | diff-lcs (1.5.1) 19 | i18n (1.14.7) 20 | concurrent-ruby (~> 1.0) 21 | io-console (0.8.0) 22 | io-console (0.8.0-java) 23 | irb (1.15.1) 24 | pp (>= 0.6.0) 25 | rdoc (>= 4.0.0) 26 | reline (>= 0.4.2) 27 | jar-dependencies (0.5.3) 28 | json (2.9.1) 29 | json (2.9.1-java) 30 | language_server-protocol (3.17.0.3) 31 | parallel (1.26.3) 32 | parser (3.3.7.0) 33 | ast (~> 2.4.1) 34 | racc 35 | pp (0.6.2) 36 | prettyprint 37 | prettyprint (0.2.0) 38 | psych (5.2.3) 39 | date 40 | stringio 41 | psych (5.2.3-java) 42 | date 43 | jar-dependencies (>= 0.1.7) 44 | racc (1.8.1) 45 | racc (1.8.1-java) 46 | rainbow (3.1.1) 47 | rake (13.2.1) 48 | rdoc (6.11.0) 49 | psych (>= 4.0.0) 50 | regexp_parser (2.10.0) 51 | reline (0.6.0) 52 | io-console (~> 0.5) 53 | rspec (3.13.0) 54 | rspec-core (~> 3.13.0) 55 | rspec-expectations (~> 3.13.0) 56 | rspec-mocks (~> 3.13.0) 57 | rspec-core (3.13.2) 58 | rspec-support (~> 3.13.0) 59 | rspec-expectations (3.13.3) 60 | diff-lcs (>= 1.2.0, < 2.0) 61 | rspec-support (~> 3.13.0) 62 | rspec-mocks (3.13.2) 63 | diff-lcs (>= 1.2.0, < 2.0) 64 | rspec-support (~> 3.13.0) 65 | rspec-support (3.13.2) 66 | rubocop (1.71.0) 67 | json (~> 2.3) 68 | language_server-protocol (>= 3.17.0) 69 | parallel (~> 1.10) 70 | parser (>= 3.3.0.2) 71 | rainbow (>= 2.2.2, < 4.0) 72 | regexp_parser (>= 2.9.3, < 3.0) 73 | rubocop-ast (>= 1.36.2, < 2.0) 74 | ruby-progressbar (~> 1.7) 75 | unicode-display_width (>= 2.4.0, < 4.0) 76 | rubocop-ast (1.37.0) 77 | parser (>= 3.3.1.0) 78 | ruby-progressbar (1.13.0) 79 | stringio (3.1.2) 80 | unicode-display_width (3.1.4) 81 | unicode-emoji (~> 4.0, >= 4.0.4) 82 | unicode-emoji (4.0.4) 83 | 84 | PLATFORMS 85 | arm64-darwin-23 86 | arm64-darwin-24 87 | java 88 | ruby 89 | universal-java-1.8 90 | universal-java-11 91 | universal-java-17 92 | universal-java-18 93 | universal-java-21 94 | x64-mingw32 95 | 96 | DEPENDENCIES 97 | debug (>= 1.0.0) 98 | example! 99 | psych (~> 5.1) 100 | rspec (~> 3.0) 101 | rubocop (~> 1.64) 102 | 103 | BUNDLED WITH 104 | 2.3.3 105 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main" 4 | gem "rails", "~> 8.0.2", ">= 8.0.2.1" 5 | # The modern asset pipeline for Rails [https://github.com/rails/propshaft] 6 | gem "propshaft" 7 | # Use sqlite3 as the database for Active Record 8 | gem "sqlite3", ">= 2.1" 9 | # Use the Puma web server [https://github.com/puma/puma] 10 | gem "puma", ">= 5.0" 11 | # Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails] 12 | gem "importmap-rails" 13 | # Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev] 14 | gem "turbo-rails" 15 | # Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev] 16 | gem "stimulus-rails" 17 | # Use Tailwind CSS [https://github.com/rails/tailwindcss-rails] 18 | gem "tailwindcss-rails" 19 | # Build JSON APIs with ease [https://github.com/rails/jbuilder] 20 | gem "jbuilder" 21 | 22 | # Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] 23 | # gem "bcrypt", "~> 3.1.7" 24 | 25 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 26 | gem "tzinfo-data", platforms: %i[ windows jruby ] 27 | 28 | # Use the database-backed adapters for Rails.cache, Active Job, and Action Cable 29 | gem "solid_cache" 30 | gem "solid_queue" 31 | gem "solid_cable" 32 | 33 | # Reduces boot times through caching; required in config/boot.rb 34 | gem "bootsnap", require: false 35 | 36 | # Deploy this application anywhere as a Docker container [https://kamal-deploy.org] 37 | gem "kamal", require: false 38 | 39 | # Add HTTP asset caching/compression and X-Sendfile acceleration to Puma [https://github.com/basecamp/thruster/] 40 | gem "thruster", require: false 41 | 42 | # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] 43 | # gem "image_processing", "~> 1.2" 44 | 45 | group :development, :test do 46 | # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem 47 | gem "debug", platforms: %i[ mri windows ], require: "debug/prelude" 48 | 49 | # Static analysis for security vulnerabilities [https://brakemanscanner.org/] 50 | gem "brakeman", require: false 51 | 52 | # Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/] 53 | gem "rubocop-rails-omakase", require: false 54 | end 55 | 56 | group :development do 57 | # Use console on exceptions pages [https://github.com/rails/web-console] 58 | gem "web-console" 59 | end 60 | 61 | group :test do 62 | # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing] 63 | gem "capybara" 64 | gem "selenium-webdriver" 65 | end 66 | 67 | gem "cancancan", "~> 3.6" 68 | 69 | gem "devise", "~> 4.9" 70 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/environments/development.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # Make code changes take effect immediately without server restart. 7 | config.enable_reloading = true 8 | 9 | # Do not eager load code on boot. 10 | config.eager_load = false 11 | 12 | # Show full error reports. 13 | config.consider_all_requests_local = true 14 | 15 | # Enable server timing. 16 | config.server_timing = true 17 | 18 | # Enable/disable Action Controller caching. By default Action Controller caching is disabled. 19 | # Run rails dev:cache to toggle Action Controller caching. 20 | if Rails.root.join("tmp/caching-dev.txt").exist? 21 | config.action_controller.perform_caching = true 22 | config.action_controller.enable_fragment_cache_logging = true 23 | config.public_file_server.headers = { "cache-control" => "public, max-age=#{2.days.to_i}" } 24 | else 25 | config.action_controller.perform_caching = false 26 | end 27 | 28 | # Change to :null_store to avoid any caching. 29 | config.cache_store = :memory_store 30 | 31 | # Store uploaded files on the local file system (see config/storage.yml for options). 32 | config.active_storage.service = :local 33 | 34 | # Don't care if the mailer can't send. 35 | config.action_mailer.raise_delivery_errors = false 36 | 37 | # Make template changes take effect immediately. 38 | config.action_mailer.perform_caching = false 39 | 40 | # Set localhost to be used by links generated in mailer templates. 41 | config.action_mailer.default_url_options = { host: "localhost", port: 3000 } 42 | 43 | # Print deprecation notices to the Rails logger. 44 | config.active_support.deprecation = :log 45 | 46 | # Raise an error on page load if there are pending migrations. 47 | config.active_record.migration_error = :page_load 48 | 49 | # Highlight code that triggered database queries in logs. 50 | config.active_record.verbose_query_logs = true 51 | 52 | # Append comments with runtime information tags to SQL queries in logs. 53 | config.active_record.query_log_tags_enabled = true 54 | 55 | # Highlight code that enqueued background job in logs. 56 | config.active_job.verbose_enqueue_logs = true 57 | 58 | # Raises error for missing translations. 59 | # config.i18n.raise_on_missing_translations = true 60 | 61 | # Annotate rendered view with file names. 62 | config.action_view.annotate_rendered_view_with_filenames = true 63 | 64 | # Uncomment if you wish to allow Action Cable access from any origin. 65 | # config.action_cable.disable_request_forgery_protection = true 66 | 67 | # Raise error when a before_action's only/except options reference missing actions. 68 | config.action_controller.raise_on_missing_callback_actions = true 69 | 70 | # Apply autocorrection by RuboCop to files generated by `bin/rails generate`. 71 | # config.generators.apply_rubocop_autocorrect_after_generate! 72 | end 73 | -------------------------------------------------------------------------------- /ruby/private/BUILD: -------------------------------------------------------------------------------- 1 | load("@bazel_skylib//:bzl_library.bzl", "bzl_library") 2 | 3 | bzl_library( 4 | name = "binary", 5 | srcs = ["binary.bzl"], 6 | visibility = ["//ruby:__subpackages__"], 7 | deps = [ 8 | ":library", 9 | ":providers", 10 | ":utils", 11 | ], 12 | ) 13 | 14 | bzl_library( 15 | name = "gem_build", 16 | srcs = ["gem_build.bzl"], 17 | visibility = ["//ruby:__subpackages__"], 18 | deps = [ 19 | ":library", 20 | ":providers", 21 | ":utils", 22 | ], 23 | ) 24 | 25 | bzl_library( 26 | name = "gem_push", 27 | srcs = ["gem_push.bzl"], 28 | visibility = ["//ruby:__subpackages__"], 29 | deps = [ 30 | ":binary", 31 | ":library", 32 | ], 33 | ) 34 | 35 | bzl_library( 36 | name = "library", 37 | srcs = ["library.bzl"], 38 | visibility = ["//ruby:__subpackages__"], 39 | deps = [":providers"], 40 | ) 41 | 42 | bzl_library( 43 | name = "test", 44 | srcs = ["test.bzl"], 45 | visibility = ["//ruby:__subpackages__"], 46 | deps = [ 47 | ":binary", 48 | ":library", 49 | ], 50 | ) 51 | 52 | bzl_library( 53 | name = "toolchain", 54 | srcs = ["toolchain.bzl"], 55 | visibility = ["//ruby:__subpackages__"], 56 | deps = [ 57 | ":download", 58 | "//ruby/private/toolchain:repository_proxy", 59 | ], 60 | ) 61 | 62 | bzl_library( 63 | name = "bundler_checksums", 64 | srcs = ["bundler_checksums.bzl"], 65 | visibility = ["//ruby:__subpackages__"], 66 | ) 67 | 68 | bzl_library( 69 | name = "bundle_fetch", 70 | srcs = ["bundle_fetch.bzl"], 71 | visibility = ["//ruby:__subpackages__"], 72 | deps = [ 73 | ":bundler_checksums", 74 | ":utils", 75 | "//ruby/private/bundle_fetch:gemfile_lock_parser", 76 | "@bazel_skylib//lib:paths", 77 | "@bazel_skylib//lib:versions", 78 | "@bazel_tools//tools/build_defs/repo:utils.bzl", 79 | ], 80 | ) 81 | 82 | bzl_library( 83 | name = "bundle_install", 84 | srcs = ["bundle_install.bzl"], 85 | visibility = ["//ruby:__subpackages__"], 86 | deps = [ 87 | ":bundle_fetch", 88 | ":gem_install", 89 | ":providers", 90 | ":utils", 91 | ], 92 | ) 93 | 94 | bzl_library( 95 | name = "gem", 96 | srcs = ["gem.bzl"], 97 | visibility = ["//ruby:__subpackages__"], 98 | deps = [":providers"], 99 | ) 100 | 101 | bzl_library( 102 | name = "gem_install", 103 | srcs = ["gem_install.bzl"], 104 | visibility = ["//ruby:__subpackages__"], 105 | deps = [ 106 | ":providers", 107 | ":utils", 108 | ], 109 | ) 110 | 111 | bzl_library( 112 | name = "bundle", 113 | srcs = ["bundle.bzl"], 114 | visibility = ["//ruby:__subpackages__"], 115 | ) 116 | 117 | bzl_library( 118 | name = "download", 119 | srcs = ["download.bzl"], 120 | visibility = ["//ruby:__subpackages__"], 121 | ) 122 | 123 | bzl_library( 124 | name = "providers", 125 | srcs = ["providers.bzl"], 126 | visibility = ["//ruby:__subpackages__"], 127 | ) 128 | 129 | bzl_library( 130 | name = "utils", 131 | srcs = ["utils.bzl"], 132 | visibility = ["//ruby:__subpackages__"], 133 | ) 134 | -------------------------------------------------------------------------------- /examples/rails/README.md: -------------------------------------------------------------------------------- 1 | # Rails Example 2 | 3 | This example demonstrates how to use Bazel and rules_ruby to build and test a 4 | Ruby on Rails application. The actual Rails application lives under the 5 | `people_tracker` directory. 6 | 7 | ## Development Workflow 8 | 9 | ### Bazel Testing 10 | 11 | ```bash 12 | bazel test //... 13 | ``` 14 | 15 | ### Direnv Setup 16 | 17 | This project uses [direnv](https://direnv.net/) to provide access to `rails` 18 | and other related binaries on the command-line. Make sure you have direnv 19 | installed and allow the `.envrc` file: 20 | 21 | ```bash 22 | direnv allow 23 | ``` 24 | 25 | #### Rails Command 26 | 27 | Once direnv is configured, change into the `people_tracker/` directory and run 28 | `rails` commands directly for development tasks instead of using 29 | `people_tracker/bin/rails`: 30 | 31 | ```bash 32 | cd people_tracker/ 33 | rails test 34 | rails generate scaffold Foo 35 | rails server 36 | ``` 37 | 38 | The `rails` command will automatically use the Ruby gems installed by Bazel, 39 | so there is no need to run `bundle install` separately. 40 | 41 | ## Implementation Notes 42 | 43 | ### Rails Test Setup 44 | 45 | To run Rails tests with Bazel, you need to create test macros that configure the 46 | Rails test environment. Create a file at `people_tracker/test/rails_test.bzl`: 47 | 48 | ```starlark 49 | """Module for app-specific rails helpers and macros.""" 50 | 51 | load("@rules_ruby//rails:rails_test_factory.bzl", "rails_test_factory") 52 | 53 | # This is the directory in the Bazel workspace where the test helpers reside. 54 | # This is used to generate the test helper labels and appropriate includes. 55 | _TEST_PKG = "people_tracker/test" 56 | 57 | # The rails_test macro is used to define Bazel test targets for Rails model and 58 | # controller tests. See examples in people_tracker/test/models/BUILD.bazel. 59 | rails_test = rails_test_factory.new_test(test_package = _TEST_PKG) 60 | 61 | # The rails_system_test macro is used to define Bazel test targets for Rails 62 | # system tests. See examples in people_tracker/test/system/BUILD.bazel. 63 | rails_system_test = rails_test_factory.new_system_test(test_package = _TEST_PKG) 64 | ``` 65 | 66 | These macros (`rails_test` and `rails_system_test`) can then be used in your 67 | `BUILD.bazel` files to define test targets for your Rails application. 68 | 69 | The tests are configured to use a SQLite in-memory database for fast, isolated 70 | test execution. 71 | 72 | ### Patches 73 | 74 | To prevent Ruby from escaping the sandbox, Ruby requires patches to `Kernel` 75 | functions. This example implements the patches to 76 | `people_tracker/config/initializers/bazel_ruby_patches.rb`. Being included in 77 | the `config/initializers` directory for a Rails app ensures that it is applied 78 | early in the Rails load process. However, we need to apply it earlier in the 79 | load process for tests. So, we add it to the top of the 80 | `people_tracker/test/test_helper.rb`. 81 | 82 | ### Direnv - Using rails from the command-line 83 | 84 | If you install [direnv](https://direnv.net/) and allow it to load the 85 | environment defined in the `.envrc` files, you can run `rails` commands using 86 | the Ruby and Rails installed by Bazel. The `rails` command will automatically 87 | use the Ruby gems installed by Bazel, so there is no need to run `bundle 88 | install` separately. 89 | -------------------------------------------------------------------------------- /ruby/private/toolchain.bzl: -------------------------------------------------------------------------------- 1 | "Repository rule for registering Ruby interpreters" 2 | 3 | load("//ruby/private:download.bzl", _rb_download = "rb_download") 4 | load("//ruby/private/toolchain:repository_proxy.bzl", _rb_toolchain_repository_proxy = "rb_toolchain_repository_proxy") 5 | 6 | DEFAULT_RUBY_REPOSITORY = "ruby" 7 | 8 | def rb_register_toolchains( 9 | name = DEFAULT_RUBY_REPOSITORY, 10 | version = None, 11 | version_file = None, 12 | msys2_packages = ["libyaml"], 13 | register = True, 14 | **kwargs): 15 | """ 16 | Register a Ruby toolchain and lazily download the Ruby Interpreter. 17 | 18 | * _(For MRI on Linux and macOS)_ Installed using [ruby-build](https://github.com/rbenv/ruby-build). 19 | * _(For MRI on Windows)_ Installed using [RubyInstaller](https://rubyinstaller.org). 20 | * _(For JRuby on any OS)_ Downloaded and installed directly from [official website](https://www.jruby.org). 21 | * _(For TruffleRuby on Linux and macOS)_ Installed using [ruby-build](https://github.com/rbenv/ruby-build). 22 | * _(For "system")_ Ruby found on the PATH is used. Please note that builds are not hermetic in this case. 23 | 24 | `WORKSPACE`: 25 | ```bazel 26 | load("@rules_ruby//ruby:deps.bzl", "rb_register_toolchains") 27 | 28 | rb_register_toolchains( 29 | version = "3.0.6" 30 | ) 31 | ``` 32 | 33 | Once registered, you can use the toolchain directly as it provides all the binaries: 34 | 35 | ```output 36 | $ bazel run @ruby -- -e "puts RUBY_VERSION" 37 | $ bazel run @ruby//:bundle -- update 38 | $ bazel run @ruby//:gem -- install rails 39 | ``` 40 | 41 | You can also use Ruby engine targets to `select()` depending on installed Ruby interpreter: 42 | 43 | `BUILD`: 44 | ```bazel 45 | rb_library( 46 | name = "my_lib", 47 | srcs = ["my_lib.rb"], 48 | deps = select({ 49 | "@ruby//engine:jruby": [":my_jruby_lib"], 50 | "@ruby//engine:truffleruby": ["//:my_truffleruby_lib"], 51 | "@ruby//engine:ruby": ["//:my__lib"], 52 | "//conditions:default": [], 53 | }), 54 | ) 55 | ``` 56 | 57 | Args: 58 | name: base name of resulting repositories, by default "ruby" 59 | version: a semver version of MRI, or a string like [interpreter type]-[version], or "system" 60 | version_file: .ruby-version or .tool-versions file to read version from 61 | msys2_packages: extra MSYS2 packages to install 62 | register: whether to register the resulting toolchains, should be False under bzlmod 63 | **kwargs: additional parameters to the downloader for this interpreter type 64 | """ 65 | proxy_repo_name = name + "_toolchains" 66 | if name not in native.existing_rules().values(): 67 | _rb_download( 68 | name = name, 69 | version = version, 70 | version_file = version_file, 71 | msys2_packages = msys2_packages, 72 | **kwargs 73 | ) 74 | _rb_toolchain_repository_proxy( 75 | name = proxy_repo_name, 76 | toolchain = "@{}//:toolchain".format(name), 77 | toolchain_type = "@rules_ruby//ruby:toolchain_type", 78 | ) 79 | if register: 80 | native.register_toolchains("@{}//:all".format(proxy_repo_name)) 81 | -------------------------------------------------------------------------------- /ruby/private/gem_push.bzl: -------------------------------------------------------------------------------- 1 | "Implementation details for rb_gem_push" 2 | 3 | load("//ruby/private:binary.bzl", "generate_rb_binary_script", BINARY_ATTRS = "ATTRS") 4 | load("//ruby/private:library.bzl", LIBRARY_ATTRS = "ATTRS") 5 | 6 | def _rb_gem_push_impl(ctx): 7 | env = {} 8 | java_toolchain = ctx.toolchains["@bazel_tools//tools/jdk:runtime_toolchain_type"] 9 | ruby_toolchain = ctx.toolchains["@rules_ruby//ruby:toolchain_type"] 10 | if ctx.attr.ruby != None: 11 | ruby_toolchain = ctx.attr.ruby[platform_common.ToolchainInfo] 12 | srcs = [ctx.file.gem] 13 | tools = [ruby_toolchain.gem] 14 | 15 | if ruby_toolchain.version.startswith("jruby"): 16 | env["JAVA_HOME"] = java_toolchain.java_runtime.java_home 17 | tools.extend(java_toolchain.java_runtime.files.to_list()) 18 | 19 | script = generate_rb_binary_script( 20 | ctx, 21 | binary = ruby_toolchain.gem, 22 | bundler = False, 23 | args = ["push", ctx.file.gem.short_path], 24 | ) 25 | 26 | runfiles = ctx.runfiles(srcs + tools) 27 | runfiles = runfiles.merge(ctx.attr._runfiles_library[DefaultInfo].default_runfiles) 28 | env.update(ctx.attr.env) 29 | 30 | return [ 31 | DefaultInfo( 32 | executable = script, 33 | runfiles = runfiles, 34 | ), 35 | RunEnvironmentInfo( 36 | environment = env, 37 | inherited_environment = ctx.attr.env_inherit, 38 | ), 39 | ] 40 | 41 | rb_gem_push = rule( 42 | _rb_gem_push_impl, 43 | executable = True, 44 | attrs = dict( 45 | LIBRARY_ATTRS, 46 | gem = attr.label( 47 | allow_single_file = [".gem"], 48 | mandatory = True, 49 | doc = """ 50 | Gem file to push to RubyGems. You would usually use an output of `rb_gem_build()` target here. 51 | """, 52 | ), 53 | env = BINARY_ATTRS["env"], 54 | env_inherit = BINARY_ATTRS["env_inherit"], 55 | ruby = BINARY_ATTRS["ruby"], 56 | _binary_cmd_tpl = BINARY_ATTRS["_binary_cmd_tpl"], 57 | _binary_sh_tpl = BINARY_ATTRS["_binary_sh_tpl"], 58 | _windows_constraint = BINARY_ATTRS["_windows_constraint"], 59 | _runfiles_library = BINARY_ATTRS["_runfiles_library"], 60 | ), 61 | toolchains = [ 62 | "@rules_ruby//ruby:toolchain_type", 63 | "@bazel_tools//tools/jdk:runtime_toolchain_type", 64 | ], 65 | doc = """ 66 | Pushes a built Ruby gem. 67 | 68 | Suppose you have the following Ruby gem, where `rb_library()` is used 69 | in `BUILD` files to define the packages for the gem and `rb_gem_build()` is used 70 | to build a Ruby gem package from the sources. 71 | 72 | ```output 73 | |-- BUILD 74 | |-- Gemfile 75 | |-- WORKSPACE 76 | |-- gem.gemspec 77 | `-- lib 78 | |-- BUILD 79 | |-- gem 80 | | |-- BUILD 81 | | |-- add.rb 82 | | |-- subtract.rb 83 | | `-- version.rb 84 | `-- gem.rb 85 | ``` 86 | 87 | You can now release the built `.gem` file to RubyGems by defining a target: 88 | 89 | `BUILD`: 90 | ```bazel 91 | load("@rules_ruby//ruby:defs.bzl", "rb_gem_build", "rb_gem_push") 92 | 93 | package(default_visibility = ["//:__subpackages__"]) 94 | 95 | rb_gem_build( 96 | name = "gem-build", 97 | gemspec = "gem.gemspec", 98 | deps = ["//lib:gem"], 99 | ) 100 | 101 | rb_gem_push( 102 | name = "gem-release", 103 | gem = ":gem-build", 104 | ) 105 | ``` 106 | 107 | ```output 108 | $ bazel run :gem-release 109 | ... 110 | Pushing gem to https://rubygems.org... 111 | Successfully registered gem: example (0.1.0) 112 | ``` 113 | """, 114 | ) 115 | -------------------------------------------------------------------------------- /examples/deep_gem/README.md: -------------------------------------------------------------------------------- 1 | # Deep Gem Example 2 | 3 | This example demonstrates how to define a Ruby gem that does not reside at the root of the 4 | Bazel workspace and how to reference files using standard Bazel package notation in the 5 | `MODULE.bazel` file. 6 | 7 | ## Overview 8 | 9 | Unlike typical Ruby gems that live at the workspace root, this example shows how to 10 | structure a gem in a subdirectory (`hello_world/`) while still being able to reference its 11 | files using Bazel's standard package notation. 12 | 13 | ## Key Features 14 | 15 | - **Non-root gem location**: The gem is located in `hello_world/` subdirectory, not at the 16 | workspace root 17 | - **Standard Bazel package notation**: Files are referenced using standard Bazel labels like 18 | `//hello_world/lib/hello_world:version.rb` 19 | - **Proper dependency management**: Demonstrates how to configure `bundle_fetch` with deep 20 | gem structure 21 | 22 | ## Project Structure 23 | 24 | ``` 25 | examples/deep_gem/ 26 | ├── MODULE.bazel # Workspace configuration with deep gem references 27 | ├── hello_world/ # Gem directory (not at root) 28 | │ ├── hello_world.gemspec 29 | │ ├── Gemfile 30 | │ ├── Gemfile.lock 31 | │ ├── lib/ 32 | │ │ ├── hello_world.rb 33 | │ │ └── hello_world/ 34 | │ │ ├── speaker.rb 35 | │ │ └── version.rb # Referenced as //hello_world/lib/hello_world:version.rb 36 | │ └── spec/ 37 | │ ├── BUILD.bazel 38 | │ ├── hello_world_spec.rb 39 | │ ├── speaker_spec.rb 40 | │ └── spec_helper.rb 41 | ``` 42 | 43 | ## Bazel Package Notation 44 | 45 | The key insight of this example is how to reference gem files using standard Bazel package 46 | notation in `MODULE.bazel`: 47 | 48 | ```starlark 49 | ruby.bundle_fetch( 50 | name = "bundle", 51 | srcs = [ 52 | "//hello_world:hello_world.gemspec", # Gemspec in subdirectory 53 | "//hello_world/lib/hello_world:version.rb", # Version file in nested structure 54 | ], 55 | gemfile = "//hello_world:Gemfile", 56 | gemfile_lock = "//hello_world:Gemfile.lock", 57 | ) 58 | ``` 59 | 60 | ### Package Reference Examples 61 | 62 | - `//hello_world:hello_world.gemspec` - References the gemspec file in the hello_world directory 63 | - `//hello_world/lib/hello_world:version.rb` - References the version.rb file in the nested 64 | lib/hello_world directory 65 | - `//hello_world:Gemfile` - References the Gemfile in the hello_world directory 66 | 67 | ## Running Tests 68 | 69 | The example includes comprehensive RSpec tests organized with proper separation of concerns: 70 | 71 | ```bash 72 | # Run all tests 73 | bazel test //... 74 | 75 | # Run specific test suites 76 | bazel test //hello_world/spec:hello_world_spec 77 | bazel test //hello_world/spec:speaker_spec 78 | 79 | # Run all spec tests 80 | bazel test //hello_world/spec:all 81 | ``` 82 | 83 | ## Benefits 84 | 85 | This approach provides several advantages: 86 | 87 | 1. **Workspace Organization**: Allows gems to be organized in subdirectories for better 88 | project structure 89 | 2. **Standard Bazel Conventions**: Uses familiar Bazel package notation for file references 90 | 3. **Scalability**: Enables multiple gems within a single workspace without conflicts 91 | 4. **Maintainability**: Clear separation of concerns with proper directory structure 92 | 93 | ## Usage 94 | 95 | This example serves as a template for projects that need to: 96 | 97 | - Define gems in subdirectories rather than at the workspace root 98 | - Reference gem files using standard Bazel package notation 99 | - Maintain proper dependency management with complex directory structures 100 | - Organize multiple gems within a single Bazel workspace 101 | -------------------------------------------------------------------------------- /ruby/private/test.bzl: -------------------------------------------------------------------------------- 1 | "Implementation details for rb_test" 2 | 3 | load("//ruby/private:binary.bzl", "ATTRS", "rb_binary_impl") 4 | load("//ruby/private:library.bzl", LIBRARY_ATTRS = "ATTRS") 5 | 6 | rb_test = rule( 7 | implementation = rb_binary_impl, 8 | executable = True, 9 | test = True, 10 | attrs = dict( 11 | ATTRS, 12 | srcs = LIBRARY_ATTRS["srcs"], 13 | data = LIBRARY_ATTRS["data"], 14 | deps = LIBRARY_ATTRS["deps"], 15 | ), 16 | toolchains = [ 17 | "@rules_ruby//ruby:toolchain_type", 18 | "@bazel_tools//tools/jdk:runtime_toolchain_type", 19 | ], 20 | doc = """ 21 | Runs a Ruby test. 22 | 23 | Suppose you have the following Ruby gem, where `rb_library()` is used 24 | in `BUILD` files to define the packages for the gem. 25 | 26 | ```output 27 | |-- BUILD 28 | |-- Gemfile 29 | |-- WORKSPACE 30 | |-- gem.gemspec 31 | |-- lib 32 | | |-- BUILD 33 | | |-- gem 34 | | | |-- BUILD 35 | | | |-- add.rb 36 | | | |-- subtract.rb 37 | | | `-- version.rb 38 | | `-- gem.rb 39 | `-- spec 40 | |-- BUILD 41 | |-- add_spec.rb 42 | |-- spec_helper.rb 43 | `-- subtract_spec.rb 44 | ``` 45 | 46 | You can run all tests inside `spec/` by defining individual targets: 47 | 48 | `spec/BUILD`: 49 | ```bazel 50 | load("@rules_ruby//ruby:defs.bzl", "rb_library", "rb_test") 51 | 52 | rb_library( 53 | name = "spec_helper", 54 | srcs = ["spec_helper.rb"], 55 | ) 56 | 57 | rb_test( 58 | name = "add", 59 | srcs = ["add_spec.rb"], 60 | args = ["spec/add_spec.rb"], 61 | main = "@bundle//bin:rspec", 62 | deps = [ 63 | ":spec_helper", 64 | "@bundle", 65 | ], 66 | ) 67 | 68 | rb_test( 69 | name = "subtract", 70 | srcs = ["subtract_spec.rb"], 71 | args = ["spec/subtract_spec.rb"], 72 | main = "@bundle//bin:rspec", 73 | deps = [ 74 | ":spec_helper", 75 | "@bundle", 76 | ], 77 | ) 78 | ``` 79 | 80 | ```output 81 | $ bazel test spec/... 82 | ... 83 | //spec:add PASSED in 0.4s 84 | //spec:subtract PASSED in 0.4s 85 | 86 | Executed 2 out of 2 tests: 2 tests pass. 87 | ``` 88 | 89 | Since `rb_test()` is a wrapper around `rb_binary()`, you can also use it to run 90 | a Ruby binary script available in Gemfile dependencies, by passing `main` 91 | argument with a path to a Bundler binary stub. 92 | 93 | `BUILD`: 94 | ```bazel 95 | load("@rules_ruby//ruby:defs.bzl", "rb_test") 96 | 97 | package(default_visibility = ["//:__subpackages__"]) 98 | 99 | rb_test( 100 | name = "rubocop", 101 | args = ["lib/"], 102 | main = "@bundle//bin:rubocop", 103 | tags = ["no-sandbox"], 104 | deps = [ 105 | "//lib:gem", 106 | "@bundle", 107 | ], 108 | ) 109 | ``` 110 | 111 | ```output 112 | $ bazel test :rubocop 113 | ... 114 | //:rubocop PASSED in 0.8s 115 | 116 | Executed 1 out of 1 test: 1 test passes. 117 | ``` 118 | 119 | Note that you can also `run` every test target passing extra arguments to 120 | the Ruby script. For example, you can re-use `:rubocop` target to perform autocorrect: 121 | 122 | ```output 123 | $ bazel run :rubocop -- --autocorrect-all 124 | ... 125 | Inspecting 11 files 126 | .C......... 127 | 128 | Offenses: 129 | 130 | gem.gemspec:1:1: C: [Corrected] Style/FrozenStringLiteralComment: Missing frozen string literal comment. 131 | root = File.expand_path(__dir__) 132 | ^ 133 | gem.gemspec:2:1: C: [Corrected] Layout/EmptyLineAfterMagicComment: Add an empty line after magic comments. 134 | root = File.expand_path(__dir__) 135 | ^ 136 | 137 | 11 files inspected, 2 offenses detected, 2 offenses corrected 138 | ``` 139 | """, 140 | ) 141 | -------------------------------------------------------------------------------- /examples/jekyll/MODULE.bazel: -------------------------------------------------------------------------------- 1 | "Bazel dependencies" 2 | 3 | bazel_dep(name = "bazel_skylib", version = "1.7.1", dev_dependency = True) 4 | bazel_dep(name = "aspect_bazel_lib", version = "2.9.4", dev_dependency = True) 5 | bazel_dep(name = "rules_ruby", version = "0.0.0", dev_dependency = True) 6 | bazel_dep(name = "rules_shell", version = "0.5.0", dev_dependency = True) 7 | 8 | local_path_override( 9 | module_name = "rules_ruby", 10 | path = "../..", 11 | ) 12 | 13 | ruby = use_extension("@rules_ruby//ruby:extensions.bzl", "ruby") 14 | ruby.toolchain( 15 | name = "ruby", 16 | version = "3.2.8", 17 | ) 18 | use_repo(ruby, "ruby") 19 | 20 | ruby.bundle_fetch( 21 | name = "bundle", 22 | gem_checksums = { 23 | "addressable-2.8.6": "798f6af3556641a7619bad1dce04cdb6eb44b0216a991b0396ea7339276f2b47", 24 | "colorator-1.1.0": "e2f85daf57af47d740db2a32191d1bdfb0f6503a0dfbc8327d0c9154d5ddfc38", 25 | "concurrent-ruby-1.2.3": "82fdd3f8a0816e28d513e637bb2b90a45d7b982bdf4f3a0511722d2e495801e2", 26 | "em-websocket-0.5.3": "f56a92bde4e6cb879256d58ee31f124181f68f8887bd14d53d5d9a292758c6a8", 27 | "eventmachine-1.2.7": "994016e42aa041477ba9cff45cbe50de2047f25dd418eba003e84f0d16560972", 28 | "ffi-1.16.3": "6d3242ff10c87271b0675c58d68d3f10148fabc2ad6da52a18123f06078871fb", 29 | "forwardable-extended-2.6.0": "1bec948c469bbddfadeb3bd90eb8c85f6e627a412a3e852acfd7eaedbac3ec97", 30 | "http_parser.rb-0.8.0": "5a0932f1fa82ce08a8516a2685d5a86031c000560f89946913c555a0697544be", 31 | "i18n-1.14.1": "9d03698903547c060928e70a9bc8b6b87fda674453cda918fc7ab80235ae4a61", 32 | "jekyll-3.9.4": "5d5e0b931c203ce129a16b2d2d5094a905a088749d24452fa8d82e1078315eff", 33 | "jekyll-feed-0.17.0": "689aab16c877949bb9e7a5c436de6278318a51ecb974792232fd94d8b3acfcc3", 34 | "jekyll-sass-converter-1.5.2": "53773669e414dc3bb070113befacb808576025a28cfa4a4accc682e90a9c1101", 35 | "jekyll-seo-tag-2.8.0": "3f2ed1916d56f14ebfa38e24acde9b7c946df70cb183af2cb5f0598f21ae6818", 36 | "jekyll-watch-2.2.1": "bc44ed43f5e0a552836245a54dbff3ea7421ecc2856707e8a1ee203a8387a7e1", 37 | "kramdown-2.4.0": "b62e5bcbd6ea20c7a6730ebbb2a107237856e14f29cebf5b10c876cc1a2481c5", 38 | "kramdown-parser-gfm-1.1.0": "fb39745516427d2988543bf01fc4cf0ab1149476382393e0e9c48592f6581729", 39 | "liquid-4.0.4": "4fcfebb1a045e47918388dbb7a0925e7c3893e58d2bd6c3b3c73ec17a2d8fdb3", 40 | "listen-3.8.0": "9679040ac6e7845ad9f19cf59ecde60861c78e2fae57a5c20fe35e94959b2f8f", 41 | "mercenary-0.3.6": "2a084b18f5692c86a633e185d5311ba6d11fc46c802eb414ae05368178078a82", 42 | "minima-2.5.1": "520e52bc631fb16cbb8100660f6caa44f97859e2fa7e397d508deb18739567be", 43 | "pathutil-0.16.2": "e43b74365631cab4f6d5e4228f812927efc9cb2c71e62976edcb252ee948d589", 44 | "public_suffix-5.0.4": "35cd648e0d21d06b8dce9331d19619538d1d898ba6d56a6f2258409d2526d1ae", 45 | "rb-fsevent-0.11.2": "43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe", 46 | "rb-inotify-0.10.1": "050062d4f31d307cca52c3f6a7f4b946df8de25fc4bd373e1a5142e41034a7ca", 47 | "rexml-3.2.6": "e0669a2d4e9f109951cb1fde723d8acd285425d81594a2ea929304af50282816", 48 | "rouge-3.30.0": "a3d353222aa72e49e2c86726c0bcfd719f82592f57d494474655f48e669eceb6", 49 | "safe_yaml-1.0.5": "a6ac2d64b7eb027bdeeca1851fe7e7af0d668e133e8a88066a0c6f7087d9f848", 50 | "sass-3.7.4": "808b0d39053aa69068df939e24671fe84fd5a9d3314486e1a1457d0934a4255d", 51 | "sass-listen-4.0.0": "ae9dcb76dd3e234329e5ba6e213f48e532c5a3e7b0b4d8a87f13aaca0cc18377", 52 | "wdm-0.1.1": "28406f5f236796019bea5b2a85e37cbcd229ec928c8b68261947a44eec15b474", 53 | "webrick-1.8.1": "19411ec6912911fd3df13559110127ea2badd0c035f7762873f58afc803e158f", 54 | }, 55 | gemfile = "//:Gemfile", 56 | gemfile_lock = "//:Gemfile.lock", 57 | ) 58 | use_repo(ruby, "bundle", "ruby_toolchains") 59 | 60 | register_toolchains("@ruby_toolchains//:all") 61 | -------------------------------------------------------------------------------- /ruby/private/providers.bzl: -------------------------------------------------------------------------------- 1 | "Providers for interoperability between rules" 2 | 3 | RubyFilesInfo = provider( 4 | "Provider for Ruby files", 5 | fields = { 6 | "binary": "Main Ruby script.", 7 | "transitive_data": "Transitive data files to add to runfiles.", 8 | "transitive_deps": "Transitive dependencies to get files from.", 9 | "transitive_srcs": "Transitive Ruby files.", 10 | "bundle_env": "Bundle environment variables (deprecated)", 11 | }, 12 | ) 13 | 14 | BundlerInfo = provider( 15 | "Provider for Bundler installation", 16 | fields = { 17 | "bin": "Binstubs path (BUNDLE_BIN).", 18 | "gemfile": "Gemfile path (BUNDLE_GEMFILE).", 19 | "path": "Bundle path (BUNDLE_PATH).", 20 | "env": "Bundle environment variables.", 21 | }, 22 | ) 23 | 24 | GemInfo = provider( 25 | "Provider for a packed Ruby gem", 26 | fields = { 27 | "name": "Gem name.", 28 | "version": "Gem version.", 29 | }, 30 | ) 31 | 32 | # https://bazel.build/rules/depsets 33 | 34 | def get_transitive_srcs(srcs, deps): 35 | """Obtain the source files for a target and its transitive dependencies. 36 | 37 | Args: 38 | srcs: a list of source files 39 | deps: a list of targets that are direct dependencies 40 | Returns: 41 | a collection of the transitive sources 42 | """ 43 | return depset( 44 | srcs, 45 | transitive = [dep[RubyFilesInfo].transitive_srcs for dep in deps], 46 | ) 47 | 48 | def get_transitive_data(data, deps): 49 | """Obtain the data files for a target and its transitive dependencies. 50 | 51 | Args: 52 | data: a list of data files 53 | deps: a list of targets that are direct dependencies 54 | Returns: 55 | a collection of the transitive data files 56 | """ 57 | return depset( 58 | data, 59 | transitive = [dep[RubyFilesInfo].transitive_data for dep in deps], 60 | ) 61 | 62 | def get_transitive_deps(deps): 63 | """Obtain the dependencies for a target and its transitive dependencies. 64 | 65 | Args: 66 | deps: a list of targets that are direct dependencies 67 | Returns: 68 | a collection of the transitive dependencies 69 | """ 70 | return depset( 71 | deps, 72 | transitive = [dep[RubyFilesInfo].transitive_deps for dep in deps], 73 | ) 74 | 75 | # https://bazel.build/extending/rules#runfiles 76 | def get_transitive_runfiles(runfiles, srcs, data, deps): 77 | """Obtain the runfiles for a target, its transitive data files and dependencies. 78 | 79 | Args: 80 | runfiles: the runfiles 81 | srcs: a list of source files 82 | data: a list of data files 83 | deps: a list of targets that are direct dependencies 84 | Returns: 85 | the runfiles 86 | """ 87 | transitive_runfiles = [] 88 | for targets in (srcs, data, deps): 89 | for target in targets: 90 | transitive_runfiles.append(target[DefaultInfo].default_runfiles) 91 | return runfiles.merge_all(transitive_runfiles) 92 | 93 | def get_bundle_env(envs, deps): 94 | """Obtain the BUNDLE_* environment variables for a target and its transitive dependencies. 95 | 96 | Args: 97 | envs: a list of environment variables 98 | deps: a list of targets that are direct dependencies 99 | Returns: 100 | a collection of the transitive environment variables 101 | """ 102 | bundle_env = {} 103 | 104 | transitive_deps = get_transitive_deps(deps).to_list() 105 | for dep in transitive_deps: 106 | bundle_env.update(dep[RubyFilesInfo].bundle_env) 107 | if BundlerInfo in dep: 108 | bundle_env.update(dep[BundlerInfo].env) 109 | 110 | for env in envs: 111 | if env.startswith("BUNDLE_"): 112 | bundle_env[env] = envs[env] 113 | return bundle_env 114 | -------------------------------------------------------------------------------- /docs/rails.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Public definition for `rails_test_factory`. 4 | 5 | 6 | 7 | ## rails_test_factory.new_system_test 8 | 9 |
10 | load("@rules_ruby//rails:rails_test_factory.bzl", "rails_test_factory")
11 | 
12 | rails_test_factory.new_system_test(test_package, application_system_test_case, default_includes,
13 |                                    default_size, tags)
14 | 
15 | 16 | Create a `rails_system_test` macro for a Rails application. 17 | 18 | **PARAMETERS** 19 | 20 | 21 | | Name | Description | Default Value | 22 | | :------------- | :------------- | :------------- | 23 | | test_package | Optional. The name of the package that contains the test helpers. For example, if the Rails app is rooted in the `foo` directory, the test package is typically `foo/test`. | `None` | 24 | | application_system_test_case | Optional. The label for the Rails application's `application_system_test_case.rb`. | `None` | 25 | | default_includes | Optional. A `list` of Ruby includes that should be part of the Ruby test invocation. | `None` | 26 | | default_size | Optional. The default test size for the tests created with the resulting macro. | `"large"` | 27 | | tags | Optional. A `list` of tags that are added to the test declaration. | `["no-sandbox"]` | 28 | 29 | **RETURNS** 30 | 31 | A Bazel macro function that defines Rails system test targets using the 32 | provided attributes. 33 | 34 | 35 | 36 | 37 | ## rails_test_factory.new_test 38 | 39 |
40 | load("@rules_ruby//rails:rails_test_factory.bzl", "rails_test_factory")
41 | 
42 | rails_test_factory.new_test(test_package, test_helper, default_includes, default_size, tags)
43 | 
44 | 45 | Create a `rails_test` macro for a Rails application. 46 | 47 | The resulting macro encapsulates the application-specific attributes for the 48 | resulting test target. 49 | 50 | 51 | **PARAMETERS** 52 | 53 | 54 | | Name | Description | Default Value | 55 | | :------------- | :------------- | :------------- | 56 | | test_package | Optional. The name of the package that contains the test helpers. For example, if the Rails app is rooted in the `foo` directory, the test package is typically `foo/test`. | `None` | 57 | | test_helper | The label for the Rails application's `test_helper.rb`. | `None` | 58 | | default_includes | Optional. A `list` of Ruby includes that should be part of the Ruby test invocation. | `None` | 59 | | default_size | Optional. The default test size for the tests created with the resulting macro. | `"small"` | 60 | | tags | Optional. A `list` of tags that are added to the test declaration. | `[]` | 61 | 62 | **RETURNS** 63 | 64 | A Bazel macro function that defines Rails test targets using the 65 | provided attributes. 66 | 67 | 68 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/environments/production.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # Code is not reloaded between requests. 7 | config.enable_reloading = false 8 | 9 | # Eager load code on boot for better performance and memory savings (ignored by Rake tasks). 10 | config.eager_load = true 11 | 12 | # Full error reports are disabled. 13 | config.consider_all_requests_local = false 14 | 15 | # Turn on fragment caching in view templates. 16 | config.action_controller.perform_caching = true 17 | 18 | # Cache assets for far-future expiry since they are all digest stamped. 19 | config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" } 20 | 21 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 22 | # config.asset_host = "http://assets.example.com" 23 | 24 | # Store uploaded files on the local file system (see config/storage.yml for options). 25 | config.active_storage.service = :local 26 | 27 | # Assume all access to the app is happening through a SSL-terminating reverse proxy. 28 | config.assume_ssl = true 29 | 30 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 31 | config.force_ssl = true 32 | 33 | # Skip http-to-https redirect for the default health check endpoint. 34 | # config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } } 35 | 36 | # Log to STDOUT with the current request id as a default log tag. 37 | config.log_tags = [ :request_id ] 38 | config.logger = ActiveSupport::TaggedLogging.logger(STDOUT) 39 | 40 | # Change to "debug" to log everything (including potentially personally-identifiable information!) 41 | config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") 42 | 43 | # Prevent health checks from clogging up the logs. 44 | config.silence_healthcheck_path = "/up" 45 | 46 | # Don't log any deprecations. 47 | config.active_support.report_deprecations = false 48 | 49 | # Replace the default in-process memory cache store with a durable alternative. 50 | # config.cache_store = :mem_cache_store 51 | 52 | # Replace the default in-process and non-durable queuing backend for Active Job. 53 | # config.active_job.queue_adapter = :resque 54 | 55 | # Ignore bad email addresses and do not raise email delivery errors. 56 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 57 | # config.action_mailer.raise_delivery_errors = false 58 | 59 | # Set host to be used by links generated in mailer templates. 60 | config.action_mailer.default_url_options = { host: "example.com" } 61 | 62 | # Specify outgoing SMTP server. Remember to add smtp/* credentials via rails credentials:edit. 63 | # config.action_mailer.smtp_settings = { 64 | # user_name: Rails.application.credentials.dig(:smtp, :user_name), 65 | # password: Rails.application.credentials.dig(:smtp, :password), 66 | # address: "smtp.example.com", 67 | # port: 587, 68 | # authentication: :plain 69 | # } 70 | 71 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 72 | # the I18n.default_locale when a translation cannot be found). 73 | config.i18n.fallbacks = true 74 | 75 | # Do not dump schema after migrations. 76 | config.active_record.dump_schema_after_migration = false 77 | 78 | # Only use :id for inspections in production. 79 | config.active_record.attributes_for_inspect = [ :id ] 80 | 81 | # Enable DNS rebinding protection and other `Host` header attacks. 82 | # config.hosts = [ 83 | # "example.com", # Allow requests from example.com 84 | # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` 85 | # ] 86 | # 87 | # Skip DNS rebinding protection for the default health check endpoint. 88 | # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } 89 | end 90 | -------------------------------------------------------------------------------- /ruby/private/library.bzl: -------------------------------------------------------------------------------- 1 | "Implementation details for rb_library" 2 | 3 | load( 4 | "//ruby/private:providers.bzl", 5 | "BundlerInfo", 6 | "RubyFilesInfo", 7 | "get_bundle_env", 8 | "get_transitive_data", 9 | "get_transitive_deps", 10 | "get_transitive_runfiles", 11 | "get_transitive_srcs", 12 | ) 13 | 14 | ATTRS = { 15 | "srcs": attr.label_list( 16 | allow_files = [".rb", ".gemspec", "Gemfile", "Gemfile.lock"], 17 | doc = "List of Ruby source files used to build the library.", 18 | ), 19 | "deps": attr.label_list( 20 | doc = "List of other Ruby libraries the target depends on.", 21 | ), 22 | "data": attr.label_list( 23 | allow_files = True, 24 | doc = "List of runtime dependencies needed by a program that depends on this library.", 25 | ), 26 | "bundle_env": attr.string_dict( 27 | default = {}, 28 | doc = "List of bundle environment variables to set when building the library.", 29 | ), 30 | } 31 | 32 | def _rb_library_impl(ctx): 33 | # TODO: avoid expanding the depset to a list, it may be expensive in a large graph 34 | transitive_data = get_transitive_data(ctx.files.data, ctx.attr.deps).to_list() 35 | transitive_deps = get_transitive_deps(ctx.attr.deps).to_list() 36 | transitive_srcs = get_transitive_srcs(ctx.files.srcs, ctx.attr.deps).to_list() 37 | 38 | runfiles = ctx.runfiles(transitive_srcs + transitive_data) 39 | runfiles = get_transitive_runfiles(runfiles, ctx.attr.srcs, ctx.attr.deps, ctx.attr.data) 40 | 41 | providers = [ 42 | DefaultInfo( 43 | files = depset(transitive_srcs + transitive_data), 44 | runfiles = runfiles, 45 | ), 46 | RubyFilesInfo( 47 | binary = None, 48 | transitive_data = depset(transitive_data), 49 | transitive_deps = depset(transitive_deps), 50 | transitive_srcs = depset(transitive_srcs), 51 | bundle_env = get_bundle_env(ctx.attr.bundle_env, ctx.attr.deps), 52 | ), 53 | ] 54 | 55 | for dep in transitive_deps: 56 | if BundlerInfo in dep: 57 | providers.append(dep[BundlerInfo]) 58 | break 59 | 60 | return providers 61 | 62 | rb_library = rule( 63 | implementation = _rb_library_impl, 64 | attrs = ATTRS, 65 | doc = """ 66 | Defines a Ruby library. 67 | 68 | Suppose you have the following Ruby gem: 69 | 70 | ```output 71 | |-- BUILD 72 | |-- Gemfile 73 | |-- WORKSPACE 74 | |-- gem.gemspec 75 | `-- lib 76 | |-- BUILD 77 | |-- gem 78 | | |-- BUILD 79 | | |-- add.rb 80 | | |-- subtract.rb 81 | | `-- version.rb 82 | `-- gem.rb 83 | ``` 84 | 85 | You can define packages for the gem source files: 86 | 87 | `BUILD`: 88 | ```bazel 89 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 90 | 91 | package(default_visibility = ["//:__subpackages__"]) 92 | 93 | rb_library( 94 | name = "gem", 95 | deps = ["//lib:gem"], 96 | ) 97 | ``` 98 | 99 | `lib/BUILD`: 100 | ```bazel 101 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 102 | 103 | package(default_visibility = ["//:__subpackages__"]) 104 | 105 | rb_library( 106 | name = "gem", 107 | srcs = ["gem.rb"], 108 | deps = [ 109 | "//lib/gem:add", 110 | "//lib/gem:subtract", 111 | "//lib/gem:version", 112 | ], 113 | ) 114 | ``` 115 | 116 | `lib/gem/BUILD`: 117 | ```bazel 118 | load("@rules_ruby//ruby:defs.bzl", "rb_library") 119 | 120 | package(default_visibility = ["//:__subpackages__"]) 121 | 122 | rb_library( 123 | name = "add", 124 | srcs = ["add.rb"], 125 | ) 126 | 127 | rb_library( 128 | name = "subtract", 129 | srcs = ["subtract.rb"], 130 | ) 131 | 132 | rb_library( 133 | name = "version", 134 | srcs = ["version.rb"], 135 | ) 136 | ``` 137 | 138 | Once the packages are defined, you can use them in other targets 139 | such as `rb_gem_build()` to build a Ruby gem. See examples of 140 | using other rules. 141 | """, 142 | ) 143 | -------------------------------------------------------------------------------- /examples/rails/people_tracker/config/deploy.yml: -------------------------------------------------------------------------------- 1 | # Name of your application. Used to uniquely configure containers. 2 | service: people_tracker 3 | 4 | # Name of the container image. 5 | image: your-user/people_tracker 6 | 7 | # Deploy to these servers. 8 | servers: 9 | web: 10 | - 192.168.0.1 11 | # job: 12 | # hosts: 13 | # - 192.168.0.1 14 | # cmd: bin/jobs 15 | 16 | # Enable SSL auto certification via Let's Encrypt and allow for multiple apps on a single web server. 17 | # Remove this section when using multiple web servers and ensure you terminate SSL at your load balancer. 18 | # 19 | # Note: If using Cloudflare, set encryption mode in SSL/TLS setting to "Full" to enable CF-to-app encryption. 20 | proxy: 21 | ssl: true 22 | host: app.example.com 23 | 24 | # Credentials for your image host. 25 | registry: 26 | # Specify the registry server, if you're not using Docker Hub 27 | # server: registry.digitalocean.com / ghcr.io / ... 28 | username: your-user 29 | 30 | # Always use an access token rather than real password when possible. 31 | password: 32 | - KAMAL_REGISTRY_PASSWORD 33 | 34 | # Inject ENV variables into containers (secrets come from .kamal/secrets). 35 | env: 36 | secret: 37 | - RAILS_MASTER_KEY 38 | clear: 39 | # Run the Solid Queue Supervisor inside the web server's Puma process to do jobs. 40 | # When you start using multiple servers, you should split out job processing to a dedicated machine. 41 | SOLID_QUEUE_IN_PUMA: true 42 | 43 | # Set number of processes dedicated to Solid Queue (default: 1) 44 | # JOB_CONCURRENCY: 3 45 | 46 | # Set number of cores available to the application on each server (default: 1). 47 | # WEB_CONCURRENCY: 2 48 | 49 | # Match this to any external database server to configure Active Record correctly 50 | # Use people_tracker-db for a db accessory server on same machine via local kamal docker network. 51 | # DB_HOST: 192.168.0.2 52 | 53 | # Log everything from Rails 54 | # RAILS_LOG_LEVEL: debug 55 | 56 | # Aliases are triggered with "bin/kamal ". You can overwrite arguments on invocation: 57 | # "bin/kamal logs -r job" will tail logs from the first server in the job section. 58 | aliases: 59 | console: app exec --interactive --reuse "bin/rails console" 60 | shell: app exec --interactive --reuse "bash" 61 | logs: app logs -f 62 | dbc: app exec --interactive --reuse "bin/rails dbconsole" 63 | 64 | # Use a persistent storage volume for sqlite database files and local Active Storage files. 65 | # Recommended to change this to a mounted volume path that is backed up off server. 66 | volumes: 67 | - "people_tracker_storage:/rails/storage" 68 | 69 | # Bridge fingerprinted assets, like JS and CSS, between versions to avoid 70 | # hitting 404 on in-flight requests. Combines all files from new and old 71 | # version inside the asset_path. 72 | asset_path: /rails/public/assets 73 | 74 | # Configure the image builder. 75 | builder: 76 | arch: amd64 77 | 78 | # # Build image via remote server (useful for faster amd64 builds on arm64 computers) 79 | # remote: ssh://docker@docker-builder-server 80 | # 81 | # # Pass arguments and secrets to the Docker build process 82 | # args: 83 | # RUBY_VERSION: ruby-3.4.5 84 | # secrets: 85 | # - GITHUB_TOKEN 86 | # - RAILS_MASTER_KEY 87 | 88 | # Use a different ssh user than root 89 | # ssh: 90 | # user: app 91 | 92 | # Use accessory services (secrets come from .kamal/secrets). 93 | # accessories: 94 | # db: 95 | # image: mysql:8.0 96 | # host: 192.168.0.2 97 | # # Change to 3306 to expose port to the world instead of just local network. 98 | # port: "127.0.0.1:3306:3306" 99 | # env: 100 | # clear: 101 | # MYSQL_ROOT_HOST: '%' 102 | # secret: 103 | # - MYSQL_ROOT_PASSWORD 104 | # files: 105 | # - config/mysql/production.cnf:/etc/mysql/my.cnf 106 | # - db/production.sql:/docker-entrypoint-initdb.d/setup.sql 107 | # directories: 108 | # - data:/var/lib/mysql 109 | # redis: 110 | # image: redis:7.0 111 | # host: 192.168.0.2 112 | # port: 6379 113 | # directories: 114 | # - data:/data 115 | -------------------------------------------------------------------------------- /examples/gem/WORKSPACE: -------------------------------------------------------------------------------- 1 | local_repository( 2 | name = "rules_ruby", 3 | path = "../..", 4 | ) 5 | 6 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 7 | 8 | http_archive( 9 | name = "bazel_skylib", 10 | sha256 = "66ffd9315665bfaafc96b52278f57c7e2dd09f5ede279ea6d39b2be471e7e3aa", 11 | urls = [ 12 | "https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.2/bazel-skylib-1.4.2.tar.gz", 13 | ], 14 | ) 15 | 16 | load("@rules_ruby//ruby:deps.bzl", "rb_bundle_fetch", "rb_register_toolchains") 17 | 18 | rb_register_toolchains( 19 | version_file = "//:.ruby-version", 20 | ) 21 | 22 | rb_bundle_fetch( 23 | name = "bundle", 24 | srcs = [ 25 | "//:gem.gemspec", 26 | "//:lib/gem/version.rb", 27 | ], 28 | env = { 29 | "BUNDLE_BUILD__FOO": "bar", 30 | }, 31 | gem_checksums = { 32 | "ast-2.4.2": "1e280232e6a33754cde542bc5ef85520b74db2aac73ec14acef453784447cc12", 33 | "concurrent-ruby-1.3.5": "813b3e37aca6df2a21a3b9f1d497f8cbab24a2b94cab325bffe65ee0f6cbebc6", 34 | "date-3.4.1": "bf268e14ef7158009bfeaec40b5fa3c7271906e88b196d958a89d4b408abe64f", 35 | "date-3.4.1-java": "74740d914c65a922a15657c25ff0e203c16f1d0f7aa910a9ebed712afe9819c4", 36 | "debug-1.10.0": "11e28ca74875979e612444104f3972bd5ffb9e79179907d7ad46dba44bd2e7a4", 37 | "diff-lcs-1.5.1": "273223dfb40685548436d32b4733aa67351769c7dea621da7d9dd4813e63ddfe", 38 | "i18n-1.14.7": "ceba573f8138ff2c0915427f1fc5bdf4aa3ab8ae88c8ce255eb3ecf0a11a5d0f", 39 | "io-console-0.8.0": "cd6a9facbc69871d69b2cb8b926fc6ea7ef06f06e505e81a64f14a470fddefa2", 40 | "io-console-0.8.0-java": "3cc6fd5c66e587145c1fdf8dc40c2e3d851e90722a5d0cc3f38da352f06fe1bd", 41 | "irb-1.15.1": "d9bca745ac4207a8b728a52b98b766ca909b86ff1a504bcde3d6f8c84faae890", 42 | "jar-dependencies-0.5.3": "f6a7a0bf3f917252461e2a87f9f54005424502f7dc9ef912d8b9540658dbd0bc", 43 | "json-2.9.1": "d2bdef4644052fad91c1785d48263756fe32fcac08b96a20bb15840e96550d11", 44 | "json-2.9.1-java": "88de8c79b54fee6ae1b4854bc48b8d7089f524cbacaf4596df24f86b10896ee8", 45 | "language_server-protocol-3.17.0.3": "3d5c58c02f44a20d972957a9febe386d7e7468ab3900ce6bd2b563dd910c6b3f", 46 | "parallel-1.26.3": "d86babb7a2b814be9f4b81587bf0b6ce2da7d45969fab24d8ae4bf2bb4d4c7ef", 47 | "parser-3.3.7.0": "7449011771e3e7881297859b849de26a6f4fccd515bece9520a87e7d2116119b", 48 | "pp-0.6.2": "947ec3120c6f92195f8ee8aa25a7b2c5297bb106d83b41baa02983686577b6ff", 49 | "prettyprint-0.2.0": "2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193", 50 | "psych-5.2.3": "84a54bb952d14604fea22d99938348814678782f58b12648fcdfa4d2fce859ee", 51 | "psych-5.2.3-java": "3e5425b9e8a2f41cc2707d5ef14fdc1ae908abbafb12fe45727bd63900056585", 52 | "racc-1.8.1": "4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f", 53 | "racc-1.8.1-java": "54f2e6d1e1b91c154013277d986f52a90e5ececbe91465d29172e49342732b98", 54 | "rainbow-3.1.1": "039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a", 55 | "rake-13.2.1": "46cb38dae65d7d74b6020a4ac9d48afed8eb8149c040eccf0523bec91907059d", 56 | "rdoc-6.11.0": "bec66fb9b019be64f7ba7d2cd2aecb283a3a01fef23a95b33e2349c6d1aa0040", 57 | "regexp_parser-2.10.0": "cb6f0ddde88772cd64bff1dbbf68df66d376043fe2e66a9ef77fcb1b0c548c61", 58 | "reline-0.6.0": "57620375dcbe56ec09bac7192bfb7460c716bbf0054dc94345ecaa5438e539d2", 59 | "rspec-3.13.0": "d490914ac1d5a5a64a0e1400c1d54ddd2a501324d703b8cfe83f458337bab993", 60 | "rspec-core-3.13.2": "94fbda6e4738e478f1c7532b7cc241272fcdc8b9eac03a97338b1122e4573300", 61 | "rspec-expectations-3.13.3": "0e6b5af59b900147698ea0ff80456c4f2e69cac4394fbd392fbd1ca561f66c58", 62 | "rspec-mocks-3.13.2": "2327335def0e1665325a9b617e3af9ae20272741d80ac550336309a7c59abdef", 63 | "rspec-support-3.13.2": "cea3a2463fd9b84b9dcc9685efd80ea701aa8f7b3decb3b3ce795ed67737dbec", 64 | "rubocop-1.71.0": "e19679efd447346ac476122313d3788ae23c38214790bcf660e984c747608bf0", 65 | "rubocop-ast-1.37.0": "9513ac88aaf113d04b52912533ffe46475de1362d4aa41141b51b2455827c080", 66 | "ruby-progressbar-1.13.0": "80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33", 67 | "stringio-3.1.2": "204f1828f85cdb39d57cac4abc6dc44b04505a223f131587f2e20ae3729ba131", 68 | "unicode-display_width-3.1.4": "8caf2af1c0f2f07ec89ef9e18c7d88c2790e217c482bfc78aaa65eadd5415ac1", 69 | "unicode-emoji-4.0.4": "2c2c4ef7f353e5809497126285a50b23056cc6e61b64433764a35eff6c36532a", 70 | }, 71 | gemfile = "//:Gemfile", 72 | gemfile_lock = "//:Gemfile.lock", 73 | ) 74 | -------------------------------------------------------------------------------- /examples/gem/MODULE.bazel: -------------------------------------------------------------------------------- 1 | "Bazel dependencies" 2 | 3 | bazel_dep(name = "bazel_skylib", version = "1.5.0", dev_dependency = True) 4 | bazel_dep(name = "aspect_bazel_lib", version = "2.19.4", dev_dependency = True) 5 | bazel_dep(name = "rules_ruby", version = "0.0.0", dev_dependency = True) 6 | bazel_dep(name = "rules_shell", version = "0.4.0", dev_dependency = True) 7 | 8 | local_path_override( 9 | module_name = "rules_ruby", 10 | path = "../..", 11 | ) 12 | 13 | ruby = use_extension("@rules_ruby//ruby:extensions.bzl", "ruby") 14 | ruby.toolchain( 15 | name = "ruby", 16 | version_file = "//:.ruby-version", 17 | ) 18 | use_repo(ruby, "ruby") 19 | 20 | ruby.bundle_fetch( 21 | name = "bundle", 22 | srcs = [ 23 | "//:gem.gemspec", 24 | "//:lib/gem/version.rb", 25 | ], 26 | env = { 27 | "BUNDLE_BUILD__FOO": "bar", 28 | }, 29 | gem_checksums = { 30 | "ast-2.4.2": "1e280232e6a33754cde542bc5ef85520b74db2aac73ec14acef453784447cc12", 31 | "concurrent-ruby-1.3.5": "813b3e37aca6df2a21a3b9f1d497f8cbab24a2b94cab325bffe65ee0f6cbebc6", 32 | "date-3.4.1": "bf268e14ef7158009bfeaec40b5fa3c7271906e88b196d958a89d4b408abe64f", 33 | "date-3.4.1-java": "74740d914c65a922a15657c25ff0e203c16f1d0f7aa910a9ebed712afe9819c4", 34 | "debug-1.10.0": "11e28ca74875979e612444104f3972bd5ffb9e79179907d7ad46dba44bd2e7a4", 35 | "diff-lcs-1.5.1": "273223dfb40685548436d32b4733aa67351769c7dea621da7d9dd4813e63ddfe", 36 | "i18n-1.14.7": "ceba573f8138ff2c0915427f1fc5bdf4aa3ab8ae88c8ce255eb3ecf0a11a5d0f", 37 | "io-console-0.8.0": "cd6a9facbc69871d69b2cb8b926fc6ea7ef06f06e505e81a64f14a470fddefa2", 38 | "io-console-0.8.0-java": "3cc6fd5c66e587145c1fdf8dc40c2e3d851e90722a5d0cc3f38da352f06fe1bd", 39 | "irb-1.15.1": "d9bca745ac4207a8b728a52b98b766ca909b86ff1a504bcde3d6f8c84faae890", 40 | "jar-dependencies-0.5.3": "f6a7a0bf3f917252461e2a87f9f54005424502f7dc9ef912d8b9540658dbd0bc", 41 | "json-2.9.1": "d2bdef4644052fad91c1785d48263756fe32fcac08b96a20bb15840e96550d11", 42 | "json-2.9.1-java": "88de8c79b54fee6ae1b4854bc48b8d7089f524cbacaf4596df24f86b10896ee8", 43 | "language_server-protocol-3.17.0.3": "3d5c58c02f44a20d972957a9febe386d7e7468ab3900ce6bd2b563dd910c6b3f", 44 | "parallel-1.26.3": "d86babb7a2b814be9f4b81587bf0b6ce2da7d45969fab24d8ae4bf2bb4d4c7ef", 45 | "parser-3.3.7.0": "7449011771e3e7881297859b849de26a6f4fccd515bece9520a87e7d2116119b", 46 | "pp-0.6.2": "947ec3120c6f92195f8ee8aa25a7b2c5297bb106d83b41baa02983686577b6ff", 47 | "prettyprint-0.2.0": "2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193", 48 | "psych-5.2.3": "84a54bb952d14604fea22d99938348814678782f58b12648fcdfa4d2fce859ee", 49 | "psych-5.2.3-java": "3e5425b9e8a2f41cc2707d5ef14fdc1ae908abbafb12fe45727bd63900056585", 50 | "racc-1.8.1": "4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f", 51 | "racc-1.8.1-java": "54f2e6d1e1b91c154013277d986f52a90e5ececbe91465d29172e49342732b98", 52 | "rainbow-3.1.1": "039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a", 53 | "rake-13.2.1": "46cb38dae65d7d74b6020a4ac9d48afed8eb8149c040eccf0523bec91907059d", 54 | "rdoc-6.11.0": "bec66fb9b019be64f7ba7d2cd2aecb283a3a01fef23a95b33e2349c6d1aa0040", 55 | "regexp_parser-2.10.0": "cb6f0ddde88772cd64bff1dbbf68df66d376043fe2e66a9ef77fcb1b0c548c61", 56 | "reline-0.6.0": "57620375dcbe56ec09bac7192bfb7460c716bbf0054dc94345ecaa5438e539d2", 57 | "rspec-3.13.0": "d490914ac1d5a5a64a0e1400c1d54ddd2a501324d703b8cfe83f458337bab993", 58 | "rspec-core-3.13.2": "94fbda6e4738e478f1c7532b7cc241272fcdc8b9eac03a97338b1122e4573300", 59 | "rspec-expectations-3.13.3": "0e6b5af59b900147698ea0ff80456c4f2e69cac4394fbd392fbd1ca561f66c58", 60 | "rspec-mocks-3.13.2": "2327335def0e1665325a9b617e3af9ae20272741d80ac550336309a7c59abdef", 61 | "rspec-support-3.13.2": "cea3a2463fd9b84b9dcc9685efd80ea701aa8f7b3decb3b3ce795ed67737dbec", 62 | "rubocop-1.71.0": "e19679efd447346ac476122313d3788ae23c38214790bcf660e984c747608bf0", 63 | "rubocop-ast-1.37.0": "9513ac88aaf113d04b52912533ffe46475de1362d4aa41141b51b2455827c080", 64 | "ruby-progressbar-1.13.0": "80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33", 65 | "stringio-3.1.2": "204f1828f85cdb39d57cac4abc6dc44b04505a223f131587f2e20ae3729ba131", 66 | "unicode-display_width-3.1.4": "8caf2af1c0f2f07ec89ef9e18c7d88c2790e217c482bfc78aaa65eadd5415ac1", 67 | "unicode-emoji-4.0.4": "2c2c4ef7f353e5809497126285a50b23056cc6e61b64433764a35eff6c36532a", 68 | }, 69 | gemfile = "//:Gemfile", 70 | gemfile_lock = "//:Gemfile.lock", 71 | ) 72 | use_repo(ruby, "bundle", "ruby_toolchains") 73 | 74 | register_toolchains("@ruby_toolchains//:all") 75 | -------------------------------------------------------------------------------- /ruby/private/gem_install.bzl: -------------------------------------------------------------------------------- 1 | "Implementation details for rb_gem_install" 2 | 3 | load("//ruby/private:providers.bzl", "GemInfo") 4 | load( 5 | "//ruby/private:utils.bzl", 6 | _convert_env_to_script = "convert_env_to_script", 7 | _is_windows = "is_windows", 8 | _normalize_path = "normalize_path", 9 | ) 10 | 11 | def _rb_gem_install_impl(ctx): 12 | gem = ctx.file.gem 13 | install_dir = ctx.actions.declare_directory(gem.basename[:-4]) 14 | toolchain = ctx.toolchains["@rules_ruby//ruby:toolchain_type"] 15 | if ctx.attr.ruby != None: 16 | toolchain = ctx.attr.ruby[platform_common.ToolchainInfo] 17 | 18 | env = {} 19 | env.update(toolchain.env) 20 | 21 | tools = [] 22 | tools.extend(toolchain.files) 23 | 24 | if toolchain.version.startswith("jruby"): 25 | java_toolchain = ctx.toolchains["@bazel_tools//tools/jdk:runtime_toolchain_type"] 26 | tools.extend(java_toolchain.java_runtime.files.to_list()) 27 | env.update({"JAVA_HOME": java_toolchain.java_runtime.java_home}) 28 | 29 | if _is_windows(ctx): 30 | gem_install = ctx.actions.declare_file("gem_install_{}.cmd".format(ctx.label.name)) 31 | template = ctx.file._gem_install_cmd_tpl 32 | env.update({"PATH": _normalize_path(ctx, toolchain.ruby.dirname) + ";%PATH%"}) 33 | else: 34 | gem_install = ctx.actions.declare_file("gem_install_{}.sh".format(ctx.label.name)) 35 | template = ctx.file._gem_install_sh_tpl 36 | env.update({"PATH": "%s:$PATH" % toolchain.ruby.dirname}) 37 | 38 | ctx.actions.expand_template( 39 | template = template, 40 | output = gem_install, 41 | substitutions = { 42 | "{env}": _convert_env_to_script(ctx, env), 43 | "{gem_binary}": _normalize_path(ctx, toolchain.gem.path), 44 | "{gem}": gem.path, 45 | "{install_dir}": install_dir.path, 46 | }, 47 | ) 48 | 49 | name, _, version = ctx.attr.name.rpartition("-") 50 | ctx.actions.run( 51 | executable = gem_install, 52 | inputs = depset([gem, gem_install]), 53 | outputs = [install_dir], 54 | mnemonic = "GemInstall", 55 | progress_message = "Installing %{input} (%{label})", 56 | tools = tools, 57 | use_default_shell_env = True, 58 | ) 59 | 60 | return [ 61 | DefaultInfo(files = depset([gem, install_dir])), 62 | GemInfo( 63 | name = name, 64 | version = version, 65 | ), 66 | ] 67 | 68 | rb_gem_install = rule( 69 | _rb_gem_install_impl, 70 | attrs = { 71 | "gem": attr.label( 72 | allow_single_file = [".gem"], 73 | mandatory = True, 74 | doc = "Gem file to install.", 75 | ), 76 | "ruby": attr.label( 77 | doc = "Override Ruby toolchain to use when installing the gem.", 78 | providers = [platform_common.ToolchainInfo], 79 | ), 80 | "_gem_install_cmd_tpl": attr.label( 81 | allow_single_file = True, 82 | default = "@rules_ruby//ruby/private/gem_install:gem_install.cmd.tpl", 83 | ), 84 | "_gem_install_sh_tpl": attr.label( 85 | allow_single_file = True, 86 | default = "@rules_ruby//ruby/private/gem_install:gem_install.sh.tpl", 87 | ), 88 | "_windows_constraint": attr.label( 89 | default = "@platforms//os:windows", 90 | ), 91 | }, 92 | toolchains = [ 93 | "@rules_ruby//ruby:toolchain_type", 94 | "@bazel_tools//tools/jdk:runtime_toolchain_type", 95 | ], 96 | doc = """ 97 | Installs a built Ruby gem. 98 | 99 | Suppose you have the following Ruby gem, where `rb_library()` is used 100 | in `BUILD` files to define the packages for the gem and `rb_gem_build()` is used 101 | to build a Ruby gem package from the sources. 102 | 103 | ```output 104 | |-- BUILD 105 | |-- Gemfile 106 | |-- WORKSPACE 107 | |-- gem.gemspec 108 | `-- lib 109 | |-- BUILD 110 | |-- gem 111 | | |-- BUILD 112 | | |-- add.rb 113 | | |-- subtract.rb 114 | | `-- version.rb 115 | `-- gem.rb 116 | ``` 117 | 118 | You can now install the built `.gem` file by defining a target: 119 | 120 | `BUILD`: 121 | ```bazel 122 | load("@rules_ruby//ruby:defs.bzl", "rb_gem_build", "rb_gem_install") 123 | 124 | package(default_visibility = ["//:__subpackages__"]) 125 | 126 | rb_gem_build( 127 | name = "gem-build", 128 | gemspec = "gem.gemspec", 129 | deps = ["//lib:gem"], 130 | ) 131 | 132 | rb_gem_install( 133 | name = "gem-install", 134 | gem = ":gem-build", 135 | ) 136 | ``` 137 | 138 | ```output 139 | $ bazel build :gem-install 140 | ... 141 | Successfully installed example-0.1.0 142 | 1 gem installed 143 | ... 144 | ``` 145 | """, 146 | ) 147 | --------------------------------------------------------------------------------