diff --git a/BUILD b/BUILD new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..5bd96d7 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# rules_yaml + +This project provides [Bazel](http://bazel.build) rules for operating with YAML. + +## Setup + +In your WORKSPACE file, include the following snippets. +This will tell Bazel to fetch the YAML rules archive, extract it, and prepare it for use in your application. + +```bzl +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "rules_yaml", + sha256 = "", + url = "https://github.com/calebfroese/rules_yaml/archive/0.0.1.zip", +) + +load("@rules_yaml//:defs.bzl", "yaml_repositories") + +# This sets up the dependencies for rules_yaml +yaml_repositories() +``` + +## Usage + +You can pull elements into new YAML files using the `yaml_excerpt` rule. + +```bzl +# Extract elements nested under the path into a new file +yaml_excerpt( + name = "first_car_info", + src = "template.yml", + path = "config.properties.cars[0].Details", +) +# Which can then be passed in to other rules as ":first_car_info" +``` diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 0000000..e69de29 diff --git a/defs.bzl b/defs.bzl new file mode 100644 index 0000000..40f993b --- /dev/null +++ b/defs.bzl @@ -0,0 +1,5 @@ +load("//internal/rules:yaml_excerpt.bzl", _yaml_excerpt = "yaml_excerpt") +load("//internal/repository:yaml_repositories.bzl", _yaml_repositories = "yaml_repositories") + +yaml_excerpt = _yaml_excerpt +yaml_repositories = _yaml_repositories diff --git a/internal/BUILD b/internal/BUILD new file mode 100644 index 0000000..e69de29 diff --git a/internal/common/BUILD b/internal/common/BUILD new file mode 100644 index 0000000..c5f93a2 --- /dev/null +++ b/internal/common/BUILD @@ -0,0 +1 @@ +package(default_visibility = ["//internal:__subpackages__"]) diff --git a/internal/common/utils.bzl b/internal/common/utils.bzl new file mode 100644 index 0000000..cd98f0b --- /dev/null +++ b/internal/common/utils.bzl @@ -0,0 +1,9 @@ +def select_compiler(compiler): + """Will return the correct YAML yq executable for the host machine.""" + if compiler != None: + return compiler + return select({ + "@bazel_tools//src/conditions:darwin": "@yq_binary_darwin//file", + "@bazel_tools//src/conditions:windows": "@yq_binary_windows//file", + "//conditions:default": "@yq_binary_linux//file", + }) diff --git a/internal/repository/BUILD b/internal/repository/BUILD new file mode 100644 index 0000000..c5f93a2 --- /dev/null +++ b/internal/repository/BUILD @@ -0,0 +1 @@ +package(default_visibility = ["//internal:__subpackages__"]) diff --git a/internal/repository/yaml_repositories.bzl b/internal/repository/yaml_repositories.bzl new file mode 100644 index 0000000..ab62a8a --- /dev/null +++ b/internal/repository/yaml_repositories.bzl @@ -0,0 +1,39 @@ +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file") + +_YQ_SOURCES = { + "darwin_amd64": ( + ["https://github.com/mikefarah/yq/releases/download/2.4.0/yq_darwin_amd64"], + "f09d3db259a0073a441362e94c7973a921c58903c7dd7cb7894672037687322c", + ), + "windows_amd64": ( + ["https://github.com/mikefarah/yq/releases/download/2.4.0/yq_windows_amd64.exe"], + "793dac701765fce832afff85104cb208c1392a94c369474222fe42a119e1bcd1", + ), + "linux_amd64": ( + ["https://github.com/mikefarah/yq/releases/download/2.4.0/yq_linux_amd64"], + "99a01ae32f0704773c72103adb7050ef5c5cad14b517a8612543821ef32d6cc9", + ), +} + +def yaml_repositories(yq_sources = _YQ_SOURCES): + """Declares workspaces that the YAML rules depends on. All consumers of rules_yaml should call this in their + WORKSPACE.""" + + http_file( + name = "yq_binary_darwin", + executable = True, + urls = yq_sources["darwin_amd64"][0], + sha256 = yq_sources["darwin_amd64"][1], + ) + http_file( + name = "yq_binary_windows", + executable = True, + urls = yq_sources["windows_amd64"][0], + sha256 = yq_sources["windows_amd64"][1], + ) + http_file( + name = "yq_binary_linux", + executable = True, + urls = yq_sources["linux_amd64"][0], + sha256 = yq_sources["linux_amd64"][1], + ) diff --git a/internal/rules/BUILD b/internal/rules/BUILD new file mode 100644 index 0000000..c5f93a2 --- /dev/null +++ b/internal/rules/BUILD @@ -0,0 +1 @@ +package(default_visibility = ["//internal:__subpackages__"]) diff --git a/internal/rules/yaml_excerpt.bzl b/internal/rules/yaml_excerpt.bzl new file mode 100644 index 0000000..d423cb2 --- /dev/null +++ b/internal/rules/yaml_excerpt.bzl @@ -0,0 +1,56 @@ +load("//internal/common:utils.bzl", "select_compiler") + +def yaml_excerpt(name, src, path, compiler = None): + """Macro to wrap the yaml_excerpt rule getting around the restriction of running Starlarks `select` in rules.""" + _yaml_excerpt( + name = name, + src = src, + path = path, + compiler = select_compiler(compiler), + ) + +def _yaml_excerpt_impl(ctx): + executable = ctx.executable.compiler + sourcefile = ctx.file.src + outputfile = ctx.outputs.excerpt + print("Exec", executable) + + ctx.actions.run_shell( + tools = [executable], + outputs = [outputfile], + inputs = [sourcefile], + command = "{executable} read {yaml_file} {path} > {output}".format( + executable = executable.path, + yaml_file = sourcefile.path, + path = ctx.attr.path, + output = outputfile.path, + ), + ) + +_yaml_excerpt = rule( + doc = """Extracts YAML at a path into a new file + + Uses JSON path syntax to reference a YAML element and output a file with the selected contents. A custom + yq executable can optionally be provided.""", + implementation = _yaml_excerpt_impl, + attrs = { + "src": attr.label( + doc = """The source YAML file to perform operations on""", + mandatory = True, + allow_single_file = True, + ), + "path": attr.string( + doc = """JSON path reference to the element, for example `a.b.c`. `$` can be specified to reference the root.""", + mandatory = True, + ), + "compiler": attr.label( + doc = """yq executable""", + allow_files = True, + executable = True, + cfg = "host", + ), + }, + outputs = { + "excerpt": "%{name}.yaml", + }, +)