mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-21 23:21:12 +00:00
6ce31587d4
Bugs found during Step 11 (Run Tests) functional gate: 1. e2e/docker/docker-compose.test.yml referenced docker/Dockerfile (doesn't exist). Renamed to docker/companion-tier1.Dockerfile. 2. fdr-output volume declared tmpfs size=64g, which requires actual host RAM. Docker Desktop on macOS has only ~3.8 GiB; tmpfs alloc fails. Switched to a plain named volume (the SUT enforces the 64 GB cap internally per NFT-LIM-02; the volume-layer cap was belt-and- suspenders only). Documented the overlay2+xfs override path for CI runners that support it. 3. Added e2e-results/ to .gitignore (runtime output dir created by the bind-mount). These bugs predate this session; the harness had never been bench-tested end-to-end. Surfacing them was the actual outcome of running test-run. Co-authored-by: Cursor <cursoragent@cursor.com>
148 lines
5.1 KiB
YAML
148 lines
5.1 KiB
YAML
# Tier-1 docker-compose entrypoint for the gps-denied-onboard blackbox e2e harness.
|
|
#
|
|
# Spec sources (single source of truth):
|
|
# _docs/02_document/tests/environment.md § Docker Environment
|
|
# _docs/02_tasks/todo/AZ-406_test_infrastructure.md
|
|
#
|
|
# Layout note: AZ-406 introduces this file; later test-task batches may add
|
|
# per-scenario override files alongside it (e.g. negative path injectors).
|
|
# This base file MUST stay self-contained — every override is purely additive.
|
|
#
|
|
# Build context (`build.context: ../..`) is the repo root, so the SUT image
|
|
# build sees `src/`, `cpp/`, `docker/Dockerfile`, and `pyproject.toml`.
|
|
|
|
services:
|
|
|
|
gps-denied-onboard:
|
|
build:
|
|
context: ../..
|
|
dockerfile: docker/companion-tier1.Dockerfile
|
|
args:
|
|
BUILD_VINS_MONO: "OFF"
|
|
image: gps-denied-onboard:e2e
|
|
networks: [e2e-net]
|
|
volumes:
|
|
- tile-cache-fixture:/var/azaion/tile-cache:ro
|
|
- fdr-output:/var/azaion/fdr
|
|
environment:
|
|
ONBOARD_FC_ADAPTER: ${FC_ADAPTER:-ardupilot}
|
|
ONBOARD_VIO_STRATEGY: ${VIO_STRATEGY:-okvis2}
|
|
MAVLINK_SIGNING_PASSKEY_FILE: /run/secrets/mavlink_passkey
|
|
secrets:
|
|
- mavlink_passkey
|
|
depends_on:
|
|
- mock-suite-sat-service
|
|
healthcheck:
|
|
test: ["CMD", "python", "-c", "from gps_denied_onboard.healthcheck import check; check()"]
|
|
interval: 5s
|
|
retries: 12
|
|
|
|
ardupilot-plane-sitl:
|
|
image: ardupilot/ardupilot-sitl:plane-stable
|
|
networks: [e2e-net]
|
|
command: ["--vehicle=ArduPlane", "--gps-type=14"]
|
|
environment:
|
|
# GPS_TYPE=14 selects MAV (external positioning) per ArduPilot SITL params.
|
|
AP_PARAM_GPS_TYPE: "14"
|
|
|
|
inav-sitl:
|
|
image: inavflight/inav-sitl:9.0.0
|
|
networks: [e2e-net]
|
|
# iNav SITL exposes MSP on TCP 5760 (UART1) per docs/SITL/SITL.md
|
|
|
|
mock-suite-sat-service:
|
|
build: ../fixtures/mock-suite-sat
|
|
image: mock-suite-sat-service:e2e
|
|
networks: [e2e-net]
|
|
environment:
|
|
MOCK_SUITE_SAT_AUDIT_PATH: /audit
|
|
volumes:
|
|
- mock-audit:/audit
|
|
healthcheck:
|
|
test: ["CMD", "python", "-c", "import urllib.request, sys; sys.exit(0 if urllib.request.urlopen('http://localhost:8080/mock/health', timeout=2).status==200 else 1)"]
|
|
interval: 5s
|
|
retries: 12
|
|
|
|
mavproxy-listener:
|
|
image: ardupilot/mavproxy:latest
|
|
networks: [e2e-net]
|
|
command:
|
|
- "--master=udp:0.0.0.0:14551"
|
|
- "--logfile=/var/log/tlogs/${RUN_ID:-local}.tlog"
|
|
- "--out=udp:e2e-runner:14552"
|
|
volumes:
|
|
- tlog-output:/var/log/tlogs
|
|
|
|
e2e-runner:
|
|
build: ../runner
|
|
image: gps-denied-onboard-e2e-runner:latest
|
|
networks: [e2e-net]
|
|
environment:
|
|
RUN_ID: ${RUN_ID:-local}
|
|
FC_ADAPTER: ${FC_ADAPTER:-ardupilot}
|
|
VIO_STRATEGY: ${VIO_STRATEGY:-okvis2}
|
|
TIER: tier1-docker
|
|
MAVLINK_PASSKEY_PATH: /test-fixtures/secrets/mavlink-test-passkey.txt
|
|
MOCK_SUITE_SAT_URL: http://mock-suite-sat-service:8080
|
|
AP_SITL_HOST: ardupilot-plane-sitl
|
|
INAV_SITL_HOST: inav-sitl
|
|
MAVPROXY_LISTENER_HOST: mavproxy-listener
|
|
volumes:
|
|
- ../../_docs/00_problem/input_data:/test-data:ro
|
|
- ../../_docs/00_problem/input_data/expected_results:/expected:ro
|
|
- ../fixtures:/test-fixtures:ro
|
|
- ../tests:/test-suite:ro
|
|
- fdr-output:/fdr:ro
|
|
- tlog-output:/tlogs:ro
|
|
- e2e-results:/e2e-results
|
|
- mock-audit:/mock-audit:ro
|
|
command:
|
|
- "pytest"
|
|
- "/test-suite"
|
|
- "--csv=/e2e-results/run-${RUN_ID:-local}/report.csv"
|
|
- "--csv-columns=test_id,test_name,traces_to,fc_adapter,vio_strategy,tier,started_at_utc,execution_time_ms,result,error_message,evidence_paths"
|
|
- "--evidence-out=/e2e-results/run-${RUN_ID:-local}/evidence"
|
|
depends_on:
|
|
gps-denied-onboard:
|
|
condition: service_healthy
|
|
mock-suite-sat-service:
|
|
condition: service_healthy
|
|
ardupilot-plane-sitl:
|
|
condition: service_started
|
|
inav-sitl:
|
|
condition: service_started
|
|
mavproxy-listener:
|
|
condition: service_started
|
|
|
|
networks:
|
|
e2e-net:
|
|
driver: bridge
|
|
# CRITICAL: enforces RESTRICT-SAT-1 / NFT-SEC-02 / NFT-SEC-05 at the network layer.
|
|
# The SUT, mock, runner, and SITLs can talk to each other but none of them can
|
|
# reach the public internet (no DNS, no egress). The e2e-runner verifies this
|
|
# at runtime by attempting a TCP connect to 1.1.1.1:443 (AC-5).
|
|
internal: true
|
|
|
|
volumes:
|
|
# Size cap follows AC-NEW-3: each FDR file ≤ 64 GB. The volume layer cap is
|
|
# belt-and-suspenders; the SUT enforces the cap internally per NFT-LIM-02.
|
|
# `--storage-opt size=64g` requires overlay2 with xfs backing on the host —
|
|
# most CI runners and macOS Docker Desktop hosts lack that combination, so
|
|
# this base file uses the documented fallback (a plain named volume) and
|
|
# relies on the SUT-internal cap. CI runners with overlay2+xfs can override
|
|
# via a docker-compose.override.yml that re-introduces the tmpfs driver_opts.
|
|
fdr-output: {}
|
|
tile-cache-fixture: {}
|
|
tlog-output: {}
|
|
mock-audit: {}
|
|
e2e-results:
|
|
driver: local
|
|
driver_opts:
|
|
type: none
|
|
device: ${PWD}/../../e2e-results
|
|
o: bind
|
|
|
|
secrets:
|
|
mavlink_passkey:
|
|
file: ./secrets/mavlink_passkey
|