Skip to content
Draft
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
4 changes: 4 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ common --enable_platform_specific_config
common --downloader_config=bazel_downloader.cfg
common --@rules_zig//zig/settings:use_cc_common_link=true
common --@rules_zig//zig/settings:mode=release_fast
common --@rules_rust//rust/settings:codegen_units=1
common --@rules_rust//rust/settings:lto=fat
common --stripopt=--strip-all

common:linux --sandbox_add_mount_pair=/tmp
Expand All @@ -12,6 +14,8 @@ common --bes_backend=grpcs://remote.buildbuddy.io

common:remote --jobs=500
common:remote --extra_execution_platforms=@llvm//:rbe_platform
common:remote --platforms=@llvm//:rbe_platform
common:remote --@llvm//config:experimental_stub_libgcc_s=True
common:remote --noexperimental_throttle_remote_action_building
common:remote --remote_cache=grpcs://remote.buildbuddy.io
common:remote --remote_executor=grpcs://remote.buildbuddy.io
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/build_release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,24 @@ fi

bazel build "${bazel_flags[@]}" -c opt \
//cmd/darwin-actiond:darwin-actiond_macos_arm64 \
//cmd/linux-actiond:linux-actiond_linux_arm64 \
//cmd/linux-actiond:linux-actiond_linux_x86_64 \
//cmd/windows-actiond:windows-actiond_windows_arm64 \
//cmd/windows-actiond:windows-actiond_windows_x86_64

cp -f \
bazel-bin/cmd/darwin-actiond/darwin-actiond_macos_arm64/darwin-actiond_macos_arm64 \
bazel-bin/cmd/linux-actiond/linux-actiond_linux_arm64/linux-actiond_linux_arm64 \
bazel-bin/cmd/linux-actiond/linux-actiond_linux_x86_64/linux-actiond_linux_x86_64 \
bazel-bin/cmd/windows-actiond/windows-actiond_windows_arm64/windows-actiond_windows_arm64.exe \
bazel-bin/cmd/windows-actiond/windows-actiond_windows_x86_64/windows-actiond_windows_x86_64.exe \
"${artifact_dir}/"

cd "${artifact_dir}"
shasum -a 256 \
darwin-actiond_macos_arm64 \
linux-actiond_linux_arm64 \
linux-actiond_linux_x86_64 \
windows-actiond_windows_arm64.exe \
windows-actiond_windows_x86_64.exe \
> SHA256.txt
59 changes: 58 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ on:
- main
workflow_dispatch:

concurrency:
group: build-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
release-binaries:
name: Release binaries
Expand All @@ -24,6 +28,60 @@ jobs:
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
run: .github/workflows/build_release.sh release

linux-firecracker:
name: Linux Firecracker ${{ matrix.mode }} (${{ matrix.architecture }})
strategy:
fail-fast: false
matrix:
include:
- architecture: arm64
mode: build-only
runner: ubuntu-24.04-arm
- architecture: x86_64
mode: llvm-smoke
runner: ubuntu-24.04
runs-on: ${{ matrix.runner }}
timeout-minutes: 240

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Enable KVM
if: matrix.mode == 'llvm-smoke'
run: |
test -c /dev/kvm
sudo chmod a+rw /dev/kvm

- name: Build Linux ARM64 release
if: matrix.mode == 'build-only'
env:
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
run: |
bazel build --config=remote \
--remote_header="x-buildbuddy-api-key=$BUILDBUDDY_API_KEY" \
-c opt \
//cmd/linux-actiond:linux-actiond_linux_arm64

- name: Compare actiond and Linux host
if: matrix.mode == 'llvm-smoke'
env:
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
ACTIOND_REVISION: ${{ github.event.pull_request.head.sha || github.sha }}
ACTIOND_VM_CAS_IMAGE_SIZE_MIB: 8192
ACTIOND_VM_MEMORY_MIB: 4096
run: e2e/run_llvm_linux_vm_smoke.sh "$RUNNER_TEMP/actiond-linux-llvm-${{ matrix.architecture }}"

