From 4ffd256c94d60dc03fa5208cd364bdca67346a95 Mon Sep 17 00:00:00 2001 From: Paul Cody Johnston Date: Sat, 3 Feb 2018 13:49:50 -0700 Subject: [PATCH] Add post_install argument to yarn_modules rule Fixes #55 --- README.md | 1 + node/internal/clean_node_modules.js | 23 ++++++++++++++++++++++ node/internal/yarn_modules.bzl | 30 +++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 node/internal/clean_node_modules.js diff --git a/README.md b/README.md index 2613e77..8327655 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ node_module( | --- | --- | --- | --- | | optional | `label` | `package_json` | A `package.json` file containing the dependencies that should be installed. | | optional | `string_dict` | `deps` | A mapping of `name` --> `version` for the dependencies that should be installed. | +| optional | `string_list` | `post_install` | A list of command-line arguments that should be invoked after the `yarn install` step. See [#55](https://github.com/pubref/rules_node/issues/55). | > Either `package_json` or `deps` must be present, but not both. diff --git a/node/internal/clean_node_modules.js b/node/internal/clean_node_modules.js new file mode 100644 index 0000000..08c645f --- /dev/null +++ b/node/internal/clean_node_modules.js @@ -0,0 +1,23 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path') + +// Yes, could look for BUILD files also, but wait for that error to +// occur before fixing it. +visitSync('node_modules/', filename => { + if (filename.endsWith("BUILD.bazel")) { + fs.unlink(filename); + console.log("Removed", filename, "from the node_modules/ tree"); + } +}); + +function visitSync(d, visitFn) { + if (fs.statSync(d).isDirectory()) { + fs.readdirSync(d).forEach(name => visitSync(path.join(d, name), visitFn)); + } else { + visitFn(d); + } +} + + diff --git a/node/internal/yarn_modules.bzl b/node/internal/yarn_modules.bzl index 0d460fe..9e7498d 100644 --- a/node/internal/yarn_modules.bzl +++ b/node/internal/yarn_modules.bzl @@ -32,6 +32,7 @@ def _yarn_modules_impl(ctx): node = ctx.path(node_label) parse_yarn_lock_js = ctx.path(ctx.attr._parse_yarn_lock_js) + clean_node_modules_js = ctx.path(ctx.attr._clean_node_modules_js) yarn_js = ctx.path(ctx.attr._yarn_js) @@ -53,6 +54,7 @@ def _yarn_modules_impl(ctx): # Copy the parse_yarn_lock script and yarn.js over here. execute(ctx, ["cp", parse_yarn_lock_js, "internal/parse_yarn_lock.js"]) + execute(ctx, ["cp", clean_node_modules_js, "internal/clean_node_modules.js"]) execute(ctx, ["cp", yarn_js, "yarn.js"]) # Build node_modules via 'yarn install' @@ -61,9 +63,32 @@ def _yarn_modules_impl(ctx): "PATH": "%s:$PATH" % ctx.path(node).dirname, }) + # Sadly, pre-existing BUILD.bazel files located in npm modules can + # screw up package boudaries. Remove these. + execute(ctx, [node, "internal/clean_node_modules.js"], quiet = True) + # Run the script and save the stdout to our BUILD file(s) parse_args = ["--resolve=%s:%s" % (k, v) for k, v in ctx.attr.resolutions.items()] result = execute(ctx, [node, "internal/parse_yarn_lock.js"] + parse_args, quiet = True) + + # If the user has specified a post_install step, build those args + # and execute it. + post_install_args = [] + for arg in ctx.attr.post_install: + if arg == "{node}": + post_install_args.append(node) + else: + post_install_args.append(arg) + if len(post_install_args) > 0: + # Expose python, node, and basic tools by default. Might need + # to add a post_install_tools option in the future if this is + # not sufficient. + python = ctx.which("python") + mkdir = ctx.which("mkdir") + execute(ctx, post_install_args, environment = { + "PATH": ":".join([node.dirname, python.dirname, mkdir.dirname, "$PATH"]) + }) + ctx.file("BUILD.bazel", result.stdout) @@ -89,6 +114,10 @@ yarn_modules = repository_rule( default = Label("//node:internal/parse_yarn_lock.js"), single_file = True, ), + "_clean_node_modules_js": attr.label( + default = Label("//node:internal/clean_node_modules.js"), + single_file = True, + ), "_yarn_js": attr.label( default = Label("@yarn//:bin/yarn.js"), single_file = True, @@ -97,6 +126,7 @@ yarn_modules = repository_rule( mandatory = False, allow_files = FileType(["package.json"]), ), + "post_install": attr.string_list(), "deps": attr.string_dict(mandatory = False), "resolutions": attr.string_dict(mandatory = False), }