Skip to content

fix(agent): make sessions cluster truncation UTF-8 safe Refs #1734 #69

fix(agent): make sessions cluster truncation UTF-8 safe Refs #1734

fix(agent): make sessions cluster truncation UTF-8 safe Refs #1734 #69

Workflow file for this run

name: CI (Firecracker)
on:
workflow_dispatch:
inputs:
vm_type:
description: 'Firecracker VM image type'
required: false
default: 'focal-ci'
type: choice
options:
- focal-ci
- focal
pull_request:
paths:
- 'crates/**'
- 'Cargo.toml'
- 'Cargo.lock'
- 'terraphim_server/**'
# Cancel in-progress runs on the same branch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
vm-infrastructure:
name: Firecracker VM lifecycle proof
# bigbox runners co-locate with fcctl-web at 127.0.0.1:8080 — must use bigbox label
runs-on: [self-hosted, bigbox]
timeout-minutes: 5
env:
FCCTL_URL: http://127.0.0.1:8080
VM_TYPE: ${{ inputs.vm_type || 'focal-ci' }}
steps:
- name: Health check fcctl-web
run: |
curl -sf --retry 3 --retry-delay 2 $FCCTL_URL/health
echo "fcctl-web is healthy"
- name: Create VM
id: vm
run: |
RESPONSE=$(curl -sf -X POST $FCCTL_URL/api/vms \
-H 'Content-Type: application/json' \
-d "{\"vm_type\": \"$VM_TYPE\"}")
echo "$RESPONSE"
VM_ID=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
if [ -z "$VM_ID" ] || [ "$VM_ID" = "null" ]; then
echo "ERROR: failed to parse vm id from response"
exit 1
fi
echo "vm_id=$VM_ID" >> $GITHUB_OUTPUT
echo "Created VM: $VM_ID"
- name: Wait for VM ready
run: |
VM_ID="${{ steps.vm.outputs.vm_id }}"
for i in $(seq 1 18); do
STATUS=$(curl -sf $FCCTL_URL/api/vms/$VM_ID \
| python3 -c "import sys,json; print(json.load(sys.stdin).get('status','unknown'))" 2>/dev/null || echo "unknown")
echo " attempt $i: status=$STATUS"
if [ "$STATUS" = "running" ]; then
echo "VM is running"
break
fi
if [ "$i" = "18" ]; then
echo "ERROR: VM did not reach running status within 90 seconds"
exit 1
fi
sleep 5
done
- name: Execute command in VM
# /api/vms/{id} returning status=running means firecracker VMM is up,
# but the in-guest sshd may still be initialising. Retry the execute
# call (which SSHes into the guest) until it returns exit_code=0 or
# until we exhaust attempts. Each retry has a short SSH timeout so a
# single failure doesn't burn the workflow timeout.
run: |
VM_ID="${{ steps.vm.outputs.vm_id }}"
PAYLOAD="{\"vm_id\":\"$VM_ID\",\"code\":\"echo vm-ok && uname -r && id\",\"language\":\"bash\",\"agent_id\":\"ci-probe-${{ github.run_id }}\",\"timeout_ms\":15000}"
for i in $(seq 1 6); do
RESULT=$(curl -sf -X POST $FCCTL_URL/api/llm/execute -H 'Content-Type: application/json' -d "$PAYLOAD" || echo '{"exit_code":-1,"stderr":"curl failed"}')
EXIT=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('exit_code', -1))" 2>/dev/null || echo "-1")
echo "attempt $i: exit_code=$EXIT"
if [ "$EXIT" = "0" ]; then
echo "$RESULT" | python3 -m json.tool
exit 0
fi
sleep 5
done
echo "ERROR: VM did not accept SSH after 6 attempts"
echo "$RESULT" | python3 -m json.tool || echo "$RESULT"
exit 1
- name: Destroy VM
if: always()
run: |
VM_ID="${{ steps.vm.outputs.vm_id }}"
if [ -n "$VM_ID" ] && [ "$VM_ID" != "null" ]; then
curl -sf -X DELETE $FCCTL_URL/api/vms/$VM_ID && echo "VM $VM_ID destroyed" || echo "VM cleanup failed (non-fatal)"
fi
rust-build:
name: Rust build + test
# Must run on bigbox: sccache binary lives at /home/alex/.local/bin and the
# SeaweedFS S3 cache is bound to fcbr0 (172.26.0.1:8333), reachable only
# from this host. Mac runners would fail on both counts.
runs-on: [self-hosted, bigbox]
timeout-minutes: 30
# Route all rustc invocations through sccache backed by SeaweedFS S3 on
# fcbr0. See .docs/adr-rust-build-cache-seaweedfs.md. Env is applied to
# every step so cargo fmt/clippy/build/test all share the cache.
env:
RUSTC_WRAPPER: /home/alex/.local/bin/sccache
SCCACHE_BUCKET: rust-cache
SCCACHE_SERVER_PORT: "4231"
SCCACHE_ENDPOINT: http://172.26.0.1:8333
SCCACHE_S3_USE_SSL: "false"
SCCACHE_REGION: us-east-1
SCCACHE_S3_KEY_PREFIX: terraphim-ai
AWS_ACCESS_KEY_ID: any
AWS_SECRET_ACCESS_KEY: any
# sccache cannot cache incremental compilations; cargo dev profile
# defaults to incremental=true. Disable to push more rustc invocations
# through sccache. Cold-cache run showed 438 calls skipped for this
# reason. See .docs/adr-rust-build-cache-seaweedfs.md.
CARGO_INCREMENTAL: "0"
steps:
- uses: actions/checkout@v4
- name: sccache start and zero stats
run: |
/home/alex/.local/bin/sccache --start-server || true
/home/alex/.local/bin/sccache --zero-stats
# zlob is default on terraphim_file_search + terraphim_mcp_server, so
# fff-core/build.rs never hits its CI-detection panic branch and we
# don't need the old `unset CI` workaround. zig 0.16 is installed on
# bigbox; see .cargo/config.toml for the Darwin `dynamic_lookup`
# linker workaround on local Mac dev.
#
# All cargo invocations are dispatched via `rch exec --` so they
# share rchd's queue + slot accounting with ADF agents (see
# .docs/adr-rch-build-queue-not-firecracker-ci.md). Fail-open: if
# rchd is down or no slot is available, rch falls through to local
# cargo with no behaviour change.
- name: cargo fmt --check
run: /home/alex/.local/bin/rch exec -- cargo fmt -- --check
- name: cargo clippy
run: /home/alex/.local/bin/rch exec -- cargo clippy -- -D warnings
- name: cargo build --workspace
run: /home/alex/.local/bin/rch exec -- cargo build --workspace
- name: cargo test --workspace
# Only test_chat_command is skipped: it requires LLM API credentials
# not present in CI. All other failures must be fixed at the source,
# not skipped.
run: /home/alex/.local/bin/rch exec -- cargo test --workspace -- --skip test_chat_command
- name: sccache stats
if: always()
run: /home/alex/.local/bin/sccache --show-stats