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
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ docs/
# NOT examples/: sandd/Cargo.toml declares [[example]] targets at ../examples/*.rs,
# and cargo parses every workspace member's manifest even when building one package.
# Excluding this directory makes the workspace fail to parse in any image that builds
# from source (Dockerfile.controller, Dockerfile.server-tunnel).
# from source (e.g. Dockerfile.server-tunnel).
python/tests/
25 changes: 3 additions & 22 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,33 +24,16 @@ jobs:
- runner: ubuntu-22.04
target: x86_64-unknown-linux-musl
asset: sandd-linux-amd64
package: sandd
bin: sandd
- runner: ubuntu-22.04-arm
target: aarch64-unknown-linux-musl
asset: sandd-linux-arm64
package: sandd
bin: sandd
# No Intel-mac (x86_64-apple-darwin) leg: GitHub is retiring the
# macos-13 (Intel) runners, so that job queues indefinitely and — with
# `release` gated on `needs: build` — blocks the whole release from
# publishing. Apple Silicon (macos-14/arm64) covers modern Macs.
- runner: macos-14
target: aarch64-apple-darwin
asset: sandd-darwin-arm64
package: sandd
bin: sandd
# THE DAEMON ONLY. There is deliberately no sandd-controller asset and no
# controller image: the controller is not a deployed artifact any more. Its
# only consumer, Nebula, compiles it INTO its manager process through the C
# ABI (server/src/ffi.rs), because a daemon's connection is a live socket
# owned by whichever process accepted it — so reaching back into a workload
# from a separate controller process would mean relaying.
#
# `cargo build --bin sandd-controller` and `make docker-build-controller`
# still work for anyone who wants to run it standalone. They are just not
# release artifacts, and publishing them would imply a supported deployment
# shape that nothing uses.
steps:
- uses: actions/checkout@v4

Expand All @@ -64,13 +47,11 @@ jobs:
if: endsWith(matrix.target, '-musl')
run: sudo apt-get update && sudo apt-get install -y musl-tools

- name: Build ${{ matrix.bin }}
run: |
cargo build --package ${{ matrix.package }} --bin ${{ matrix.bin }} \
--release --locked --target ${{ matrix.target }}
- name: Build daemon
run: cargo build --package sandd --release --locked --target ${{ matrix.target }}

- name: Rename binary
run: mv target/${{ matrix.target }}/release/${{ matrix.bin }} ${{ matrix.asset }}
run: mv target/${{ matrix.target }}/release/sandd ${{ matrix.asset }}

- name: Verify static linking
if: endsWith(matrix.target, '-musl')
Expand Down
1 change: 0 additions & 1 deletion Cargo.lock

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

80 changes: 4 additions & 76 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ MATURIN := .venv/bin/maturin
# Pinned so lint results don't shift when ruff changes its default rule set.
RUFF_VERSION := ruff==0.15.15

.PHONY: help build install dev test clean daemon-build daemon-release controller-build controller-release test-e2e test-e2e-tunnel docker-build docker-down
.PHONY: help build install dev test clean daemon-build daemon-release test-e2e test-e2e-tunnel docker-build docker-down

help:
@echo "SandD - Sandbox Daemon - Build Commands"
Expand All @@ -18,17 +18,10 @@ help:
@echo " make test-e2e-tunnel - Run tunnel-mode (Tailscale mesh) e2e tests (slow)"
@echo " make daemon-build - Build daemon binary (debug)"
@echo " make daemon-release - Build daemon binary (release)"
@echo " make controller-build - Build controller binary (debug)"
@echo " make controller-release - Build controller binary (release)"
@echo " make docker-build - Build Docker image for daemon"
@echo " make docker-down - Stop and remove Docker containers"
@echo " make clean - Clean build artifacts"
@echo ""
@echo "Controller image (native Rust binary — what Nebula runs):"
@echo " make docker-build-controller - Build both arches (no push)"
@echo " make docker-build-controller-local - Build host arch only, load locally"
@echo " make docker-push-controller - Build both arches and push a manifest"
@echo ""
@echo "Tunnel server (Python-hosted controller) image — multi-arch (amd64 + arm64):"
@echo " make docker-build-server-tunnel - Build both arches (no push)"
@echo " make docker-build-server-tunnel-local - Build host arch only, load locally"
Expand All @@ -47,11 +40,8 @@ test: lint $(PYTEST) dev
@echo "Running Rust tests (daemon)..."
cargo test --package sandd
@echo ""
@echo "Running Rust tests (controller: lib + binary)..."
# NOT --lib: that skips src/main.rs, where the controller's config/flag rules and
# the "auth on but material missing must be FATAL" tests live. --no-default-features
# is implicit (python is off by default), which is also what the bin target needs.
cargo test --package sandbox-server --lib --bins
@echo "Running Rust tests (controller)..."
cargo test --package sandbox-server --lib
@echo ""
@echo "Running Python tests (excluding e2e)..."
$(PYTEST) python/tests/ -m "not e2e"
Expand All @@ -64,17 +54,6 @@ daemon-release:
@echo ""
@echo "SandD binary built at: ./target/release/sandd"

