Skip to content

Commit

Permalink
chore: open-source the vercel_pkg rule from silo
Browse files Browse the repository at this point in the history
Will reference it from a blog post about the fetching pattern used here
  • Loading branch information
alexeagle committed Jul 6, 2023
1 parent dee824c commit e205c14
Show file tree
Hide file tree
Showing 14 changed files with 1,318 additions and 0 deletions.
1 change: 1 addition & 0 deletions vercel_pkg/.bazelignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
1 change: 1 addition & 0 deletions vercel_pkg/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
common --enable_bzlmod
1 change: 1 addition & 0 deletions vercel_pkg/.bazelversion
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6.2.0
1 change: 1 addition & 0 deletions vercel_pkg/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
26 changes: 26 additions & 0 deletions vercel_pkg/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
load("@aspect_rules_ts//ts:defs.bzl", "ts_project")
load("@npm//:defs.bzl", "npm_link_all_packages")
load("//defs:vercel_pkg.bzl", "vercel_pkg")

npm_link_all_packages(name = "node_modules")

ts_project(
name = "transpile",
srcs = ["index.ts"],
)

# Make a self-contained binary so we don't rely on Node.js being installed on the system
vercel_pkg(
name = "example_build",
out = "example",
entry_point = "index.js",
# Ideally we would use Node 18, but it requires a newer glibc and therefore doesn't work with
# Ubuntu 18 or other earlier OS distros:
# https://github.com/nodejs/node/releases/tag/v18.0.0:
# Prebuilt binaries for Linux are now built on Red Hat Enterprise Linux (RHEL) 8 and are
# compatible with Linux distributions based on glibc 2.28 or later, for example,
# Debian 10, RHEL 8, Ubuntu 20.04.
# So we build a binary with Node 16 statically linked for wider distribution compat.
# Note, this means we cannot use newer APIs like native fetch.
node_major_version = 16,
)
35 changes: 35 additions & 0 deletions vercel_pkg/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"Bazel dependencies"
bazel_dep(name = "aspect_rules_js", version = "1.29.0")
bazel_dep(name = "aspect_rules_ts", version = "1.4.4")
bazel_dep(name = "bazel_skylib", version = "1.4.2")
bazel_dep(name = "platforms", version = "0.0.6")

npm = use_extension("@aspect_rules_js//npm:extensions.bzl", "npm", dev_dependency = True)

npm.npm_translate_lock(
name = "npm",
pnpm_lock = "//:pnpm-lock.yaml",
verify_node_modules_ignored = "//:.bazelignore",
)

use_repo(npm, "npm")

rules_ts_ext = use_extension(
"@aspect_rules_ts//ts:extensions.bzl",
"ext",
dev_dependency = True,
)

rules_ts_ext.deps()

use_repo(rules_ts_ext, "npm_typescript")

pkg_fetch = use_extension("//defs:vercel_pkg_fetch.bzl", "pkg_fetch")

use_repo(
pkg_fetch,
"pkg_fetch_node_linux_x64",
"pkg_fetch_node_linux_arm64",
"pkg_fetch_node_macos_x64",
"pkg_fetch_node_macos_arm64",
)
1 change: 1 addition & 0 deletions vercel_pkg/WORKSPACE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Marker that this folder is the root of a Bazel workspace.
23 changes: 23 additions & 0 deletions vercel_pkg/defs/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"Allow us to select() on the host platform"

[
config_setting(
name = "{}_{}".format(
os,
cpu,
),
constraint_values = [
"@platforms//os:{}".format(os),
"@platforms//cpu:{}".format(cpu),
],
visibility = ["//visibility:public"],
)
for os in [
"linux",
"macos",
]
for cpu in [
"aarch64",
"x86_64",
]
]
67 changes: 67 additions & 0 deletions vercel_pkg/defs/vercel_pkg.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""Bazel Macro to run https://github.com/vercel/pkg:
This command line interface enables you to package your Node.js project into an executable that can
be run even on devices without Node.js installed.
"""

load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
load("@npm//:pkg/package_json.bzl", pkg_bin = "bin")

# buildifier: disable=function-docstring
def vercel_pkg(name, entry_point, out, node_major_version, **kwargs):
# Walk back from the cwd we'll run the tool in, which is bazel-out/arch/bin/path/to/package
path_to_root = "/".join([".."] * (3 + len(native.package_name().split("/"))))

for platform in ["linux-arm64", "linux-x64", "macos-arm64", "macos-x64"]:
cache_folder = "@pkg_fetch_node_{}//file".format(platform.replace("-", "_"))
cache_folder_path = path_to_root + "/external/pkg_fetch_node_{}/file".format(platform.replace("-", "_"))
platform_out = "-".join([out, platform])
pkg_bin.pkg(
name = "_{}_{}".format(name, platform),
srcs = [
cache_folder,
entry_point,
],
copy_srcs_to_bin = False,
outs = [platform_out],
# See https://github.com/vercel/pkg#usage
args = [
entry_point,
# TODO: Compiling bytecode is non-deterministic, see
# https://github.com/vercel/pkg#bytecode-reproducibility
"--no-bytecode",
# Expose our source code in the executable, needed since we don't compile bytecode.
"--public",
"--targets",
"node{}-{}".format(node_major_version, platform),
"--output",
platform_out,
],
env = {
"CHDIR": native.package_name(),
"PKG_CACHE_PATH": cache_folder_path,
},
# Avoid fetching/building on platforms that won't be select'ed below.
target_compatible_with = [
"@platforms//os:linux" if platform.startswith("linux-") else "@platforms//os:macos",
"@platforms//cpu:x86_64" if platform.endswith("-x64") else "@platforms//cpu:arm64",
],
# Uncomment for debugging
# silent_on_success = False,
# Uncomment to allow the https://github.com/vercel/pkg-fetch tool to fetch nodejs packages
# rather than require that the PKG_CACHE already has them.
# tags = ["requires-network"],
)

copy_file(
name = name,
src = select({
"//defs:linux_aarch64": "{}-{}".format(out, "linux-arm64"),
"//defs:linux_x86_64": "{}-{}".format(out, "linux-x64"),
"//defs:macos_aarch64": "{}-{}".format(out, "macos-arm64"),
"//defs:macos_x86_64": "{}-{}".format(out, "macos-x64"),
}),
is_executable = True,
out = out,
**kwargs
)
53 changes: 53 additions & 0 deletions vercel_pkg/defs/vercel_pkg_fetch.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""Repository rules for https://github.com/vercel/pkg-fetch
This is a transitive dependency of vercel/pkg which we explicitly fetch with Bazel downloader
so that it doesn't fetch lazily when the action runs.
"""

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")

# The version can be found in the /pnpm-lock.yaml file:
# /pkg/5.8.1:
# ...
# pkg-fetch: 3.4.2
PKG_FETCH_VERSION = "3.4"

# Node versions mirrored into the pkg-fetch releases:
# https://github.com/vercel/pkg-fetch/releases/tag/v3.4
# TODO(#2631): should match our node_version in WORKSPACE nodejs_register_toolchains
PKG_FETCH_NODE_VERSION = "16.16.0"
PKG_FETCH_VENDORED_NODE = {
"c38f270d190fd1f5d8e74800b62408d06f4492720fec1fd46414a7f504114847": "alpine-arm64",
"2c4caf90c620f4839277edf8dfb4fd1d259294a2bfbed2b90bb6063a6e0c9d23": "alpine-x64",
"e3913ecef725f83ccbd2181d7d33043f8b3e72466d09897c338ee328cffc3bfe": "linux-arm64",
"f1a561aadf78e438e73b043a3c5d7b9fe075d7abcaaec6f29d9e2a0ba00d3a69": "linux-x64",
"aac0039a2b380057085a4b927637c6e5550eabfd55d1ca2f98e022abccfd7390": "linuxstatic-arm64",
"cbe14ff111fd3d1ecb82cf6aaec5a53588537008fdcfab4bc2c880d651f5580a": "linuxstatic-armv7",
"8a888553a4855f3b01ea91a398eb3112b0d5f58f5f0112e9fecf6621615201ce": "linuxstatic-x64",
"d9140eebaa88620b9692d6e11cc2d92b2b56f791a6bbeddd771f5e07d042e1bc": "macos-arm64",
"321fcef798383c6e19d7ae242bc73dd1f1c7471499b00ee6b105c764645d9263": "macos-x64",
"e078fd200f6f0cd2e84ba668711a5cc9c7f0d20d36fae1bfe4bc361f40f5923f": "win-arm64",
"b6c5f9a5bce3b451b6d59153eae6db1a87016edc3775ef9eae39f86485735672": "win-x64",
}

def pkg_fetch_deps(_):
for (sha256, platform) in PKG_FETCH_VENDORED_NODE.items():
http_file(
name = "pkg_fetch_node_{}".format(platform.replace("-", "_")),
# Match the path of what the `pkg` program would do dynamically.
downloaded_file_path = "v{}/fetched-v{}-{}".format(
PKG_FETCH_VERSION,
PKG_FETCH_NODE_VERSION,
platform,
),
sha256 = sha256,
urls = ["https://github.com/vercel/pkg-fetch/releases/download/v{}/node-v{}-{}".format(
PKG_FETCH_VERSION,
PKG_FETCH_NODE_VERSION,
platform,
)],
)

pkg_fetch = module_extension(
implementation = pkg_fetch_deps,
)
1 change: 1 addition & 0 deletions vercel_pkg/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('hello world!');
5 changes: 5 additions & 0 deletions vercel_pkg/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"devDependencies": {
"pkg": "^5.8.1"
}
}
Loading

0 comments on commit e205c14

Please sign in to comment.