Ci inside VM's running many operating systems as guests - mirror
Find a file
Till Wegmueller ceaac25a7e Send incremental UpdateTask with step states during log streaming
Streamer now sends UpdateTask alongside UpdateLog on each poll so
Forgejo maps log lines to steps in real time, not just at completion.
This prevents "Set up job" from accumulating all streamed logs.
2026-04-07 00:44:02 +02:00
.idea Add TUI support and logs-client crate for enhanced job and log management 2026-01-25 22:31:11 +01:00
.junie Add explicit libvirt configuration support; remove environment variable reliance; bump version to 0.1.9 2025-11-17 22:40:50 +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 Introduce GNU tar (gtar) support and workflow setup enhancements; bump version to 0.1.16 2025-11-18 15:17:03 +01:00
crates Send incremental UpdateTask with step states during log streaming 2026-04-07 00:44:02 +02:00
deploy Add log delivery and step state reporting to Forgejo runner 2026-04-06 23:59:26 +02:00
docs/ai Add GitHub App support, AMQP integration, and webhook enhancements 2026-01-25 16:50:52 +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 Introduce logs-service for structured job logs management; bump version to 0.1.13 2025-11-18 11:48:09 +01: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.