Files
fips/.github/workflows/ci.yml
2026-04-10 08:45:18 +00:00

321 lines
12 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
SOURCE_DATE_EPOCH: 0 # overridden per-step after checkout
# ─────────────────────────────────────────────────────────────────────────────
# 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:
fmt:
name: Format check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --check
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: Set SOURCE_DATE_EPOCH from git
run: echo "SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)" >> "$GITHUB_ENV"
- 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
- name: SHA-256 hashes
run: sha256sum target/release/fips target/release/fipsctl target/release/fipstop
# 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: Set SOURCE_DATE_EPOCH from git
run: echo "SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)" >> "$GITHUB_ENV"
- 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.
#
# All harnesses share a single Docker image (fips-test:latest) built once
# in the setup step from testing/docker/.
# ─────────────────────────────────────────────────────────────────────────────
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
# ── Rekey integration test ──────────────────────────────────────────
- suite: rekey
type: rekey
topology: rekey
# ── Chaos / stochastic scenarios ───────────────────────────────────
- suite: chaos-smoke-10
type: chaos
scenario: smoke-10
- suite: churn-mixed-10
type: chaos
scenario: churn-mixed
chaos_flags: "--nodes 10 --duration 120"
- suite: ethernet-mesh
type: chaos
scenario: ethernet-mesh
- suite: ethernet-only
type: chaos
scenario: ethernet-only
- suite: tcp-mesh
type: chaos
scenario: tcp-mesh
- suite: bottleneck-parent
type: chaos
scenario: bottleneck-parent
- suite: cost-avoidance
type: chaos
scenario: cost-avoidance
- 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
- suite: congestion-stress
type: chaos
scenario: congestion-stress
# ── 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
# Install binaries to unified docker context and build shared image
- name: Install binaries and build Docker image
run: |
chmod +x _bin/fips _bin/fipsctl
[ -f _bin/fipstop ] && chmod +x _bin/fipstop || true
cp _bin/fips testing/docker/fips
cp _bin/fipsctl testing/docker/fipsctl
[ -f _bin/fipstop ] && cp _bin/fipstop testing/docker/fipstop || true
docker build -t fips-test:latest testing/docker
docker build -t fips-test-app:latest -f testing/docker/Dockerfile.app testing/docker
# ── Static topology ────────────────────────────────────────────────────
- name: Generate configs (static)
if: matrix.type == 'static'
run: bash testing/static/scripts/generate-configs.sh ${{ matrix.topology }}
- 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
# ── Rekey integration test ──────────────────────────────────────────────
- name: Generate and inject configs (rekey)
if: matrix.type == 'rekey'
run: |
bash testing/static/scripts/generate-configs.sh rekey
bash testing/static/scripts/rekey-test.sh inject-config
- name: Start containers (rekey)
if: matrix.type == 'rekey'
run: |
docker compose -f testing/static/docker-compose.yml \
--profile rekey up -d
- name: Run rekey test
if: matrix.type == 'rekey'
run: bash testing/static/scripts/rekey-test.sh
- name: Collect logs on failure (rekey)
if: matrix.type == 'rekey' && failure()
run: |
docker compose -f testing/static/docker-compose.yml \
--profile rekey logs --no-color
- name: Stop containers (rekey)
if: matrix.type == 'rekey' && always()
run: |
docker compose -f testing/static/docker-compose.yml \
--profile rekey down --volumes --remove-orphans
# ── Chaos simulation ───────────────────────────────────────────────────
- name: Install Python deps (chaos)
if: matrix.type == 'chaos'
run: pip3 install --quiet pyyaml jinja2
- name: Run chaos scenario
if: matrix.type == 'chaos'
run: bash testing/chaos/scripts/chaos.sh ${{ matrix.scenario }} ${{ matrix.chaos_flags }}
- 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: Run sidecar integration test
if: matrix.type == 'sidecar'
run: bash testing/sidecar/scripts/test-sidecar.sh --skip-build
- 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