Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support bzlmod #17

Merged
merged 6 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .bcr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Bazel Central Registry

When the ruleset is released, we want it to be published to the
Bazel Central Registry automatically:
<https://registry.bazel.build>

This folder contains configuration files to automate the publish step.
See <https://github.com/bazel-contrib/publish-to-bcr/blob/main/templates/README.md>
for authoritative documentation about these files.
6 changes: 6 additions & 0 deletions .bcr/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# See https://github.com/bazel-contrib/publish-to-bcr#a-note-on-release-automation
# Our releases are created by github actions based on pushing a tag, so they don't have an author.
# This person's fork of BCR will be used to originate pull requests.
fixedReleaser:
alexeagle marked this conversation as resolved.
Show resolved Hide resolved
login: alexeagle
email: [email protected]
12 changes: 12 additions & 0 deletions .bcr/metadata.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"homepage": "https://github.com/p0deje/rules_ruby",
"maintainers": [
{
"github": "p0deje",
"name": "Alex Rodionov"
}
],
"repository": ["github:p0deje/rules_ruby"],
"versions": [],
"yanked_versions": {}
}
10 changes: 10 additions & 0 deletions .bcr/presubmit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
bcr_test_module:
module_path: "examples/gem"
matrix:
platform: ["debian10", "macos", "ubuntu2004", "windows"]
tasks:
run_tests:
name: "Run test module"
platform: ${{ platform }}
test_targets:
- "//..."
alexeagle marked this conversation as resolved.
Show resolved Hide resolved
5 changes: 5 additions & 0 deletions .bcr/source.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"integrity": "**leave this alone**",
"strip_prefix": "{REPO}-{VERSION}",
"url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/{REPO}-{TAG}.tar.gz"
}
21 changes: 16 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
- ubuntu-latest
- macos-latest
- windows-latest
bzlmodEnabled: [true, false]
exclude:
- os: windows-latest
ruby: 3.3.0-preview3
Expand All @@ -39,11 +40,21 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: p0deje/[email protected]
- run: echo 'RUBY_VERSION = "${{ matrix.ruby }}"' > ruby_version.bzl
- run: bazel build ...
- run: bazel run lib/gem:add-numbers 2
- run: bazel run lib/gem:print-version
- run: bazel test ...

- name: Set bzlmod flag
# Store the --enable_bzlmod flag that we add to the test command below
# only when we're running bzlmod in our test matrix.
id: set_bzlmod_flag
if: matrix.bzlmodEnabled
run: echo "bzlmod_flag=--enable_bzlmod" >> $GITHUB_OUTPUT

- id: set_ruby_version
run: echo 'RUBY_VERSION = "${{ matrix.ruby }}"' > ruby_version.bzl

- run: bazel test ${{ steps.set_bzlmod_flag.outputs.bzlmod_flag }} //...
- run: bazel run ${{ steps.set_bzlmod_flag.outputs.bzlmod_flag }} lib/gem:add-numbers 2
- run: bazel run ${{ steps.set_bzlmod_flag.outputs.bzlmod_flag }} lib/gem:print-version

- if: failure() && runner.debug == '1'
uses: mxschmitt/action-tmate@v3

Expand Down
16 changes: 16 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"Define the Bazel module published to the Bazel Central Registry"

module(
name = "rules_ruby",
# NB: this version will be replaced after a release by the Publish to BCR app
version = "0.0.0",
compatibility_level = 1,
)

# Lower-bound dependency versions.
# These should NOT be increased unless needed, as bumping our lower-bound may change
# the versions resolved in users repositories.
bazel_dep(name = "bazel_skylib", version = "1.3.0")
bazel_dep(name = "platforms", version = "0.0.5")

# TODO: should we register any toolchain by default?
alexeagle marked this conversation as resolved.
Show resolved Hide resolved
52 changes: 9 additions & 43 deletions docs/repository_rules.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions examples/gem/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"Bazel dependencies"

bazel_dep(name = "bazel_skylib", version = "1.5.0", dev_dependency = True)
bazel_dep(name = "rules_ruby", version = "0.0.0", dev_dependency = True)
local_path_override(
module_name = "rules_ruby",
path = "../..",
)

ruby = use_extension("@rules_ruby//ruby:extensions.bzl", "ruby")
ruby.toolchain(
name = "rules_ruby",
version = "3.2.1",
)
use_repo(ruby, "rules_ruby_dist")
ruby.bundle(
name = "bundle",
srcs = [
"//:Gemfile.lock",
"//:gem.gemspec",
"//:lib/gem/version.rb",
],
env = {
"BUNDLE_BUILD__FOO": "bar",
},
gemfile = "//:Gemfile",
toolchain = "@rules_ruby_dist//:BUILD",
)
use_repo(ruby, "bundle", "rules_ruby_toolchains")

register_toolchains("@rules_ruby_toolchains//:all")
2 changes: 2 additions & 0 deletions examples/gem/WORKSPACE.bzlmod
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Marker file that this is the root of a Bazel workspace.
# This file replaces WORKSPACE.bazel under --enable_bzlmod.
7 changes: 6 additions & 1 deletion ruby/deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@
load("//ruby/private:bundle.bzl", _rb_bundle = "rb_bundle")
load("//ruby/private:download.bzl", _rb_register_toolchains = "rb_register_toolchains")

