Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/bazelbuild/rules_jsonnet

Jsonnet rules for Bazel
https://github.com/bazelbuild/rules_jsonnet

bazel bazel-rules jsonnet jsonnet-rules

Last synced: about 2 months ago
JSON representation

Jsonnet rules for Bazel

Awesome Lists containing this project

README

        

[![Build status](https://badge.buildkite.com/c3449aba989713394a3237070971eb59b92ad19d6f69555a25.svg)](https://buildkite.com/bazel/rules-jsonnet-postsubmit)

# Jsonnet Rules

## Overview

These are build rules for working with [Jsonnet][jsonnet] files with Bazel.

[jsonnet]: https://jsonnet.org

## Setup

To use the Jsonnet rules as part of your Bazel project, please follow the
instructions on [the releases page](https://github.com/bazelbuild/rules_jsonnet/releases).

## Jsonnet Compiler Selection

By default for Bzlmod, Bazel will use the [Go
compiler](https://github.com/google/go-jsonnet). Note that the
primary development focus of the Jsonnet project is now with the Go compiler.
This repository's support for using the C++ compiler is deprecated, and may be
removed in a future release.

To use [the
C++](https://github.com/google/jsonnet) or
[Rust](https://github.com/CertainLach/jrsonnet) compiler of Jsonnet instead,
register a different compiler:

| Jsonnet compiler | MODULE.bazel directive | WORKSPACE directive |
| ---------------- | --------------------------------- | -------------------------------------------------------------------------------- |
| Go | `jsonnet.compiler(name = "go")` | `register_toolchains("@io_bazel_rules_jsonnet//jsonnet:go_jsonnet_toolchain")` |
| cpp | `jsonnet.compiler(name = "cpp")` | `register_toolchains("@io_bazel_rules_jsonnet//jsonnet:cpp_jsonnet_toolchain")` |
| Rust | `jsonnet.compiler(name = "rust")` | `register_toolchains("@io_bazel_rules_jsonnet//jsonnet:rust_jsonnet_toolchain")` |

Note that `WORKSPACE` users must register a toolchain manually, using the table
above as reference.

### Rust Jsonnet Compiler

To use the Rust Jsonnet compiler a `Nightly` Rust version for the host tools is
required because `-Z bindeps` is needed to compile the Jrsonnet binary.

Add the following snippet to the `Module.bazel` file:

```Starlark
bazel_dep(name = "rules_rust", version = "0.45.1")

rust_host = use_extension("@rules_rust//rust:extensions.bzl", "rust_host_tools")
rust_host.host_tools(
version = "nightly/2024-05-02",
)
```

### CLI

Use the `--extra_toolchains` flag to pass the preferred toolchain to the bazel
invocation:

```bash
bazel build //... --extra_toolchains=@rules_jsonnet//jsonnet:cpp_jsonnet_toolchain

bazel test //... --extra_toolchains=@rules_jsonnet//jsonnet:rust_jsonnet_toolchain

bazel run //... --extra_toolchains=@rules_jsonnet//jsonnet:go_jsonnet_toolchain
```


## jsonnet_library

```python
jsonnet_library(name, srcs, deps, imports)
```







Attributes




name

Name, required

A unique name for this rule.





srcs

List of Labels, required


List of .jsonnet files that comprises this Jsonnet
library.





deps

List of labels, optional


List of targets that are required by the srcs Jsonnet
files.





imports

List of strings, optional


List of import -J flags to be passed to the
jsonnet compiler.




### Example

Suppose you have the following directory structure:

```
[workspace]/
WORKSPACE
configs/
BUILD
backend.jsonnet
frontend.jsonnet
```

You can use the `jsonnet_library` rule to build a collection of `.jsonnet`
files that can be imported by other `.jsonnet` files as dependencies:

`configs/BUILD`:

```python
load("@io_bazel_rules_jsonnet//jsonnet:jsonnet.bzl", "jsonnet_library")

jsonnet_library(
name = "configs",
srcs = [
"backend.jsonnet",
"frontend.jsonnet",
],
)
```


## jsonnet\_to\_json

```python
jsonnet_to_json(name, src, deps, outs, multiple_outputs, imports, stamp_keys, ext_strs, ext_str_envs, ext_code, ext_code_envs ext_str_files, ext_str_file_vars, ext_code_files, ext_code_file_vars, yaml_stream)
```







Attributes




name

Name, required

A unique name for this rule.



This name will be used as the name of the JSON file generated by this
rule.





src

Label, required


The .jsonnet file to convert to JSON.





deps

List of labels, optional


List of targets that are required by the src Jsonnet
file.





outs

List of Filenames, required


Names of the output .json files to be generated by this rule.



If you are generating only a single JSON file and are not using
jsonnet multiple output files, then this attribute should only
contain the file name of the JSON file you are generating.



If you are generating multiple JSON files using jsonnet multiple file
output (jsonnet -m), then list the file names of all the
JSON files to be generated. The file names specified here must match
the file names specified in your src Jsonnet file.



For the case where multiple file output is used but only for
generating one output file, set the multiple_outputs
attribute to 1 to explicitly enable the -m flag for
multiple file output.





multiple_outputs

bool, optional, default 0


Set to 1 to explicitly enable multiple file output via the
jsonnet -m flag.



This is used for the case where multiple file output is used but only
for generating a single output file. For example:




local foo = import "foo.jsonnet";

{
"foo.json": foo,
}






imports

List of strings, optional


List of import -J flags to be passed to the
jsonnet compiler.





stamp_keys

List of strings, optional


Specify which variables in `ext_strs` and `ext_code` should get stamped by listing the matching dict keys.



To get outside variables provided by a script invoked via `--workspace_status_command` into the build. For example:



jsonnet_to_json(
name = "...",
ext_strs = {
"cluster": "{CLUSTER}"
},
stamp_keys = ["cluster"]
)


$ cat .bazelrc
build --workspace_status_command=./print-workspace-status.sh

$ cat print-workspace-status.sh
cat <<EOF
VAR1 value1
# This can be overridden by users if they "export CLUSTER_OVERRIDE"
CLUSTER ${CLUSTER_OVERRIDE:-default-value2}
EOF



ext_strs

String dict, optional


Map of strings to pass to jsonnet as external variables via --ext-str key=value.





ext_str_envs

String list, optional


List of env var names containing strings to pass to jsonnet as external variables via --ext-str key.





ext_code

String dict, optional


Map of code to pass to jsonnet as external variables via
--ext-code key=value.





ext_code_envs

String list, optional


List of env var names containing jsonnet code to pass to jsonnet as external variables via
--ext-code key.





ext_str_files

List of labels, optional but needed together with file_vars


List of string files that map to the var name defined in file_vars at the same index and together are passed to jsonnet via
--ext-str-file var=file.





ext_str_file_vars

List of string, optional but needed together with files


List of var names that maps to the file defined in files at the same index and together are passed to jsonnet via
--ext-str-file var=file.





ext_code_files

String dict, optional


List of jsonnet code files that map to the var name defined in ext_code_file_vars at the same index and together are passed to jsonnet via
--ext-code-file var=file.





ext_code_file_vars

String dict, optional


List of var names that maps to the code file defined in code_files at the same index and together are passed to jsonnet via
--ext-code-file var=file.





tla_strs

String dict, optional


Map of strings to pass to jsonnet as top-level arguments via --tla-str key=value.





tla_str_envs

String list, optional


List of env var names containing strings to pass to jsonnet as top-level arguments via --tla-str key.





tla_code

String dict, optional


Map of code to pass to jsonnet as top-level arguments via
--tla-code key=value.





tla_code_envs

String list, optional


List of env var names containing jsonnet code to pass to jsonnet as top-level arguments via
--tla-code key.





tla_str_files

Label-keyed String dict, optional


Dict of labels referencing text files and a var name, passed to jsonnet via --tla-str-file var=file.





tla_code_files

Label-keyed String dict, optional


Dict of labels referencing code files and a var name, passed to jsonnet via --tla-code-file var=file.





yaml_stream

bool, optional, default is False


Set to 1 to write output as a YAML stream of JSON documents.




### Example

Suppose you have the following directory structure:

```
[workspace]/
WORKSPACE
workflows/
BUILD
workflow.libsonnet
wordcount.jsonnet
intersection.jsonnet
```

Say that `workflow.libsonnet` is a base configuration library for a workflow
scheduling system and `wordcount.jsonnet` and `intersection.jsonnet` both
import `workflow.libsonnet` to define workflows for performing a wordcount and
intersection of two files, respectively.

First, create a `jsonnet_library` target with `workflow.libsonnet`:

`workflows/BUILD`:

```python
load("@io_bazel_rules_jsonnet//jsonnet:jsonnet.bzl", "jsonnet_library")

jsonnet_library(
name = "workflow",
srcs = ["workflow.libsonnet"],
)
```

To compile `wordcount.jsonnet` and `intersection.jsonnet` to JSON, define two
`jsonnet_to_json` targets:

```python
jsonnet_to_json(
name = "wordcount",
src = "wordcount.jsonnet",
outs = ["wordcount.json"],
deps = [":workflow"],
)

jsonnet_to_json(
name = "intersection",
src = "intersection.jsonnet",
outs = ["intersection.json"],
deps = [":workflow"],
)
```

### Example: Multiple output files

To use Jsonnet's [multiple output files][multiple-output-files], suppose you
add a file `shell-workflows.jsonnet` that imports `wordcount.jsonnet` and
`intersection.jsonnet`:

`workflows/shell-workflows.jsonnet`:

```
local wordcount = import "workflows/wordcount.jsonnet";
local intersection = import "workflows/intersection.jsonnet";

{
"wordcount-workflow.json": wordcount,
"intersection-workflow.json": intersection,
}
```

To compile `shell-workflows.jsonnet` into the two JSON files,
`wordcount-workflow.json` and `intersection-workflow.json`, first create a
`jsonnet_library` target containing the two files that
`shell-workflows.jsonnet` depends on:

```python
jsonnet_library(
name = "shell-workflows-lib",
srcs = [
"wordcount.jsonnet",
"intersection.jsonnet",
],
deps = [":workflow"],
)
```

Then, create a `jsonnet_to_json` target and set `outs` to the list of output
files to indicate that multiple output JSON files are generated:

```python
jsonnet_to_json(
name = "shell-workflows",
src = "shell-workflows.jsonnet",
deps = [":shell-workflows-lib"],
outs = [
"wordcount-workflow.json",
"intersection-workflow.json",
],
)
```

[multiple-output-files]: https://jsonnet.org/learning/getting_started.html#multi


## jsonnet\_to\_json\_test

```python
jsonnet_to_json_test(name, src, deps, imports, golden, error=0, regex=False, yaml_stream=False, stamp_keys, ext_strs, ext_str_envs, ext_code, ext_code_envs ext_str_files, ext_str_file_vars, ext_code_files, ext_code_file_vars)
```







Attributes




name

Name, required

A unique name for this rule.



This name will be used as the name of the JSON file generated by this
rule.





src

Label, required


The .jsonnet file to convert to JSON.





deps

List of labels, optional


List of targets that are required by the src Jsonnet
file.





imports

codefileList of strings, optional


List of import -J flags to be passed to the
jsonnet compiler.





stamp_keys

List of strings, optional


Specify which variables in `ext_strs` and `ext_code` should get stamped by listing the matching dict keys.



To get outside variables provided by a script invoked via `--workspace_status_command` into the build.





ext_strs

String dict, optional


Map of strings to pass to jsonnet as external variables via --ext-str key=value.





ext_str_envs

String list, optional


List of env var names containing strings to pass to jsonnet as external variables via --ext-str key.





ext_code

String dict, optional


Map of code to pass to jsonnet as external variables via
--ext-code key=value.





ext_code_envs

String list, optional


List of env var names containing jsonnet code to pass to jsonnet as external variables via
--ext-code key.





ext_str_files

List of labels, optional but needed together with file_vars


List of string files that map to the var name defined in file_vars at the same index and together are passed to jsonnet via
--ext-str-file var=file.





ext_str_file_vars

List of string, optional but needed together with files


List of var names that maps to the file defined in files at the same index and together are passed to jsonnet via
--ext-str-file var=file.





ext_code_files

String dict, optional


List of jsonnet code files that map to the var name defined in ext_code_file_vars at the same index and together are passed to jsonnet via
--ext-code-file var=file.





ext_code_file_vars

String dict, optional


List of var names that maps to the code file defined in code_files at the same index and together are passed to jsonnet via
--ext-code-file var=file.





golden

Label, optional


The expected (combined stdout and stderr) output to compare to the
output of running jsonnet on src.





error

Integer, optional, default is 0


The expected error code from running jsonnet on
src.





regex

bool, optional, default is False


Set to 1 if golden contains a regex used to match
the output of running jsonnet on src.





yaml_stream

bool, optional, default is False


Set to 1 to write output as a YAML stream of JSON documents.




### Example

Suppose you have the following directory structure:

```
[workspace]/
WORKSPACE
config/
BUILD
base_config.libsonnet
test_config.jsonnet
test_config.json
```

Suppose that `base_config.libsonnet` is a library Jsonnet file, containing the
base configuration for a service. Suppose that `test_config.jsonnet` is a test
configuration file that is used to test `base_config.jsonnet`, and
`test_config.json` is the expected JSON output from compiling
`test_config.jsonnet`.

The `jsonnet_to_json_test` rule can be used to verify that compiling a Jsonnet
file produces the expected JSON output. Simply define a `jsonnet_to_json_test`
target and provide the input test Jsonnet file and the `golden` file containing
the expected JSON output:

`config/BUILD`:

```python
load(
"@io_bazel_rules_jsonnet//jsonnet:jsonnet.bzl",
"jsonnet_library",
"jsonnet_to_json_test",
)

jsonnet_library(
name = "base_config",
srcs = ["base_config.libsonnet"],
)

jsonnet_to_json_test(
name = "test_config_test",
src = "test_config",
deps = [":base_config"],
golden = "test_config.json",
)
```

To run the test: `bazel test //config:test_config_test`

### Example: Negative tests

Suppose you have the following directory structure:

```
[workspace]/
WORKSPACE
config/
BUILD
base_config.libsonnet
invalid_config.jsonnet
invalid_config.output
```

Suppose that `invalid_config.jsonnet` is a Jsonnet file used to verify that
an invalid config triggers an assertion in `base_config.jsonnet`, and
`invalid_config.output` is the expected error output.

The `jsonnet_to_json_test` rule can be used to verify that compiling a Jsonnet
file results in an expected error code and error output. Simply define a
`jsonnet_to_json_test` target and provide the input test Jsonnet file, the
expected error code in the `error` attribute, and the `golden` file containing
the expected error output:

`config/BUILD`:

```python
load(
"@io_bazel_rules_jsonnet//jsonnet:jsonnet.bzl",
"jsonnet_library",
"jsonnet_to_json_test",
)

jsonnet_library(
name = "base_config",
srcs = ["base_config.libsonnet"],
)

jsonnet_to_json_test(
name = "invalid_config_test",
src = "invalid_config",
deps = [":base_config"],
golden = "invalid_config.output",
error = 1,
)
```

To run the test: `bazel test //config:invalid_config_test`