Ci inside VM's running many operating systems as guests - mirror
Find a file
Till Wegmueller bf94664a30
Refactor VM lifecycle handling and improve guest IP discovery, bump version to 0.1.6
- Adjust stopping, destroying, and persisting VM lifecycle events to ensure better sequencing and avoid races.
- Enhance `discover_guest_ip_virsh` with detailed logging, structured attempt tracking, and robust fallback mechanisms.
- Introduce `Attempt` struct to capture detailed command execution context for debugging.
- Update console log handling to snapshot logs early, minimizing race conditions.
- Bump orchestrator version to 0.1.6.

Signed-off-by: Till Wegmueller <toasterson@gmail.com>
2025-11-17 21:34:19 +01:00
.idea Add Debian packaging support and network configuration enhancements 2025-11-17 19:57:19 +01:00
.junie Add support for multi-OS VM builds with cross-built runners and improved local development tooling 2025-11-01 14:31:48 +01:00
.mise/tasks Enable libvirt feature for orchestrator and bump version to 0.1.2 2025-11-17 20:01:06 +01:00
.solstice Add insecure TLS support, CA bundle handling, and package update for SunOS environments 2025-11-02 20:48:05 +01:00
crates Refactor VM lifecycle handling and improve guest IP discovery, bump version to 0.1.6 2025-11-17 21:34:19 +01:00
deploy Add Debian packaging support and network configuration enhancements 2025-11-17 19:57:19 +01:00
docs/ai Add support for multi-OS VM builds with cross-built runners and improved local development tooling 2025-11-01 14:31:48 +01:00
examples Add Debian packaging support and network configuration enhancements 2025-11-17 19:57:19 +01:00
packaging/arch Add Podman Compose deployment stack with Traefik and services integration 2025-11-08 20:21:57 +00:00
.gitignore Initial Commit 2025-10-25 20:01:08 +02:00
Cargo.toml Initial Commit 2025-10-25 20:01:08 +02:00
Cross.toml Add bindgen-related configuration and dependencies for cross-compilation 2025-11-01 16:22:37 +01:00
docker-compose.yml Enable job log persistence, HTTP server, and extend CI/packaging support 2025-11-02 23:37:11 +01:00
fnox.toml Add heuristic failure detection and improve runner URL configuration 2025-11-03 22:36:31 +01:00
LICENSE Initial commit 2025-10-25 18:31:50 +02:00
mise.toml Add runner binary serving via orchestrator, update configurations and documentation 2025-11-09 19:02:42 +01:00
README.md Add support for multi-OS VM builds with cross-built runners and improved local development tooling 2025-11-01 14:31:48 +01:00

Solstice CI

Build your code on multiple operating systems easily — with firstclass support for Illumos and Linux, and a simple, observable pipeline.

Solstice CI is a Rust workspace that provides:

  • Orchestration to provision perjob virtual machines (libvirt/KVM) (bHyve)
  • A simple workflow format (KDL) and runner
  • Integration layers for forges (Forgejo/Gitea, GitHub) based on messaging (RabbitMQ)
  • Shared telemetry and utilities

This README follows best practices inspired by awesome-readme. It focuses on how to get productive locally, what you need to run it, and how to contribute.

Table of Contents

  • Overview
  • Features
  • OS and Tooling Requirements
  • Quickstart: Local Development
  • Running the Services
  • Configuration (Environment Variables)
  • Testing
  • Troubleshooting
  • Contributing (Codeberg Pull Requests)
  • License

Overview

Solstice CI is a modular CI system:

  • crates/orchestrator — schedules jobs and provisions VMs per job
  • crates/forge-integration — receives webhooks and enqueues job requests
  • crates/workflow-runner — executes a KDL workflow inside a VM/agent
  • crates/common — shared types, telemetry, and messaging helpers
  • crates/ciadm and crates/cidev — small CLIs to aid development and admin tasks

Features

  • Per-job VMs via libvirt/KVM with image prefetch and capacity controls
  • RabbitMQ for job request queueing (durable, backpressure via prefetch)
  • gRPC/HTTP components and structured telemetry (tracing + OTLP)
  • Simple development flows with cargo and docker-compose

OS and Tooling Requirements

Minimum supported host OS for end-to-end local runs:

  • Linux x86_64 (recommended): required for libvirt/KVM hypervisor path
  • macOS / Windows: supported for building, running non-hypervisor services, and exercising CLIs; full VM orchestration is Linux-only currently

Required tools:

  • Rust (stable, edition 2024). Install via rustup: https://rustup.rs
  • Cargo (comes with rustup)
  • Docker or Podman for running RabbitMQ locally (docker-compose file provided)
  • Git

Optional but recommended:

  • Postgres (DATABASE_URL). Some binaries accept a database URL; current snapshots may not require a live DB for basic dev loops
  • An OpenTelemetry collector (OTLP) for tracing (or rely on stderr logs)

