Skip to content

Commit

Permalink
feat: add pre and post install patches to yarn_install and npm_install (
Browse files Browse the repository at this point in the history
  • Loading branch information
Greg Magolan authored Apr 14, 2021
1 parent ab0b372 commit d805f33
Show file tree
Hide file tree
Showing 14 changed files with 184 additions and 0 deletions.
24 changes: 24 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,30 @@ filegroup(
yarn_lock = "//:tools/fine_grained_goldens/yarn.lock",
)

yarn_install(
name = "internal_npm_install_test_patches_yarn",
package_json = "//internal/npm_install/test/patches_yarn:package.json",
package_path = "internal/npm_install/test/patches_yarn",
patch_args = ["-p0"],
patch_tool = "patch",
post_install_patches = ["//internal/npm_install/test/patches_yarn:semver+1.0.0.patch"],
pre_install_patches = ["//internal/npm_install/test/patches_yarn:package_json.patch"],
symlink_node_modules = False,
yarn_lock = "//internal/npm_install/test/patches_yarn:yarn.lock",
)

npm_install(
name = "internal_npm_install_test_patches_npm",
package_json = "//internal/npm_install/test/patches_npm:package.json",
package_lock_json = "//internal/npm_install/test/patches_npm:package-lock.json",
package_path = "internal/npm_install/test/patches_npm",
patch_args = ["-p0"],
patch_tool = "patch",
post_install_patches = ["//internal/npm_install/test/patches_npm:semver+1.0.0.patch"],
pre_install_patches = ["//internal/npm_install/test/patches_npm:package_json.patch"],
symlink_node_modules = False,
)

yarn_install(
name = "fine_grained_goldens_multi_linked",
included_files = [
Expand Down
63 changes: 63 additions & 0 deletions internal/npm_install/npm_install.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,37 @@ fine grained npm dependencies.
In most cases, this should be the directory of the package.json file so that the linker links the node_modules
in the same location they are found in the source tree. In a future release, this will default to the package.json
directory. This is planned for 4.0: https://github.com/bazelbuild/rules_nodejs/issues/2451""",
),
"patch_args": attr.string_list(
default = ["-p0"],
doc =
"The arguments given to the patch tool. Defaults to -p0, " +
"however -p1 will usually be needed for patches generated by " +
"git. If multiple -p arguments are specified, the last one will take effect." +
"If arguments other than -p are specified, Bazel will fall back to use patch " +
"command line tool instead of the Bazel-native patch implementation. When falling " +
"back to patch command line tool and patch_tool attribute is not specified, " +
"`patch` will be used.",
),
"patch_tool": attr.string(
default = "",
doc = "The patch(1) utility to use. If this is specified, Bazel will use the specifed " +
"patch tool instead of the Bazel-native patch implementation.",
),
"post_install_patches": attr.label_list(
doc = """Patch files to apply after running package manager.
This can be used to make changes to installed packages after the package manager runs.
File paths in patches should be relative to workspace root.""",
),
"pre_install_patches": attr.label_list(
doc = """Patch files to apply before running package manager.
This can be used to make changes to package.json or other data files passed in before running the
package manager.
File paths in patches should be relative to workspace root.""",
),
"quiet": attr.bool(
default = True,
Expand Down Expand Up @@ -205,6 +236,34 @@ data attribute.
),
})

def _apply_patches(repository_ctx, patches):
bash_exe = repository_ctx.os.environ["BAZEL_SH"] if "BAZEL_SH" in repository_ctx.os.environ else "bash"

patch_tool = repository_ctx.attr.patch_tool
if not patch_tool:
patch_tool = "patch"
patch_args = repository_ctx.attr.patch_args

for patchfile in patches:
command = "{patchtool} {patch_args} < {patchfile}".format(
patchtool = patch_tool,
patchfile = repository_ctx.path(patchfile),
patch_args = " ".join([
"'%s'" % arg
for arg in patch_args
]),
)
st = repository_ctx.execute(
[bash_exe, "-c", command],
quiet = repository_ctx.attr.quiet,
# Working directory is _ which is where all files are copied to and
# where the install is run; patches should be relative to workspace root.
working_directory = "_",
)
if st.return_code:
fail("Error applying patch %s:\n%s%s" %
(str(patchfile), st.stderr, st.stdout))

def _create_build_files(repository_ctx, rule_type, node, lock_file, generate_local_modules_build_files):
repository_ctx.report_progress("Processing node_modules: installing Bazel packages and generating BUILD files")
if repository_ctx.attr.manual_build_file_contents:
Expand Down Expand Up @@ -399,6 +458,7 @@ cd /D "{root}" && "{npm}" {npm_args}
_copy_data_dependencies(repository_ctx)
_add_scripts(repository_ctx)
_add_node_repositories_info_deps(repository_ctx)
_apply_patches(repository_ctx, repository_ctx.attr.pre_install_patches)