# The CONTROLLER binary — what Nebula runs, one Deployment per workload. No
# --features python: the pyo3 layer must stay out or the bin cannot link at all
# (extension-module leaves the CPython symbols undefined). See server/Cargo.toml.
controller-build:
cargo build --package sandbox-server --bin sandd-controller

controller-release:
cargo build --package sandbox-server --bin sandd-controller --release
@echo ""
@echo "SandD controller binary built at: ./target/release/sandd-controller"

clean:
cargo clean
rm -rf target/
Expand Down Expand Up @@ -114,61 +93,10 @@ docker-up:
docker-down:
docker compose -f hack/docker/docker-compose.e2e.yml down

# --- Controller image (native Rust binary) -------------------------------------
#
# For running the controller STANDALONE. Nebula does not pull this: it links the
# controller into its own manager through the C ABI (server/src/ffi.rs), so there is
# no controller Deployment and no image to pin. Nothing publishes this image either
# — the release workflow ships the daemon binaries only.
#
# Distroless + one static-ish binary, ~50MB against the ~4GB server-tunnel image
# below, because it carries no interpreter, no rustup and no Tailscale client.
#
# Multi-arch for the same reason as every other image here (see the note below):
# built on arm64 Macs, deployed to mostly-amd64 nodes.
CONTROLLER_IMG ?= inftyai/sandd-controller
CONTROLLER_TAG ?= latest

.PHONY: docker-build-controller
docker-build-controller: buildx-builder
docker buildx build \
--builder $(BUILDX_BUILDER) \
--platform $(PLATFORMS) \
-f hack/docker/Dockerfile.controller \
-t $(CONTROLLER_IMG):$(CONTROLLER_TAG) \
.

# Host arch only, loaded into the local docker store so it can actually be run
# (`docker run --rm $(CONTROLLER_IMG):$(CONTROLLER_TAG) --help`). A multi-platform
# build cannot be --load'ed: the local store holds one arch per tag.
.PHONY: docker-build-controller-local
docker-build-controller-local: buildx-builder
docker buildx build \
--builder $(BUILDX_BUILDER) \
-f hack/docker/Dockerfile.controller \
-t $(CONTROLLER_IMG):$(CONTROLLER_TAG) \
--load \
.

.PHONY: docker-push-controller
docker-push-controller: buildx-builder
docker buildx build \
--builder $(BUILDX_BUILDER) \
--platform $(PLATFORMS) \
-f hack/docker/Dockerfile.controller \
-t $(CONTROLLER_IMG):$(CONTROLLER_TAG) \
--push \
.
@echo ""
@echo "Pushed $(CONTROLLER_IMG):$(CONTROLLER_TAG) for $(PLATFORMS)"
@echo "Verify the manifest lists both arches:"
@echo " docker buildx imagetools inspect $(CONTROLLER_IMG):$(CONTROLLER_TAG)"

# --- Tunnel server (controller) image ------------------------------------------
#
# The PYTHON-hosted controller, kept for the tunnel/mesh e2e stacks and for driving a
# controller from Python (`from sandd import Server`). Nebula uses the native binary
# above instead — no Python drives its controllers and it does not use the mesh.
# controller from Python (`from sandd import Server`).
#
# The controller image must run on BOTH architectures: it is developed on arm64
# Macs but deployed to clusters whose nodes are usually amd64 (and increasingly
Expand Down
Loading
Loading