Hardware hints for Linux/local VM testing:

  • CPU virtualization enabled (VT-x/AMD-V)
  • 8 GB RAM+ recommended for running VMs alongside tooling

Quickstart: Local Development

  1. Clone the repo
  1. Start RabbitMQ locally
  • docker compose up -d rabbitmq
  • Management UI: http://localhost:15672 (guest/guest)
  • Or with mise: mise run dev:up
  1. Build everything
  • cargo build --workspace
  1. (Linux) Prepare an example orchestrator config
  • The orchestrator defaults to examples/orchestrator-image-map.yaml. Edit it to point local_path to a writable location; the orchestrator will download images as needed.
  1. Run services in separate terminals
  • Forge integration (webhooks) or enqueue sample jobs
  • Orchestrator (VM scheduler/hypervisor)
  1. Inspect logs
  • Logs are structured via tracing. Set RUST_LOG=info (or debug/trace) as needed.

Running the Services

Environment defaults are sensible for local dev; override via flags or env vars.

Forge Integration (HTTP webhook receiver) — also supports a manual enqueue mode:

  • cargo run -p forge-integration -- --help
  • cargo run -p forge-integration -- enqueue --repo-url https://codeberg.org/example/repo.git --commit-sha deadbeef --runs-on illumos-latest
  • cargo run -p forge-integration -- --http-addr 0.0.0.0:8080 --webhook-path /webhooks/forgejo

Orchestrator (Linux + libvirt/KVM):

  • cargo run -p orchestrator -- --config examples/orchestrator-image-map.yaml --grpc-addr 0.0.0.0:50051
  • You can cap concurrency and per-label capacity with --max-concurrency and --capacity-map, e.g. --capacity-map illumos-latest=1,ubuntu-22.04=2

Workflow runner (agent, useful for inspection of KDL files):

  • cargo run -p workflow-runner -- --workflow path/to/workflow.kdl

Developer helper (validate/list/show workflow KDL):

  • cargo run -p cidev -- validate --path path/to/workflow.kdl
  • cargo run -p cidev -- list --path path/to/workflow.kdl
  • cargo run -p cidev -- show --path path/to/workflow.kdl --job build

Configuration (Environment Variables)

Common env (see crates and guidelines for full list):

  • RUST_LOG=info
  • OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 (optional)
  • AMQP_URL=amqp://127.0.0.1:5672/%2f
  • AMQP_EXCHANGE=solstice.jobs
  • AMQP_QUEUE=solstice.jobs.v1
  • AMQP_ROUTING_KEY=jobrequest.v1
  • AMQP_PREFETCH=64

Orchestrator specifics:

  • ORCH_CONFIG=examples/orchestrator-image-map.yaml
  • MAX_CONCURRENCY=2
  • CAPACITY_MAP=illumos-latest=1,ubuntu-22.04=2
  • GRPC_ADDR=0.0.0.0:50051
  • DATABASE_URL=postgres://user:pass@localhost:5432/solstice (if used)
  • LIBVIRT_URI=qemu:///system (Linux)
  • LIBVIRT_NETWORK=default

Forge integration specifics:

  • HTTP_ADDR=0.0.0.0:8080
  • WEBHOOK_PATH=/webhooks/forgejo
  • WEBHOOK_SECRET=... (recommended in real setups)

Testing

  • Run all tests across the workspace:
    • cargo test --workspace
  • Run a specific crates tests:
    • cargo test -p orchestrator
  • Run an integration test by name filter:
    • cargo test smoke

Troubleshooting

  • No logs? Ensure tracing is initialized once and set RUST_LOG appropriately.
  • RabbitMQ not reachable? Verify docker compose is running and ports 5672/15672 are open.
  • VM provisioning errors on non-Linux hosts: hypervisor features require Linux. Use a Linux machine or dev container/VM.
  • Image downloads fail: check examples/orchestrator-image-map.yaml entries and local_path permissions.

Contributing (Codeberg Pull Requests)

We welcome contributions via the standard fork-and-pull-request workflow on Codeberg.

  1. Fork the repository on Codeberg
  1. Create a feature branch
  • git checkout -b feat/short-description
  1. Make changes and commit
  • Follow conventional, descriptive commit messages when practical
  • cargo fmt; cargo clippy --workspace --all-targets --all-features
  • cargo test --workspace
  1. Push your branch to your fork
  • git push origin feat/short-description
  1. Open a Pull Request on Codeberg
  • Describe the change, motivations, and testing steps
  • Link to any related issues
  1. Review process
  • Automated checks will run
  • A maintainer will review and may request changes
  1. Getting your PR merged
  • Ensure feedback is addressed
  • Squash/rebase as requested by maintainers

Security and credentials:

  • Do not commit secrets. Use env vars locally and a secret store in deployments.

License

This project is licensed under the Mozilla Public License 2.0 (MPL-2.0). See LICENSE for details.