- name: Upload Linux LLVM smoke results
if: always() && matrix.mode == 'llvm-smoke'
uses: actions/upload-artifact@v4
with:
name: linux-firecracker-${{ matrix.mode }}-${{ matrix.architecture }}
if-no-files-found: warn
path: |
${{ runner.temp }}/actiond-linux-llvm-${{ matrix.architecture }}/*.md
${{ runner.temp }}/actiond-linux-llvm-${{ matrix.architecture }}/*.log

windows-llvm-smoke:
name: Windows ${{ matrix.mode }} (${{ matrix.architecture }})
strategy:
Expand All @@ -37,7 +95,6 @@ jobs:
- architecture: x86_64
mode: llvm-smoke
runner: windows-2025
extra_arguments: -Jobs 8
runs-on: ${{ matrix.runner }}
timeout-minutes: 180

Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ jobs:
fi
gh release upload "${TAG_NAME}" \
release/darwin-actiond_macos_arm64 \
release/linux-actiond_linux_arm64 \
release/linux-actiond_linux_x86_64 \
release/windows-actiond_windows_arm64.exe \
release/windows-actiond_windows_x86_64.exe \
release/SHA256.txt \
Expand Down
27 changes: 20 additions & 7 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Architecture

`actiond` is a local Remote Execution API worker and cache for Bazel. Its main
mode is `darwin-actiond serve-vm` or `windows-actiond serve-vm`: the host
process owns the public gRPC listener, starts a small Linux VM, and forwards
REAPI traffic into a Linux guest over virtio-vsock or Hyper-V sockets.
mode is `darwin-actiond serve-vm`, `windows-actiond serve-vm`, or
`linux-actiond serve-vm`: the host process owns the public gRPC listener,
starts a small Linux VM, and forwards REAPI traffic into a Linux guest over
virtio-vsock or Hyper-V sockets.

The design centers on three ideas:

Expand All @@ -18,7 +19,7 @@ Bazel
|
| gRPC / REAPI
v
darwin-actiond / windows-actiond
darwin-actiond / windows-actiond / linux-actiond
|
| TCP-to-virtio-vsock / TCP-to-AF_HYPERV bridge
v
Expand All @@ -32,7 +33,10 @@ guest ext4 disk mounted at /cas
On Windows, `windows-actiond` uses Host Compute System `LinuxKernelDirect`,
Hyper-V synthetic SCSI, and `AF_HYPERV`. Guest AF_VSOCK port 5001 maps to the
standard Hyper-V socket service GUID template. The Windows guest matches the
ARM64 or x86_64 host architecture; the macOS guest is ARM64.
ARM64 or x86_64 host architecture; the macOS guest is ARM64. On Linux,
`linux-actiond` uses Firecracker with KVM and PCI on ARM64 and x86_64.
Firecracker exposes the CAS and runtime images as virtio PCI block devices.
Firecracker exposes guest vsock connections through a host Unix socket.

In VM mode, the host does not keep a second CAS mirror. Uploads, downloads,
ActionCache requests, and Execute requests are forwarded to the guest. The
Expand All @@ -52,6 +56,15 @@ the matching Linux kernel, initramfs, and runtime SquashFS. At startup it
materializes those bytes under `--root`, wraps the runtime and CAS as fixed VHD
files, and starts the VM with Host Compute System.

`linux-actiond` is released for ARM64 and x86_64. Zig `@embedFile` includes the
matching Linux kernel, compressed initramfs, runtime SquashFS, and Firecracker
executable built from the pinned Firecracker 1.16.0 source. `linux-actiond`
writes each embedded file to a sealed memfd, generates the Firecracker config
in another sealed memfd, and executes Firecracker with `execveat`. The writable
CAS is the only disk-backed VM image. Firecracker uses KVM and PCI. The CAS
drive uses Firecracker's Async block I/O engine; the read-only runtime memfd
uses the Sync block I/O engine.

`linux-actiond-guest` lives in the initramfs. It runs as guest init, mounts the
minimal guest filesystems, mounts `/cas` and `/runtimes`, then execs itself as
the guest REAPI worker.
Expand All @@ -65,7 +78,7 @@ The VM is intentionally small:
- writable virtio or Hyper-V synthetic SCSI block device for `/cas`
- read-only virtio or Hyper-V synthetic SCSI block device for `/runtimes`
- virtio-vsock or `AF_HYPERV` for gRPC
- serial stderr for logs on macOS
- serial host logs on macOS and Linux
- no guest network device, SSH, systemd, package manager, graphics, or login

The VM is long-lived. Each action gets its own Linux process sandbox inside the
Expand Down Expand Up @@ -204,5 +217,5 @@ it is not the primary actiondfs performance benchmark.
- The REAPI surface is intentionally focused on the methods Bazel uses here.
- Remote cache compression is not supported yet.
- Cgroup limits are best-effort.
- VM mode is ARM64 Linux on Apple Silicon and architecture-matched Linux on Windows.
- VM mode is ARM64 Linux on Apple Silicon and architecture-matched Linux on Windows and Linux.
- Runtime selection is limited to the packaged glibc versions.
77 changes: 69 additions & 8 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ bazel_dep(name = "bazel_lib", version = "3.2.2")
bazel_dep(name = "rules_cc", version = "0.2.18")
bazel_dep(name = "rules_shell", version = "0.8.0")
bazel_dep(name = "platforms", version = "1.1.0")
bazel_dep(name = "llvm", version = "0.8.1")
bazel_dep(name = "llvm", version = "0.8.3")
bazel_dep(name = "linux.bzl", version = "0.0.3")
bazel_dep(name = "squashfs-tools", version = "4.7.5")
bazel_dep(name = "zstd", version = "1.5.7.bcr.1")
bazel_dep(name = "codesign.bzl", version = "0.0.13")
bazel_dep(name = "gawk", version = "5.3.2.bcr.3")
bazel_dep(name = "rules_rs", version = "0.0.86")

http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

Expand All @@ -26,6 +27,27 @@ http_archive(
urls = ["https://www.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/v1.47.4/e2fsprogs-1.47.4.tar.xz"],
)

http_archive(
name = "firecracker",
build_file = "//third_party/firecracker:firecracker.BUILD.bazel",
patch_args = ["-p1"],
patches = [
"//third_party/firecracker:firecracker_build_paths.patch",
"//third_party/firecracker:firecracker_no_uffd.patch",
],
sha256 = "70d800f6b5d5f380f12d16fbfccf7ec19e77fb13335d529b12e1a01b4d30b4bb",
strip_prefix = "firecracker-1.16.0",
urls = ["https://github.com/firecracker-microvm/firecracker/archive/refs/tags/v1.16.0.tar.gz"],
)

http_archive(
name = "libseccomp",
build_file = "//third_party/libseccomp:libseccomp.BUILD.bazel",
sha256 = "83b6085232d1588c379dc9b9cae47bb37407cf262e6e74993c61ba72d2a784dc",
strip_prefix = "libseccomp-2.6.0",
urls = ["https://github.com/seccomp/libseccomp/releases/download/v2.6.0/libseccomp-2.6.0.tar.gz"],
)

archive_override(
module_name = "linux.bzl",
integrity = "sha256-prh5lPs4P1Hl+EE00sdUaVAhgHj4ql3heA1a6/U4nZ4=",
Expand All @@ -37,7 +59,7 @@ single_version_override(
module_name = "llvm",
patch_strip = 1,
patches = ["//third_party/patches:llvm_musl_root_package_copy.patch"],
version = "0.8.1",
version = "0.8.3",
)

single_version_override(
Expand All @@ -54,8 +76,44 @@ use_repo(zig, "zig_toolchains")
register_toolchains("@zig_toolchains//:all")

register_toolchains("@llvm//toolchain:all")

register_toolchains("@codesign.bzl//toolchain:all")

rules_rust = use_extension("@rules_rs//rs:rules_rust.bzl", "rules_rust")
use_repo(rules_rust, "rules_rust")

rust_toolchains = use_extension("@rules_rs//rs/toolchains:module_extension.bzl", "toolchains")
rust_toolchains.toolchain(
edition = "2024",
version = "1.95.0",
)
use_repo(rust_toolchains, "default_rust_toolchains")

register_toolchains("@default_rust_toolchains//:all")

crate = use_extension("@rules_rs//rs:extensions.bzl", "crate")
crate.from_cargo(
name = "firecracker_crates",
cargo_lock = "@firecracker//:Cargo.lock",
cargo_toml = "@firecracker//:Cargo.toml",
platform_triples = [
"aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
"aarch64-unknown-linux-musl",
"x86_64-unknown-linux-gnu",
"x86_64-unknown-linux-musl",
],
)
crate.annotation(
build_script_env = {
"AWS_LC_SYS_CMAKE_BUILDER": "0",
"AWS_LC_SYS_CFLAGS": "-DMY_ASSEMBLER_IS_TOO_OLD_FOR_512AVX",
"AWS_LC_SYS_NO_JITTER_ENTROPY": "1",
},
crate = "aws-lc-sys",
gen_build_script = "on",
)

osx = use_extension("@llvm//extensions:osx.bzl", "osx")
osx.frameworks(names = [
"CoreFoundation",
Expand Down Expand Up @@ -93,6 +151,8 @@ llvm_project.configure(
)
use_repo(llvm_project, "llvm-project")

use_repo(crate, "firecracker_crates")

linux_kernel = use_extension("@linux.bzl//:linux.bzl", "linux_kernel")
linux_kernel.archive(
name = "linux_6_18_2",
Expand Down Expand Up @@ -145,6 +205,7 @@ use_repo(
)

glibc_deb_runtime = use_repo_rule("//runtimes:glibc_runtime_repo.bzl", "glibc_deb_runtime")

shell_deb_runtime = use_repo_rule("//runtimes:shell_runtime_repo.bzl", "shell_deb_runtime")

glibc_deb_runtime(
Expand All @@ -159,25 +220,25 @@ glibc_deb_runtime(
shell_deb_runtime(
name = "bash_5_1_aarch64",
arch = "aarch64",
sha256s = [
"57d782072eb479272f763c60b1a92956b05ef26583f78fcd35ab6ef6efccd926",
],
shell = "bash",
urls = [
"https://ports.ubuntu.com/ubuntu-ports/pool/universe/b/bash/bash-static_5.1-6ubuntu1_arm64.deb",
],
sha256s = [
"57d782072eb479272f763c60b1a92956b05ef26583f78fcd35ab6ef6efccd926",
],
)

shell_deb_runtime(
name = "bash_5_1_x86_64",
arch = "x86_64",
sha256s = [
"bacca4af0f72b83ebb9563b3adc28ceaf6ae019977900b999fcdbc240dca890a",
],
shell = "bash",
urls = [
"https://archive.ubuntu.com/ubuntu/pool/universe/b/bash/bash-static_5.1-6ubuntu1_amd64.deb",
],
sha256s = [
"bacca4af0f72b83ebb9563b3adc28ceaf6ae019977900b999fcdbc240dca890a",
],
)

glibc_deb_runtime(
Expand Down
Loading
Loading