Last active
May 3, 2018 18:51
-
-
Save ittaiz/3e700cfc3ee7a7e135a57144a47e47a8 to your computer and use it in GitHub Desktop.
Bazel Skylark rule and aspect to collect all config files (erbs) transitively
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ConfigFiles = provider( | |
fields = { | |
'transitive_config_files' : 'number of files' | |
} | |
) | |
_erb_filetype = FileType([".erb"]) | |
_attrs = ['tars','deps','runtime_deps','exports'] #data? | |
def _accumulate_transitive_config_files(accumulated, deps): | |
return depset( | |
transitive = [dep[ConfigFiles].transitive_config_files for dep in deps] + [accumulated]) | |
def _collect_current_config_files(srcs): | |
current_config_files = [] | |
for src in srcs: | |
erb_srcs = _erb_filetype.filter(src.files) | |
for file in erb_srcs: | |
current_config_files.append(file) | |
return current_config_files | |
def _collect_config_files_aspect_impl(target, ctx): | |
if hasattr(ctx.rule.attr, 'srcs'): | |
current_config_files = _collect_current_config_files(ctx.rule.attr.srcs) | |
else: | |
current_config_files = [] | |
accumulated_config_files = depset(current_config_files) | |
for attr in _attrs: | |
if hasattr(ctx.rule.attr, attr): | |
accumulated_config_files = _accumulate_transitive_config_files(accumulated_config_files, getattr(ctx.rule.attr, attr)) | |
return [ConfigFiles(transitive_config_files=accumulated_config_files)] | |
def _paths(config_files): | |
return [f.path for f in config_files] | |
def _zip(ctx, config_files): | |
zipper_args = "\n".join(_paths(config_files)) + "\n" | |
if len(config_files) > 0: | |
zipper_arg_path = ctx.actions.declare_file("%s_zipper_args" % ctx.outputs.config_archive.path) | |
ctx.actions.write(zipper_arg_path, zipper_args) | |
# We move the files and touch them so that the output file is a purely deterministic | |
# product of the _content_ of the inputs | |
cmd = """ | |
rm -f {out} | |
{zipper} c {out} @{path} | |
""" | |
cmd = cmd.format(out=ctx.outputs.config_archive.path, | |
path=zipper_arg_path.path, | |
zipper=ctx.executable._zipper.path) | |
ctx.actions.run_shell( | |
inputs = config_files + [ctx.executable._zipper, zipper_arg_path], | |
outputs = [ctx.outputs.config_archive], | |
command = cmd, | |
progress_message = "making config archive %s (%s files)" % (ctx.label, len(config_files)), | |
) | |
else: | |
# we still have to create the output we declared | |
ctx.actions.run_shell( | |
inputs = [ctx.executable._zipper], | |
outputs = [ctx.outputs.config_archive], | |
command = """ | |
echo "empty" > {out}.contents | |
rm -f {out} | |
{zipper} c {out} {out}.contents | |
rm {out}.contents | |
""".format(out=ctx.outputs.config_archive.path, | |
zipper=ctx.executable._zipper.path), | |
progress_message = "making empty config archive %s" % ctx.label, | |
) | |
def _collect_config_files_rule_impl(ctx): | |
_zip(ctx, ctx.attr.artifact[ConfigFiles].transitive_config_files.to_list()) | |
collect_config_files_aspect = aspect(implementation = _collect_config_files_aspect_impl, | |
attr_aspects = _attrs, | |
) | |
config_files = rule( | |
implementation = _collect_config_files_rule_impl, | |
attrs = { | |
'artifact' : attr.label(aspects = [collect_config_files_aspect]), | |
"_zipper": attr.label(executable=True, cfg="host", default=Label("@bazel_tools//tools/zip:zipper"), allow_files=True) | |
}, | |
outputs={"config_archive": "%{name}-config.zip"}, | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment