Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions docs/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,32 @@

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

Use `nodejs_binary_archive` to create a tar and add that to the docker image.
Use `nodejs_binary_package` to create a tar and add that to the docker image.

# Example

```bzl
load("@better_rules_javascript//nodejs:rules.bzl", "nodejs_binary_archive")
load("@io_bazel_rules_docker//container:container.bzl", "container_image")
load("@better_rules_javascript//nodejs:rules.bzl", "nodejs_binary_package")
load("@rules_oci//oci:defs.bzl", "oci_image")

container_image(
oci_image(
name = "image",
base = "@base//image",
directory = "/opt/example",
base = "@base",
entrypoint = ["/usr/local/bin/example"],
tars = ["image_layer"],
)

pkg_tar(
name = "image_layer",
package_dir = "/opt/example",
symlinks = {
"/usr/local/bin/example": "/opt/example/bin",
},
tars = [":tar"],
# Merges these tars together into one layer
deps = [":tar"],
)

nodejs_binary_archive(
nodejs_binary_package(
name = "tar",
dep = ":lib",
main = "src/main.js",
Expand Down
37 changes: 36 additions & 1 deletion npm/workspace.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,45 @@ def _npm_import_external_impl(ctx, plugins):

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

patch_args = "--directory=npm --strip=1 --forward --reject-file=-"
for patch in ctx.attr.patches:
patch_result = ctx.execute([
"sh",
"-c",
"patch %s < %s" % (patch_args, ctx.path(patch)),
])

# Ignore return code 2, which signals the patch has already been applied
if patch_result.return_code != 0 and patch_result.return_code != 2:
fail("Could not apply patch %s: %s" % (patch, patch_result.stderr))

files_result = ctx.execute(["find", "npm", "-type", "f"])
if files_result.return_code:
fail("Could not list files")
files = [file[len("npm/"):] for file in files_result.stdout.split("\n")]

final_package_path = ctx.attr.package
if ctx.attr.patches:
tar_result = ctx.execute([
"tar",
"czf",
"patched-package.tgz",
"--strip-components=1",
"npm/",
])
if tar_result.return_code:
fail("Could not tar up patched-package.tgz")
final_package_path = "patched-package.tgz"

# Don't leave the package contents sitting around now that we're done. Bazel
# builds will always extract from the .tgz file, so anyone wanting to tinker
# should go poke at the .tgz.
ctx.execute(["rm", "-r", "npm/"])

build = ""

package = struct(
archive = ctx.attr.package,
archive = final_package_path,
deps = deps,
extra_deps = extra_deps,
name = package_name,
Expand Down Expand Up @@ -63,6 +93,10 @@ def npm_import_external_rule(plugins):
doc = "Package name.",
mandatory = True,
),
"patches": attr.label_list(
allow_files = True,
mandatory = True,
),
},
)

Expand Down Expand Up @@ -155,6 +189,7 @@ def npm(name, packages, roots, plugins = DEFAULT_PLUGINS, auth_patterns = None,
name = repo_name,
package = file,
package_name = package["name"],
patches = package.get("patches", []),
deps = [json.encode({"id": package_repo_name(name, dep["id"]), "name": dep.get("name")}) for dep in package["deps"]],
extra_deps = extra_deps,
)
Expand Down
14 changes: 12 additions & 2 deletions npm/yarn-resolve/src/bzl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface BzlPackage {
integrity: string;
name: string;
url: string;
patches: string[];
}

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

return new StarlarkDict([
const elements: [StarlarkValue, StarlarkValue][] = [
[new StarlarkString("deps"), BzlDeps.toStarlark(value.deps)],
[new StarlarkString("extra_deps"), new StarlarkDict(extraDepsEntries)],
[new StarlarkString("integrity"), new StarlarkString(value.integrity)],
[new StarlarkString("name"), new StarlarkString(value.name)],
[new StarlarkString("url"), new StarlarkString(value.url)],
]);
];
if (value.patches.length > 0) {
elements.push([
new StarlarkString("patches"),
new StarlarkArray(
value.patches.map((patchPath) => new StarlarkString(patchPath)),
),
]);
}
return new StarlarkDict(elements);
}
}

Expand Down
14 changes: 14 additions & 0 deletions npm/yarn-resolve/src/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export async function resolvePackages(
integrity: npmPackage.contentIntegrity,
name: structUtils.stringifyIdent(yarnPackage.locator),
url: npmPackage.contentUrl,
patches: extractPatchPaths(yarnPackage.locator),
});
finished++;
} else if (yarnPackage.locator.reference === "workspace:.") {
Expand Down Expand Up @@ -132,6 +133,19 @@ function npmLocator(locator: Locator): Locator | undefined {
}
}

function extractPatchPaths(locator: Locator): string[] {
return locator.reference.startsWith("patch:")
? patchUtils
.parseLocator(locator)
.patchPaths.filter((patchPath) => !patchPath.startsWith("~builtin"))
.map((patchPath) => {
// Replace final slash with a colon to make it a bazel label
const parts = patchPath.split("/");
return `//${parts.slice(0, -1).join("/")}:${parts.slice(-1)}`;
})
: [];
}

function bzlId(locator: Locator): string | undefined {
if (
locator.reference.startsWith("http:") ||
Expand Down
2 changes: 1 addition & 1 deletion util/starlark/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ function printValue(value: StarlarkValue, indent?: string | undefined): string {
if (value instanceof StarlarkString) {
return printString(value);
}
throw new Error("Unreognized value");
throw new Error("Unrecognized value");
}

function printVariable(value: StarlarkVariable): string {
Expand Down
Loading