Skip to content

Commit

Permalink
Mark modules.as_extension as reproducible (#497)
Browse files Browse the repository at this point in the history
WORKSPACE macros are fully deterministic and thus a prime example of a `reproducible` module extension. This reduces clutter in `MODULE.bazel.lock`.
  • Loading branch information
fmeum committed Apr 24, 2024
1 parent 09b1079 commit 1969278
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 5 deletions.
6 changes: 4 additions & 2 deletions docs/modules_doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,16 @@ rules_foo_deps_ext = modules.as_extension(rules_foo_deps)

A module extension that generates the repositories instantiated by the given macro and also
uses [`use_all_repos`](#use_all_repos) to indicate that all of those repositories should be
imported via `use_repo`.
imported via `use_repo`. The extension is marked as reproducible if supported by the current
version of Bazel and thus doesn't result in a lockfile entry.


<a id="modules.use_all_repos"></a>

## modules.use_all_repos

<pre>
modules.use_all_repos(<a href="#modules.use_all_repos-module_ctx">module_ctx</a>)
modules.use_all_repos(<a href="#modules.use_all_repos-module_ctx">module_ctx</a>, <a href="#modules.use_all_repos-reproducible">reproducible</a>)
</pre>

Return from a module extension that should have all its repositories imported via `use_repo`.
Expand All @@ -64,6 +65,7 @@ ext = module_extension(_ext_impl)
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="modules.use_all_repos-module_ctx"></a>module_ctx | The [<code>module_ctx</code>](https://bazel.build/rules/lib/builtins/module_ctx) object passed to the module extension's implementation function. | none |
| <a id="modules.use_all_repos-reproducible"></a>reproducible | The value of the <code>reproducible</code> parameter to pass to the [<code>extension_metadata</code>](https://bazel.build/rules/lib/builtins/extension_metadata.html) object returned by this function. This is safe to set with Bazel versions that don't support this parameter and will be ignored in that case. | <code>False</code> |

**RETURNS**

Expand Down
23 changes: 20 additions & 3 deletions lib/modules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,23 @@ def _as_extension(macro, doc = None):
Returns:
A module extension that generates the repositories instantiated by the given macro and also
uses [`use_all_repos`](#use_all_repos) to indicate that all of those repositories should be
imported via `use_repo`.
imported via `use_repo`. The extension is marked as reproducible if supported by the current
version of Bazel and thus doesn't result in a lockfile entry.
"""

def _ext_impl(module_ctx):
macro()
return _use_all_repos(module_ctx)

# Setting `reproducible` is safe since `macro`, as a function without parameters, must be
# deterministic.
return _use_all_repos(module_ctx, reproducible = True)

return module_extension(
implementation = _ext_impl,
doc = doc,
)

def _use_all_repos(module_ctx):
def _use_all_repos(module_ctx, reproducible = False):
"""Return from a module extension that should have all its repositories imported via `use_repo`.
Example:
Expand All @@ -63,6 +67,10 @@ def _use_all_repos(module_ctx):
Args:
module_ctx: The [`module_ctx`](https://bazel.build/rules/lib/builtins/module_ctx) object
passed to the module extension's implementation function.
reproducible: The value of the `reproducible` parameter to pass to the
[`extension_metadata`](https://bazel.build/rules/lib/builtins/extension_metadata.html)
object returned by this function. This is safe to set with Bazel versions that don't
support this parameter and will be ignored in that case.
Returns:
An [`extension_metadata`](https://bazel.build/rules/lib/builtins/extension_metadata.html)
Expand All @@ -88,9 +96,18 @@ def _use_all_repos(module_ctx):
if root_module_has_non_dev_dependency == None:
return None

# module_ctx.extension_metadata has the paramater `reproducible` as of Bazel 7.1.0. We can't
# test for it directly and would ideally use bazel_features to check for it, but adding a
# dependency on it would require complicating the WORKSPACE setup for skylib. Thus, test for
# it by checking the availability of another feature introduced in 7.1.0.
extension_metadata_kwargs = {}
if hasattr(module_ctx, "watch"):
extension_metadata_kwargs["reproducible"] = reproducible

return extension_metadata(
root_module_direct_deps = "all" if root_module_has_non_dev_dependency else [],
root_module_direct_dev_deps = [] if root_module_has_non_dev_dependency else "all",
**extension_metadata_kwargs
)

modules = struct(
Expand Down

0 comments on commit 1969278

Please sign in to comment.