diff --git a/.github/workflows/build-runner-binary.yml b/.github/workflows/build-runner-binary.yml index 4fe736f4b..ee90a6810 100644 --- a/.github/workflows/build-runner-binary.yml +++ b/.github/workflows/build-runner-binary.yml @@ -67,6 +67,9 @@ jobs: curl -fsSL "${URL}" | tar xz -C /tmp/ cp "/tmp/boxlite-c-v${VERSION}-linux-x64-gnu/lib/libboxlite.a" sdks/go/libboxlite.a + - name: Smoke-test libboxlite ABI for Go SDK + run: bash scripts/build/check-libboxlite-abi.sh sdks/go/libboxlite.a + - name: Rewrite go.work for minimal modules run: | printf 'go 1.25.4\n\nuse (\n\t./runner\n\t./daemon\n\t./common-go\n\t./api-client-go\n\t./libs/computer-use\n\t../sdks/go\n)\n' > apps/go.work diff --git a/make/dist.mk b/make/dist.mk index f2f7d0877..0c1e7fd63 100644 --- a/make/dist.mk +++ b/make/dist.mk @@ -38,4 +38,11 @@ dist\:go: @echo "📦 Building Go SDK (release)..." @cargo build --release -p boxlite-c @bash $(SCRIPT_DIR)/build/fix-go-symbols.sh target/release/libboxlite.a + @bash $(SCRIPT_DIR)/build/check-libboxlite-abi.sh target/release/libboxlite.a + @cp target/release/libboxlite.a sdks/go/libboxlite.a + @go clean -cache + @echo "✅ Go SDK static library staged at sdks/go/libboxlite.a" @echo "✅ Go SDK release built" + +dist\:runner: + @bash $(SCRIPT_DIR)/build/build-runner-binary.sh diff --git a/make/help.mk b/make/help.mk index e1402164d..5d1543eb1 100644 --- a/make/help.mk +++ b/make/help.mk @@ -75,6 +75,7 @@ help: @echo " make dist:c - Build C SDK release and stage to sdks/c/dist/" @echo " make dist:node - Build npm package with napi-rs" @echo " make dist:go - Build Go SDK release" + @echo " make dist:runner - Build local runner release artifact without deploying" @echo "" @echo "Platform: $$(uname) ($$(uname -m))" @echo "" diff --git a/scripts/build/build-runner-binary.sh b/scripts/build/build-runner-binary.sh new file mode 100755 index 000000000..7dd98a13a --- /dev/null +++ b/scripts/build/build-runner-binary.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# Build a local Linux amd64 runner release artifact without deploying it. + +set -euo pipefail + +SCRIPT_BUILD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SCRIPT_DIR="$(cd "$SCRIPT_BUILD_DIR/.." && pwd)" +source "$SCRIPT_DIR/common.sh" + +REPO_ROOT="$PROJECT_ROOT" +VERSION="${VERSION:-$(grep -m 1 '^version' "$REPO_ROOT/Cargo.toml" | sed -E 's/^version *= *"([^"]+)".*/\1/')}" +COMMIT="${COMMIT:-$(git -C "$REPO_ROOT" rev-parse --short HEAD)}" +OUTPUT_DIR="${OUTPUT_DIR:-$REPO_ROOT/dist/runner-release}" +RUNNER_BIN="$OUTPUT_DIR/boxlite-runner" +RUNNER_TARBALL="$OUTPUT_DIR/boxlite-runner-v${VERSION}-linux-amd64-${COMMIT}.tar.gz" + +if [[ -z "$VERSION" ]]; then + print_error "Could not read version from $REPO_ROOT/Cargo.toml" + exit 1 +fi + +if [[ "$(detect_os)" != "linux" ]]; then + print_error "Runner release artifacts must be built on Linux because the binary uses cgo" + exit 1 +fi + +require_command git "Install git" +require_command go "Install Go" +require_command tar "Install tar" +require_command sha256sum "Install coreutils" + +if [[ "${SKIP_SUBMODULE_UPDATE:-0}" != "1" ]]; then + print_section "Updating submodules" + git -C "$REPO_ROOT" submodule update --init --recursive +fi + +print_section "Building and validating Go SDK static library" +make -C "$REPO_ROOT" dist:go +bash "$SCRIPT_BUILD_DIR/check-libboxlite-abi.sh" "$REPO_ROOT/sdks/go/libboxlite.a" + +print_section "Building embedded daemon assets" +cd "$REPO_ROOT/apps" +CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \ + go build \ + -ldflags "-X github.com/boxlite-ai/daemon/internal.Version=${VERSION}" \ + -o "$REPO_ROOT/apps/runner/pkg/daemon/static/daemon-amd64" \ + ./daemon/cmd/daemon/ + +CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \ + go build \ + -o "$REPO_ROOT/apps/runner/pkg/daemon/static/boxlite-computer-use" \ + ./libs/computer-use/ + +print_section "Building runner" +mkdir -p "$OUTPUT_DIR" +CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \ + go build \ + -ldflags "-X github.com/boxlite-ai/runner/internal.Version=${VERSION}" \ + -o "$RUNNER_BIN" \ + ./runner/cmd/runner/ + +tar -C "$OUTPUT_DIR" -czf "$RUNNER_TARBALL" "$(basename "$RUNNER_BIN")" + +print_success "Runner artifact built" +echo "binary: $RUNNER_BIN" +echo "tarball: $RUNNER_TARBALL" +sha256sum "$RUNNER_BIN" "$RUNNER_TARBALL" diff --git a/scripts/build/check-libboxlite-abi.sh b/scripts/build/check-libboxlite-abi.sh new file mode 100755 index 000000000..99b42c477 --- /dev/null +++ b/scripts/build/check-libboxlite-abi.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +# Smoke-test the C ABI used by the Go SDK prebuilt static library. + +set -euo pipefail + +SCRIPT_BUILD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SCRIPT_DIR="$(cd "$SCRIPT_BUILD_DIR/.." && pwd)" +source "$SCRIPT_DIR/common.sh" + +LIB="${1:-target/release/libboxlite.a}" +REPO_ROOT="$PROJECT_ROOT" + +if [[ "$LIB" != /* ]]; then + LIB="$REPO_ROOT/$LIB" +fi + +if [[ ! -f "$LIB" ]]; then + print_error "Library not found: $LIB" + exit 1 +fi + +require_command cc "Install a C compiler" + +TMP_DIR="$(mktemp -d)" +trap 'rm -rf "$TMP_DIR"' EXIT + +PROBE_C="$TMP_DIR/check-libboxlite-abi.c" +PROBE_BIN="$TMP_DIR/check-libboxlite-abi" + +cat > "$PROBE_C" <<'C' +#include "boxlite.h" +#include + +int main(void) { + CBoxliteOptions *opts = NULL; + CBoxliteError err = {0}; + + enum BoxliteErrorCode new_code = boxlite_options_new( + "ghcr.io/boxlite-ai/boxlite-agent-base:latest", + &opts, + &err + ); + enum BoxliteErrorCode port_code = boxlite_options_add_port( + opts, + 33689, + 2280, + BoxlitePortProtocolTcp, + NULL + ); + + printf("new=%d add_port=%d\n", (int)new_code, (int)port_code); + if (opts != NULL) { + boxlite_options_free(opts); + } + + return (new_code == Ok && port_code == Ok) ? 0 : 1; +} +C + +OS="$(detect_os)" +case "$OS" in + linux) + LINK_FLAGS=(-lresolv -lpthread -ldl -lrt -lm) + ;; + macos) + LINK_FLAGS=(-framework CoreFoundation -framework Security -framework IOKit -framework Hypervisor -framework vmnet -lresolv) + ;; + *) + print_error "Unsupported platform: $(uname -s)" + exit 1 + ;; +esac + +cc -I"$REPO_ROOT/sdks/c/include" "$PROBE_C" "$LIB" "${LINK_FLAGS[@]}" -o "$PROBE_BIN" + +set +e +OUTPUT="$("$PROBE_BIN" 2>&1)" +STATUS=$? +set -e +echo "$OUTPUT" + +if [[ "$STATUS" -ne 0 || "$OUTPUT" != "new=0 add_port=0" ]]; then + print_error "libboxlite ABI smoke check failed for $LIB" + exit 1 +fi + +print_success "libboxlite ABI smoke check passed for $LIB" diff --git a/scripts/deploy/runner-update-binary.sh b/scripts/deploy/runner-update-binary.sh index 2a372eadf..bc5eb97a1 100755 --- a/scripts/deploy/runner-update-binary.sh +++ b/scripts/deploy/runner-update-binary.sh @@ -15,6 +15,9 @@ # scripts/deploy/runner-update-binary.sh 0.9.5 # explicit version # AWS_REGION=us-west-2 scripts/deploy/runner-update-binary.sh # STAGE=production scripts/deploy/runner-update-binary.sh +# +# For unreleased main builds, use `make dist:runner` first to create a local +# artifact. This script intentionally downloads published GitHub release assets. set -euo pipefail