Skip to content

Commit ac732f5

Browse files
authored
Merge pull request #13 from rivethealth/Nevada/support-patches-for-npm
Support patches for npm
2 parents 65f4339 + b8919bb commit ac732f5

File tree

5 files changed

+77
-12
lines changed

5 files changed

+77
-12
lines changed

docs/docker.md

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,32 @@
77

88
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
99

10-
Use `nodejs_binary_archive` to create a tar and add that to the docker image.
10+
Use `nodejs_binary_package` to create a tar and add that to the docker image.
1111

1212
# Example
1313

1414
```bzl
15-
load("@better_rules_javascript//nodejs:rules.bzl", "nodejs_binary_archive")
16-
load("@io_bazel_rules_docker//container:container.bzl", "container_image")
15+
load("@better_rules_javascript//nodejs:rules.bzl", "nodejs_binary_package")
16+
load("@rules_oci//oci:defs.bzl", "oci_image")
1717

18-
container_image(
18+
oci_image(
1919
name = "image",
20-
base = "@base//image",
21-
directory = "/opt/example",
20+
base = "@base",
2221
entrypoint = ["/usr/local/bin/example"],
22+
tars = ["image_layer"],
23+
)
24+
25+
pkg_tar(
26+
name = "image_layer",
27+
package_dir = "/opt/example",
2328
symlinks = {
2429
"/usr/local/bin/example": "/opt/example/bin",
2530
},
26-
tars = [":tar"],
31+
# Merges these tars together into one layer
32+
deps = [":tar"],
2733
)
2834

29-
nodejs_binary_archive(
35+
nodejs_binary_package(
3036
name = "tar",
3137
dep = ":lib",
3238
main = "src/main.js",

npm/workspace.bzl

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,45 @@ def _npm_import_external_impl(ctx, plugins):
1919

2020
ctx.execute(["rm", "-r", "tmp"])
2121

22+
patch_args = "--directory=npm --strip=1 --forward --reject-file=-"
23+
for patch in ctx.attr.patches:
24+
patch_result = ctx.execute([
25+
"sh",
26+
"-c",
27+
"patch %s < %s" % (patch_args, ctx.path(patch)),
28+
])
29+
30+
# Ignore return code 2, which signals the patch has already been applied
31+
if patch_result.return_code != 0 and patch_result.return_code != 2:
32+
fail("Could not apply patch %s: %s" % (patch, patch_result.stderr))
33+
2234
files_result = ctx.execute(["find", "npm", "-type", "f"])
2335
if files_result.return_code:
2436
fail("Could not list files")
2537
files = [file[len("npm/"):] for file in files_result.stdout.split("\n")]
2638

39+
final_package_path = ctx.attr.package
40+
if ctx.attr.patches:
41+
tar_result = ctx.execute([
42+
"tar",
43+
"czf",
44+
"patched-package.tgz",
45+
"--strip-components=1",
46+
"npm/",
47+
])
48+
if tar_result.return_code:
49+
fail("Could not tar up patched-package.tgz")
50+
final_package_path = "patched-package.tgz"
51+
52+
# Don't leave the package contents sitting around now that we're done. Bazel
53+
# builds will always extract from the .tgz file, so anyone wanting to tinker
54+
# should go poke at the .tgz.
55+
ctx.execute(["rm", "-r", "npm/"])
56+
2757
build = ""
2858

2959
package = struct(
30-
archive = ctx.attr.package,
60+
archive = final_package_path,
3161
deps = deps,
3262
extra_deps = extra_deps,
3363
name = package_name,
@@ -63,6 +93,10 @@ def npm_import_external_rule(plugins):
6393
doc = "Package name.",
6494
mandatory = True,
6595
),
96+
"patches": attr.label_list(
97+
allow_files = True,
98+
mandatory = True,
99+
),
66100
},
67101
)
68102

@@ -155,6 +189,7 @@ def npm(name, packages, roots, plugins = DEFAULT_PLUGINS, auth_patterns = None,
155189
name = repo_name,
156190
package = file,
157191
package_name = package["name"],
192+
patches = package.get("patches", []),
158193
deps = [json.encode({"id": package_repo_name(name, dep["id"]), "name": dep.get("name")}) for dep in package["deps"]],
159194
extra_deps = extra_deps,
160195
)

npm/yarn-resolve/src/bzl.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface BzlPackage {
1414
integrity: string;
1515
name: string;
1616
url: string;
17+
patches: string[];
1718
}
1819

1920
export namespace BzlPackage {
@@ -26,13 +27,22 @@ export namespace BzlPackage {
2627
extraDepsEntries.push([new StarlarkString(id), BzlDeps.toStarlark(deps)]);
2728
}
2829

29-
return new StarlarkDict([
30+
const elements: [StarlarkValue, StarlarkValue][] = [
3031
[new StarlarkString("deps"), BzlDeps.toStarlark(value.deps)],
3132
[new StarlarkString("extra_deps"), new StarlarkDict(extraDepsEntries)],
3233
[new StarlarkString("integrity"), new StarlarkString(value.integrity)],
3334
[new StarlarkString("name"), new StarlarkString(value.name)],
3435
[new StarlarkString("url"), new StarlarkString(value.url)],
35-
]);
36+
];
37+
if (value.patches.length > 0) {
38+
elements.push([
39+
new StarlarkString("patches"),
40+
new StarlarkArray(
41+
value.patches.map((patchPath) => new StarlarkString(patchPath)),
42+
),
43+
]);
44+
}
45+
return new StarlarkDict(elements);
3646
}
3747
}
3848

npm/yarn-resolve/src/resolve.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export async function resolvePackages(
8484
integrity: npmPackage.contentIntegrity,
8585
name: structUtils.stringifyIdent(yarnPackage.locator),
8686
url: npmPackage.contentUrl,
87+
patches: extractPatchPaths(yarnPackage.locator),
8788
});
8889
finished++;
8990
} else if (yarnPackage.locator.reference === "workspace:.") {
@@ -132,6 +133,19 @@ function npmLocator(locator: Locator): Locator | undefined {
132133
}
133134
}
134135

136+
function extractPatchPaths(locator: Locator): string[] {
137+
return locator.reference.startsWith("patch:")
138+
? patchUtils
139+
.parseLocator(locator)
140+
.patchPaths.filter((patchPath) => !patchPath.startsWith("~builtin"))
141+
.map((patchPath) => {
142+
// Replace final slash with a colon to make it a bazel label
143+
const parts = patchPath.split("/");
144+
return `//${parts.slice(0, -1).join("/")}:${parts.slice(-1)}`;
145+
})
146+
: [];
147+
}
148+
135149
function bzlId(locator: Locator): string | undefined {
136150
if (
137151
locator.reference.startsWith("http:") ||

util/starlark/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ function printValue(value: StarlarkValue, indent?: string | undefined): string {
9898
if (value instanceof StarlarkString) {
9999
return printString(value);
100100
}
101-
throw new Error("Unreognized value");
101+
throw new Error("Unrecognized value");
102102
}
103103

104104
function printVariable(value: StarlarkVariable): string {

0 commit comments

Comments
 (0)