result = repository_ctx.execute(
[node, "pre_process_package_json.js", repository_ctx.path(repository_ctx.attr.package_json), "npm"],
Expand Down Expand Up @@ -439,6 +499,7 @@ cd /D "{root}" && "{npm}" {npm_args}
fail("remove_npm_absolute_paths failed: %s (%s)" % (result.stdout, result.stderr))

_symlink_node_modules(repository_ctx)
_apply_patches(repository_ctx, repository_ctx.attr.post_install_patches)

_create_build_files(repository_ctx, "npm_install", node, repository_ctx.attr.package_lock_json, repository_ctx.attr.generate_local_modules_build_files)

Expand Down Expand Up @@ -550,6 +611,7 @@ cd /D "{root}" && "{yarn}" {yarn_args}
_copy_data_dependencies(repository_ctx)
_add_scripts(repository_ctx)
_add_node_repositories_info_deps(repository_ctx)
_apply_patches(repository_ctx, repository_ctx.attr.pre_install_patches)

result = repository_ctx.execute(
[node, "pre_process_package_json.js", repository_ctx.path(repository_ctx.attr.package_json), "yarn"],
Expand All @@ -575,6 +637,7 @@ cd /D "{root}" && "{yarn}" {yarn_args}
fail("yarn_install failed: %s (%s)" % (result.stdout, result.stderr))

_symlink_node_modules(repository_ctx)
_apply_patches(repository_ctx, repository_ctx.attr.post_install_patches)

_create_build_files(repository_ctx, "yarn_install", node, repository_ctx.attr.yarn_lock, repository_ctx.attr.generate_local_modules_build_files)

Expand Down
9 changes: 9 additions & 0 deletions internal/npm_install/test/patches_npm/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
load("//:index.bzl", "nodejs_test")

nodejs_test(
name = "test",
data = [
"@internal_npm_install_test_patches_npm//semver",
],
entry_point = "test.js",
)
11 changes: 11 additions & 0 deletions internal/npm_install/test/patches_npm/package-lock.json

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

6 changes: 6 additions & 0 deletions internal/npm_install/test/patches_npm/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"dependencies": {
"__invalid_dependency__": "removed by pre_install_patches",
"semver": "1.0.0"
}
}
9 changes: 9 additions & 0 deletions internal/npm_install/test/patches_npm/package_json.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
--- internal/npm_install/test/patches_npm/package.json
+++ internal/npm_install/test/patches_npm/package.json
@@ -1,6 +1,5 @@
{
"dependencies": {
- "__invalid_dependency__": "removed by pre_install_patches",
"semver": "1.0.0"
}
}
10 changes: 10 additions & 0 deletions internal/npm_install/test/patches_npm/semver+1.0.0.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--- internal/npm_install/test/patches_npm/node_modules/semver/semver.js
+++ internal/npm_install/test/patches_npm/node_modules/semver/semver.js
@@ -34,6 +34,7 @@ exports.valid = valid
exports.validPackage = validPackage
exports.validRange = validRange
exports.maxSatisfying = maxSatisfying
+exports.patched = true

function clean (ver) {
v = exports.parse(ver)
5 changes: 5 additions & 0 deletions internal/npm_install/test/patches_npm/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const semver = require('semver')
if (!semver.patched) {
console.error('Expected semver to be patched');
process.exitCode = 1;
}
9 changes: 9 additions & 0 deletions internal/npm_install/test/patches_yarn/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
load("//:index.bzl", "nodejs_test")

nodejs_test(
name = "test",
data = [
"@internal_npm_install_test_patches_yarn//semver",
],
entry_point = "test.js",
)
6 changes: 6 additions & 0 deletions internal/npm_install/test/patches_yarn/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"dependencies": {
"__invalid_dependency__": "removed by pre_install_patches",
"semver": "1.0.0"
}
}
9 changes: 9 additions & 0 deletions internal/npm_install/test/patches_yarn/package_json.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
--- internal/npm_install/test/patches_yarn/package.json
+++ internal/npm_install/test/patches_yarn/package.json
@@ -1,6 +1,5 @@
{
"dependencies": {
- "__invalid_dependency__": "removed by pre_install_patches",
"semver": "1.0.0"
}
}
10 changes: 10 additions & 0 deletions internal/npm_install/test/patches_yarn/semver+1.0.0.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--- internal/npm_install/test/patches_yarn/node_modules/semver/semver.js
+++ internal/npm_install/test/patches_yarn/node_modules/semver/semver.js
@@ -34,6 +34,7 @@ exports.valid = valid
exports.validPackage = validPackage
exports.validRange = validRange
exports.maxSatisfying = maxSatisfying
+exports.patched = true

function clean (ver) {
v = exports.parse(ver)
5 changes: 5 additions & 0 deletions internal/npm_install/test/patches_yarn/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const semver = require('semver')
if (!semver.patched) {
console.error('Expected semver to be patched');
process.exitCode = 1;
}
8 changes: 8 additions & 0 deletions internal/npm_install/test/patches_yarn/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


[email protected]:
version "1.0.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-1.0.0.tgz#11f18a0c08ed21c988fc2b0257f1951969816615"
integrity sha1-EfGKDAjtIcmI/CsCV/GVGWmBZhU=

0 comments on commit d805f33

Please sign in to comment.