solstice-ci/.mise/tasks/ci/vm-build
Till Wegmueller 0b54881558
Add support for multi-OS VM builds with cross-built runners and improved local development tooling
This commit introduces:
- Flexible runner URL configuration via `SOLSTICE_RUNNER_URL(S)` for cloud-init.
- Automated detection of OS-specific runner binaries during VM boot.
- Tasks for cross-building, serving, and orchestrating Solstice runners.
- End-to-end VM build flows for Linux and Illumos environments.
- Enhanced orchestration with multi-runner HTTP serving and log streaming.
2025-11-01 14:31:48 +01:00

116 lines
4.1 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
# Build this repository inside Linux and Illumos VMs using the Solstice dev loop.
# - Cross-build runner for both targets
# - Serve both runner binaries locally
# - Start orchestrator and enqueue two jobs (ubuntu-22.04, illumos-latest)
# - Each VM will download the appropriate runner and execute .solstice/job.sh from this repo
ROOT_DIR=$(cd "$(dirname "$0")/../../.." && pwd)
cd "$ROOT_DIR"
# Requirements check
command -v cargo >/dev/null 2>&1 || { echo "cargo is required" >&2; exit 127; }
command -v cross >/dev/null 2>&1 || { echo "cross is required (cargo install cross)" >&2; exit 127; }
# Defaults
export RUST_LOG=${RUST_LOG:-info}
export ORCH_CONFIG=${ORCH_CONFIG:-examples/orchestrator-image-map.yaml}
export AMQP_URL=${AMQP_URL:-amqp://127.0.0.1:5672/%2f}
export AMQP_EXCHANGE=${AMQP_EXCHANGE:-solstice.jobs}
export AMQP_QUEUE=${AMQP_QUEUE:-solstice.jobs.v1}
export AMQP_ROUTING_KEY=${AMQP_ROUTING_KEY:-jobrequest.v1}
export AMQP_PREFETCH=${AMQP_PREFETCH:-2}
export GRPC_ADDR=${GRPC_ADDR:-0.0.0.0:50051}
# Detect host IP for guest access (virbr0 first)
if command -v ip >/dev/null 2>&1 && ip addr show virbr0 >/dev/null 2>&1; then
HOST_IP=$(ip -o -4 addr show virbr0 | awk '{print $4}' | cut -d/ -f1 | head -n1)
else
HOST_IP=${HOST_IP_OVERRIDE:-127.0.0.1}
fi
# Orchestrator contact address for gRPC log streaming from guests
export ORCH_CONTACT_ADDR=${ORCH_CONTACT_ADDR:-$HOST_IP:50051}
# Bring up RabbitMQ
"$ROOT_DIR/.mise/tasks/dev/up"
# Ensure cleanup
ORCH_PID=""
SERVE_PID=""
cleanup() {
set +e
if [[ -n "$ORCH_PID" ]] && kill -0 "$ORCH_PID" 2>/dev/null; then
echo "Stopping orchestrator (pid=$ORCH_PID)" >&2
kill "$ORCH_PID" 2>/dev/null || true
sleep 1
kill -9 "$ORCH_PID" 2>/dev/null || true
fi
if [[ -n "$SERVE_PID" ]] && kill -0 "$SERVE_PID" 2>/dev/null; then
echo "Stopping runner servers (pid=$SERVE_PID)" >&2
kill "$SERVE_PID" 2>/dev/null || true
fi
"$ROOT_DIR/.mise/tasks/dev/down" || true
}
trap cleanup EXIT INT TERM
# Cross-build runner for both targets
"$ROOT_DIR/.mise/tasks/build/runner-cross"
# Start multi runner servers (background)
SOL_RUNNER_PORT_LINUX=${SOL_RUNNER_PORT_LINUX:-8090}
SOL_RUNNER_PORT_ILLUMOS=${SOL_RUNNER_PORT_ILLUMOS:-8091}
(
exec "$ROOT_DIR/.mise/tasks/run/runner-serve-multi" >/dev/null 2>&1
) &
SERVE_PID=$!
# Compose URLs for both OSes and export for orchestrator cloud-init consumption
LINUX_URL="http://$HOST_IP:$SOL_RUNNER_PORT_LINUX/solstice-runner-linux"
ILLUMOS_URL="http://$HOST_IP:$SOL_RUNNER_PORT_ILLUMOS/solstice-runner-illumos"
export SOLSTICE_RUNNER_URLS="$LINUX_URL $ILLUMOS_URL"
# Start orchestrator in background (inherits env including SOLSTICE_RUNNER_URLS/ORCH_CONTACT_ADDR)
LOGFILE=${SOL_ORCH_LOG:-"$ROOT_DIR/target/orchestrator.vm-build.log"}
echo "Starting orchestrator... (logs: $LOGFILE)" >&2
(
exec "$ROOT_DIR/.mise/tasks/run/orchestrator" >"$LOGFILE" 2>&1
) &
ORCH_PID=$!
echo "Runner URLs:" >&2
echo " Linux: $LINUX_URL" >&2
echo " Illumos: $ILLUMOS_URL" >&2
echo "Orchestrator contact: $ORCH_CONTACT_ADDR" >&2
# Give it a moment to start
sleep 3
# Enqueue two jobs: one Linux, one Illumos
SOL_REPO_URL=${SOL_REPO_URL:-$(git -C "$ROOT_DIR" remote get-url origin 2>/dev/null || true)}
SOL_COMMIT_SHA=${SOL_COMMIT_SHA:-$(git -C "$ROOT_DIR" rev-parse HEAD 2>/dev/null || true)}
if [[ -z "${SOL_REPO_URL}" || -z "${SOL_COMMIT_SHA}" ]]; then
echo "Warning: could not detect repo URL/commit; forge-enqueue will attempt autodetect" >&2
fi
# Linux (Ubuntu image in example config)
SOL_RUNS_ON=ubuntu-22.04 "$ROOT_DIR/.mise/tasks/run/forge-enqueue"
# Illumos (default label / alias)
SOL_RUNS_ON=illumos-latest "$ROOT_DIR/.mise/tasks/run/forge-enqueue"
# Tail orchestrator logs for a while
TAIL_SECS=${SOL_TAIL_SECS:-30}
echo "Tailing orchestrator logs for ${TAIL_SECS}s..." >&2
if command -v timeout >/dev/null 2>&1; then
(timeout ${TAIL_SECS}s tail -f "$LOGFILE" || true) 2>/dev/null
elif command -v gtimeout >/dev/null 2>&1; then
(gtimeout ${TAIL_SECS}s tail -f "$LOGFILE" || true) 2>/dev/null
else
tail -f "$LOGFILE" &
TAIL_PID=$!
sleep "$TAIL_SECS" || true
kill "$TAIL_PID" 2>/dev/null || true
fi
echo "Done. Logs at $LOGFILE" >&2