Skip to content

Commit

Permalink
feat: yq
Browse files Browse the repository at this point in the history
  • Loading branch information
kormide committed Apr 20, 2022
1 parent e0af963 commit 75d838a
Show file tree
Hide file tree
Showing 30 changed files with 1,026 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ tasks:
test_targets:
- "//..."
windows:
build_flags:
- "--build_tag_filters=-no-windows-ci"
build_targets:
- "//..."
test_flags:
- "--test_tag_filters=-no-windows-ci"
test_targets:
- "//..."
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
docs/*.md linguist-generated=true
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
docs/*.md
lib/tests/jq/*.json
lib/tests/yq/empty.yaml
lib/lib/tests/write_source_files/*.js
lib/lib/tests/write_source_files/subdir/*.js
lib/lib/tests/write_source_files/subdir/subsubdir/*.js
5 changes: 5 additions & 0 deletions docs/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,9 @@ stardoc_with_diff_test(
bzl_library_target = "//lib:repo_utils",
)

stardoc_with_diff_test(
name = "yq",
bzl_library_target = "//lib:yq",
)

update_docs()
114 changes: 114 additions & 0 deletions docs/yq.md

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

3 changes: 2 additions & 1 deletion internal_deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ statement from these, that's a bug in our distribution.

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
load("//lib:repositories.bzl", "register_jq_toolchains")
load("//lib:repositories.bzl", "register_jq_toolchains", "register_yq_toolchains")

# buildifier: disable=unnamed-macro
def bazel_lib_internal_deps():
Expand Down Expand Up @@ -67,3 +67,4 @@ def bazel_lib_internal_deps():

# Register toolchains for tests
register_jq_toolchains(version = "1.6")
register_yq_toolchains(version = "4.24.5")
12 changes: 12 additions & 0 deletions lib/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ toolchain_type(
visibility = ["//visibility:public"],
)

toolchain_type(
name = "yq_toolchain_type",
visibility = ["//visibility:public"],
)

bzl_library(
name = "docs",
srcs = ["docs.bzl"],
Expand Down Expand Up @@ -144,3 +149,10 @@ bzl_library(
"//lib/private:repo_utils",
],
)

bzl_library(
name = "yq",
srcs = ["yq.bzl"],
visibility = ["//visibility:public"],
deps = ["//lib/private:yq"],
)
6 changes: 6 additions & 0 deletions lib/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,9 @@ bzl_library(
visibility = ["//lib:__subpackages__"],
deps = [":repo_utils"],
)

bzl_library(
name = "yq",
srcs = ["yq.bzl"],
visibility = ["//lib:__subpackages__"],
)
69 changes: 69 additions & 0 deletions lib/private/yq.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Implementation for yq rule"""

_yq_attrs = {
"srcs": attr.label_list(
allow_files = [".yaml", ".json", ".xml"],
mandatory = True,
allow_empty = True,
),
"expression": attr.string(mandatory = False),
"args": attr.string_list(),
"outs": attr.output_list(mandatory = True),
}

def is_split_operation(args):
for arg in args:
if arg.startswith("-s") or arg.startswith("--split-exp"):
return True
return False

def _escape_path(path):
return "/".join([".." for t in path.split("/")]) + "/"

def _yq_impl(ctx):
yq_bin = ctx.toolchains["@aspect_bazel_lib//lib:yq_toolchain_type"].yqinfo.bin

outs = ctx.outputs.outs
args = ctx.attr.args[:]
inputs = ctx.files.srcs[:]

split_operation = is_split_operation(args)

if "eval" in args or "eval-all" in args:
fail("Do not pass 'eval' or 'eval-all' into yq; this is already set based on the number of srcs")
if not split_operation and len(outs) > 1:
fail("Cannot specify multiple outputs when -s or --split-exp is not set")
if "-i" in args or "--inplace" in args:
fail("Cannot use arg -i or --inplace as it is not bazel-idiomatic to update the input file; consider using write_source_files to write back to the source tree")
if len(ctx.attr.srcs) == 0 and "-n" not in args and "--null-input" not in args:
args = args + ["--null-input"]

# For split operations, yq outputs files in the same directory so we
# must cd to the correct output dir before executing it
bin_dir = ctx.bin_dir.path + "/" + ctx.label.package
escape_bin_dir = _escape_path(bin_dir)
cmd = "cd {bin_dir} && {yq} {args} {eval_cmd} {expression} {sources} {maybe_out}".format(
bin_dir = ctx.bin_dir.path + "/" + ctx.label.package,
yq = escape_bin_dir + yq_bin.path,
eval_cmd = "eval" if len(inputs) <= 1 else "eval-all",
args = " ".join(args),
expression = "'%s'" % ctx.attr.expression if ctx.attr.expression else "",
sources = " ".join(["'%s%s'" % (escape_bin_dir, file.path) for file in ctx.files.srcs]),
# In the -s/--split-exr case, the out file names are determined by the yq expression
maybe_out = (" > %s%s" % (escape_bin_dir, outs[0].path)) if len(outs) == 1 else "",
)

ctx.actions.run_shell(
tools = [yq_bin],
inputs = inputs,
outputs = outs,
command = cmd,
mnemonic = "yq",
)

return DefaultInfo(files = depset(outs), runfiles = ctx.runfiles(outs))

yq_lib = struct(
attrs = _yq_attrs,
implementation = _yq_impl,
)
Loading

0 comments on commit 75d838a

Please sign in to comment.