rb_bundle = _rb_bundle
def rb_bundle(toolchain = "@rules_ruby_dist//:BUILD", **kwargs):
_rb_bundle(
toolchain = toolchain,
**kwargs
)

rb_register_toolchains = _rb_register_toolchains
61 changes: 61 additions & 0 deletions ruby/extensions.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"Module extensions used by bzlmod"

load("//ruby/private:download.bzl", "DEFAULT_RUBY_REPOSITORY")
load(":deps.bzl", "rb_bundle", "rb_register_toolchains")

ruby_bundle = tag_class(attrs = {
"name": attr.string(doc = "Resulting repository name for the bundle"),
"srcs": attr.label_list(),
"env": attr.string_dict(),
"gemfile": attr.label(),
"toolchain": attr.label(),
})

ruby_toolchain = tag_class(attrs = {
"name": attr.string(doc = "Base name for generated repositories, allowing multiple to be registered."),
"version": attr.string(doc = "Explicit version of ruby."),
})

def _ruby_module_extension(module_ctx):
registrations = {}
for mod in module_ctx.modules:
for bundle in mod.tags.bundle:
rb_bundle(
name = bundle.name,
srcs = bundle.srcs,
env = bundle.env,
gemfile = bundle.gemfile,
toolchain = bundle.toolchain,
)

for toolchain in mod.tags.toolchain:
# Prevent a users dependencies creating conflicting toolchain names
if toolchain.name != DEFAULT_RUBY_REPOSITORY and not mod.is_root:
fail("Only the root module may provide a name for the ruby toolchain.")

if toolchain.name in registrations.keys():
if toolchain.version == registrations[toolchain.name]:
# No problem to register a matching toolchain twice
continue
fail("Multiple conflicting toolchains declared for name {} ({} and {}".format(
toolchain.name,
toolchain.version,
registrations[toolchain.name],
))
else:
registrations[toolchain.name] = toolchain.version

for name, version in registrations.items():
rb_register_toolchains(
name = name,
version = version,
register = False,
)

ruby = module_extension(
implementation = _ruby_module_extension,
tag_classes = {
"bundle": ruby_bundle,
"toolchain": ruby_toolchain,
},
)
5 changes: 4 additions & 1 deletion ruby/private/bundle.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def _rb_bundle_impl(repository_ctx):
binstubs_path = repository_ctx.path("bin")
bundle_path = repository_ctx.path(".")
gemfile_path = repository_ctx.path(repository_ctx.attr.gemfile)
toolchain_path = repository_ctx.path(Label("@rules_ruby_dist//:BUILD")).dirname
toolchain_path = repository_ctx.path(repository_ctx.attr.toolchain).dirname

if repository_ctx.os.name.startswith("windows"):
bundle = repository_ctx.path("%s/dist/bin/bundle.cmd" % toolchain_path)
Expand Down Expand Up @@ -78,6 +78,9 @@ rb_bundle = repository_rule(
List of Ruby source files used to build the library.
""",
),
"toolchain": attr.label(
mandatory = True,
),
"gemfile": attr.label(
allow_single_file = ["Gemfile"],
doc = """
Expand Down
12 changes: 8 additions & 4 deletions ruby/private/download.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
_JRUBY_BINARY_URL = "https://repo1.maven.org/maven2/org/jruby/jruby-dist/{version}/jruby-dist-{version}-bin.tar.gz"
_RUBY_BUILD_URL = "https://github.com/rbenv/ruby-build/archive/refs/tags/v{version}.tar.gz"
_RUBY_INSTALLER_URL = "https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-{version}-1/rubyinstaller-devkit-{version}-1-x64.exe"
DEFAULT_RUBY_REPOSITORY = "rules_ruby"

def rb_register_toolchains(version = None, **kwargs):
def rb_register_toolchains(name = DEFAULT_RUBY_REPOSITORY, version = None, register = True, **kwargs):
"""
Register a Ruby toolchain and lazily download the Ruby Interpreter.

Expand All @@ -22,19 +23,22 @@ def rb_register_toolchains(version = None, **kwargs):
```

Args:
name: base name of resulting repositories, by default "rules_ruby"
version: a semver version of Matz Ruby Interpreter, or a string like [interpreter type]-[version]
register: whether to register the resulting toolchains, should be False under bzlmod
**kwargs: additional parameters to the downloader for this interpreter type
"""
repo_name = "rules_ruby_dist"
proxy_repo_name = "rules_ruby_toolchains"
repo_name = name + "_dist"
proxy_repo_name = name + "_toolchains"
if repo_name not in native.existing_rules().values():
_rb_download(name = repo_name, version = version, **kwargs)
rb_toolchain_repository_proxy(
name = proxy_repo_name,
toolchain = "@{}//:toolchain".format(repo_name),
toolchain_type = "@rules_ruby//ruby:toolchain_type",
)
native.register_toolchains("@{}//:all".format(proxy_repo_name))
if register:
native.register_toolchains("@{}//:all".format(proxy_repo_name))

def _rb_toolchain_repository_proxy_impl(repository_ctx):
repository_ctx.file(
Expand Down
Loading