mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-09 08:14:42 +00:00
fipstop: ratatui-based TUI for real-time monitoring of a running FIPS daemon. Tabs and navigation: - 8 navigable tabs: Node, Peers, Transports, Sessions, Tree, Filters, Performance, Routing - Tab/BackTab navigation with group separators in tab bar - Table views with selectable rows, detail drill-down panels, and scrollbars Node tab: - Runtime info: pid, exe path, uptime, control socket path, TUN adapter name - Identity: npub, node_addr, ipv6 address - State summary with peer/session/link/transport/connection counts - TUN IPv6 traffic and forwarded transit traffic counters Peers tab: - Table with Name, Address, Conn, Depth, SRTT, Loss, LQI, Pkts Tx/Rx - Detail panel: identity, connection info, transport cross-reference, tree/bloom state, link stats, MMP metrics with LQI Sessions tab: - Table with Name, Remote Addr, State, Role, SRTT, Loss, SQI, Path MTU, Last Activity - Detail panel: identity, session info, traffic stats, MMP metrics with SQI Transports tab: - Hierarchical tree view: expandable transport parents with nested links (▼/▶ indicators, ├─/└─ tree chars, Space/Arrow to expand/collapse) - Transport detail: type-specific stats (UDP/TCP/Ethernet) - Link detail: peer cross-reference with MMP metrics and LQI Performance tab: - Link-layer MMP: SRTT, loss, ETX, LQI, goodput per peer - Session-layer MMP: SRTT, loss, ETX, SQI, path MTU per session - Trend indicators (rising/falling/stable) with context-aware coloring Routing tab: - Routing state: cache sizes, pending lookups, recent requests - Coordinate cache: entries, fill ratio, TTL, expiry, avg age - Statistics: forwarding, discovery request/response, error signal counters Tree tab: - Spanning tree position with 16 announce stats (inbound/outbound/cumulative) Filters tab: - Bloom filter announce stats, per-peer fill ratio and estimated node count MMP metrics enhancements: - Add etx_trend DualEwma for smoothed ETX tracking - Add smoothed_loss() and smoothed_etx() accessors (long-term EWMA) - LQI (Link Quality Index) = smoothed_etx * (1 + srtt_ms / 100) - SQI (Session Quality Index) = same formula for session layer - All loss/ETX displays prefer smoothed values with raw fallback Control socket: - Add smoothed_loss, smoothed_etx, lqi/sqi to show_peers, show_sessions, and show_mmp JSON responses - Rename fips_address to ipv6_addr in show_status and show_peers - Add tun_name and control_socket to show_status - FHS-compliant 3-tier default path: $XDG_RUNTIME_DIR, /run/fips, /tmp Node extensions: - Add started_at/uptime() to Node - Add tun_name() accessor Docker sidecar updates: - TCP transport support via FIPS_PEER_TRANSPORT env var - Build scripts include fipstop binary
284 lines
10 KiB
YAML
284 lines
10 KiB
YAML
name: CI
|
||
|
||
on:
|
||
push:
|
||
branches: ["**"]
|
||
pull_request:
|
||
workflow_dispatch:
|
||
inputs:
|
||
skip_integration:
|
||
description: "Skip integration tests"
|
||
type: boolean
|
||
default: false
|
||
|
||
permissions:
|
||
checks: write
|
||
contents: read
|
||
|
||
env:
|
||
CARGO_TERM_COLOR: always
|
||
RUST_BACKTRACE: 1
|
||
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
# Job 1 – Build matrix
|
||
#
|
||
# Builds on Linux x86_64 and Linux aarch64. macOS and Windows are in a
|
||
# separate ci-compat.yml workflow so their failures don't mark this run red.
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
jobs:
|
||
build:
|
||
name: Build (${{ matrix.os }})
|
||
runs-on: ${{ matrix.os }}
|
||
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
include:
|
||
- os: ubuntu-latest
|
||
- os: ubuntu-24.04-arm
|
||
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Install Rust toolchain
|
||
uses: dtolnay/rust-toolchain@stable
|
||
|
||
- name: Cache Cargo registry + build
|
||
uses: actions/cache@v4
|
||
with:
|
||
path: |
|
||
~/.cargo/registry
|
||
~/.cargo/git
|
||
target
|
||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||
restore-keys: |
|
||
${{ runner.os }}-cargo-
|
||
|
||
- name: Build
|
||
run: cargo build --release
|
||
|
||
# Upload the Linux binary so integration jobs can use it without rebuilding
|
||
- name: Upload Linux binary
|
||
if: matrix.os == 'ubuntu-latest'
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: fips-linux
|
||
path: |
|
||
target/release/fips
|
||
target/release/fipsctl
|
||
target/release/fipstop
|
||
retention-days: 1
|
||
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
# Job 2 – Unit tests
|
||
#
|
||
# Runs `cargo test` on Linux. Gated on the build matrix completing so we
|
||
# don't waste runner time if compilation is broken.
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
test:
|
||
name: Unit tests
|
||
runs-on: ubuntu-latest
|
||
needs: [build]
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Install Rust toolchain
|
||
uses: dtolnay/rust-toolchain@stable
|
||
|
||
- name: Cache Cargo registry + build
|
||
uses: actions/cache@v4
|
||
with:
|
||
path: |
|
||
~/.cargo/registry
|
||
~/.cargo/git
|
||
target
|
||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||
restore-keys: |
|
||
${{ runner.os }}-cargo-
|
||
|
||
- name: Install cargo-nextest
|
||
uses: taiki-e/install-action@nextest
|
||
|
||
- name: Run unit tests
|
||
run: cargo nextest run --all --profile ci
|
||
|
||
- name: Publish test report (Checks tab)
|
||
uses: dorny/test-reporter@v2
|
||
if: always()
|
||
with:
|
||
name: Unit Tests
|
||
path: target/nextest/ci/junit.xml
|
||
reporter: java-junit
|
||
fail-on-error: false
|
||
|
||
- name: Publish test report (run summary)
|
||
uses: mikepenz/action-junit-report@v4
|
||
if: always()
|
||
with:
|
||
report_paths: target/nextest/ci/junit.xml
|
||
check_name: Unit Tests Summary
|
||
fail_on_failure: false
|
||
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
# Job 3 – Integration tests (static mesh + chaos simulation)
|
||
#
|
||
# Runs only when both build and test succeed. Each topology / scenario is a
|
||
# separate matrix entry so they run in parallel.
|
||
#
|
||
# Static topologies → build Docker images, start containers, ping-test
|
||
# Chaos scenarios → build sim image, run stochastic simulation
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
integration:
|
||
name: Integration (${{ matrix.suite }})
|
||
runs-on: ubuntu-latest
|
||
needs: [build, test]
|
||
if: ${{ !inputs.skip_integration }}
|
||
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
include:
|
||
# ── Static mesh topologies ─────────────────────────────────────────
|
||
- suite: static-mesh
|
||
type: static
|
||
topology: mesh
|
||
- suite: static-chain
|
||
type: static
|
||
topology: chain
|
||
# ── Chaos / stochastic scenarios ───────────────────────────────────
|
||
- suite: chaos-smoke-10
|
||
type: chaos
|
||
scenario: smoke-10
|
||
- suite: chaos-10
|
||
type: chaos
|
||
scenario: chaos-10
|
||
- suite: ethernet-mesh
|
||
type: chaos
|
||
scenario: ethernet-mesh
|
||
- suite: ethernet-only
|
||
type: chaos
|
||
scenario: ethernet-only
|
||
- suite: bottleneck-parent
|
||
type: chaos
|
||
scenario: bottleneck-parent
|
||
- suite: cost-avoidance
|
||
type: chaos
|
||
scenario: cost-avoidance
|
||
- suite: cost-mixed-7node
|
||
type: chaos
|
||
scenario: cost-mixed-7node
|
||
- suite: cost-reeval
|
||
type: chaos
|
||
scenario: cost-reeval
|
||
- suite: cost-stability
|
||
type: chaos
|
||
scenario: cost-stability
|
||
- suite: depth-vs-cost
|
||
type: chaos
|
||
scenario: depth-vs-cost
|
||
- suite: mixed-technology
|
||
type: chaos
|
||
scenario: mixed-technology
|
||
# ── Sidecar deployment ──────────────────────────────────────────
|
||
- suite: sidecar
|
||
type: sidecar
|
||
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
# Fetch the pre-built Linux binary from job 1
|
||
- name: Download Linux binary
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
name: fips-linux
|
||
path: _bin
|
||
|
||
# ── Static topology ────────────────────────────────────────────────────
|
||
- name: Install binary (static)
|
||
if: matrix.type == 'static'
|
||
run: |
|
||
chmod +x _bin/fips _bin/fipsctl
|
||
cp _bin/fips testing/static/fips
|
||
cp _bin/fipsctl testing/static/fipsctl
|
||
|
||
- name: Generate configs (static)
|
||
if: matrix.type == 'static'
|
||
run: bash testing/static/scripts/generate-configs.sh ${{ matrix.topology }}
|
||
|
||
- name: Build Docker images (static)
|
||
if: matrix.type == 'static'
|
||
run: |
|
||
docker compose -f testing/static/docker-compose.yml \
|
||
--profile ${{ matrix.topology }} build
|
||
|
||
- name: Start containers (static)
|
||
if: matrix.type == 'static'
|
||
run: |
|
||
docker compose -f testing/static/docker-compose.yml \
|
||
--profile ${{ matrix.topology }} up -d
|
||
|
||
- name: Run ping test (static)
|
||
if: matrix.type == 'static'
|
||
run: bash testing/static/scripts/ping-test.sh ${{ matrix.topology }}
|
||
|
||
- name: Collect logs on failure (static)
|
||
if: matrix.type == 'static' && failure()
|
||
run: |
|
||
docker compose -f testing/static/docker-compose.yml \
|
||
--profile ${{ matrix.topology }} logs --no-color
|
||
|
||
- name: Stop containers (static)
|
||
if: matrix.type == 'static' && always()
|
||
run: |
|
||
docker compose -f testing/static/docker-compose.yml \
|
||
--profile ${{ matrix.topology }} down --volumes --remove-orphans
|
||
|
||
# ── Chaos simulation ───────────────────────────────────────────────────
|
||
- name: Install Python deps (chaos)
|
||
if: matrix.type == 'chaos'
|
||
run: pip3 install --quiet pyyaml jinja2
|
||
|
||
- name: Install binary (chaos)
|
||
if: matrix.type == 'chaos'
|
||
run: |
|
||
chmod +x _bin/fips _bin/fipsctl
|
||
cp _bin/fips testing/chaos/fips
|
||
cp _bin/fipsctl testing/chaos/fipsctl
|
||
|
||
- name: Build chaos Docker image
|
||
if: matrix.type == 'chaos'
|
||
run: docker build -t fips-chaos:latest testing/chaos
|
||
|
||
- name: Run chaos scenario
|
||
if: matrix.type == 'chaos'
|
||
run: bash testing/chaos/scripts/chaos.sh ${{ matrix.scenario }}
|
||
|
||
- name: Upload sim results on failure (chaos)
|
||
if: matrix.type == 'chaos' && failure()
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: sim-results-${{ matrix.scenario }}
|
||
path: testing/chaos/sim-results/
|
||
retention-days: 7
|
||
|
||
# ── Sidecar deployment ──────────────────────────────────────────────
|
||
- name: Install binary (sidecar)
|
||
if: matrix.type == 'sidecar'
|
||
run: |
|
||
chmod +x _bin/fips _bin/fipsctl _bin/fipstop
|
||
cp _bin/fips testing/sidecar/fips
|
||
cp _bin/fipsctl testing/sidecar/fipsctl
|
||
cp _bin/fipstop testing/sidecar/fipstop
|
||
|
||
- name: Run sidecar integration test
|
||
if: matrix.type == 'sidecar'
|
||
run: bash testing/sidecar/scripts/test-sidecar.sh
|
||
|
||
- name: Collect logs on failure (sidecar)
|
||
if: matrix.type == 'sidecar' && failure()
|
||
run: |
|
||
for node in a b c; do
|
||
echo "--- sidecar-${node} logs ---"
|
||
docker logs "sidecar-${node}-fips-1" 2>&1 || true
|
||
echo ""
|
||
done |