diff --git a/.github/workflows/_system_test.yml b/.github/workflows/_system_test.yml index 622e26bcb..dbd1f74bb 100644 --- a/.github/workflows/_system_test.yml +++ b/.github/workflows/_system_test.yml @@ -4,6 +4,9 @@ on: env: # https://github.com/pytest-dev/pytest/issues/2042 PY_IGNORE_IMPORTMISMATCH: "1" + # test: sim IOCs and gateways from example-services, ci: the containerised blueapi server. + # Set here as --profile would replace COMPOSE_PROFILES=test from tests/system_tests/.env + COMPOSE_PROFILES: test,ci jobs: run: @@ -20,16 +23,21 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v7 - - name: Compose services - uses: hoverkraft-tech/compose-action@b659c744ee9bed25aea2307c017ad849bd104433 # v3.2.0 - with: - compose-file: "tests/system_tests/compose.yaml" + - name: Set up Docker Compose + uses: docker/setup-compose-action@v2 - - name: Start Blueapi Server - env: - EPICS_CA_NAME_SERVERS: 127.0.0.1:9064 - EPICS_PVA_NAME_SERVERS: 127.0.0.1:9075 - run: uv run blueapi -c ${{ github.workspace }}/tests/system_tests/config.yaml serve & + - name: Read dodal version from uv.lock + run: echo "DODAL_VERSION=$(grep -A1 '^name = "dls-dodal"$' uv.lock | sed -n 's/^version = "\(.*\)"$/\1/p')" >> "$GITHUB_ENV" + + - name: Compose services + # Wait on blueapi only: --wait on everything fails on the one-shot init container exiting + run: | + docker compose -f tests/system_tests/compose.yaml up -d + docker compose -f tests/system_tests/compose.yaml up -d --wait --wait-timeout 600 blueapi - name: Run tests run: uv run --locked tox -e system-test + + - name: Compose logs + if: failure() + run: docker compose -f tests/system_tests/compose.yaml logs diff --git a/tests/system_tests/compose.yaml b/tests/system_tests/compose.yaml index 193a36acc..25570146b 100644 --- a/tests/system_tests/compose.yaml +++ b/tests/system_tests/compose.yaml @@ -1,5 +1,7 @@ include: - - ../../example-services/compose.yaml + - path: + - ../../example-services/compose.yaml + - ./services/example-services-override.yaml services: numtracker: @@ -89,6 +91,38 @@ services: security_opt: - label=disable + # CI only, locally run the server with `just serve` (uv) instead + blueapi: + profiles: [ci] + build: + context: ../.. + target: runtime + network_mode: host # Port 8000 + environment: + - EPICS_CA_NAME_SERVERS=127.0.0.1:9064 + - EPICS_PVA_NAME_SERVERS=127.0.0.1:9075 + - DODAL_VERSION + # A huge default nofile limit makes the EPICS CA client spin and devices fail to connect + ulimits: + nofile: 1024 + volumes: + - ./config.yaml:/blueapi/config.yaml:ro + - ./config-scratch.yaml:/blueapi/config-scratch.yaml:ro + - ./services/blueapi/start.sh:/blueapi/start.sh:ro + entrypoint: ["sh", "/blueapi/start.sh"] + healthcheck: + test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/healthz')"] + interval: 5s + timeout: 5s + retries: 10 + # setup-scratch plus device connection can take several minutes + start_period: 300s + depends_on: + configure-services: + condition: service_completed_successfully + security_opt: + - label=disable + blueapi-oauth2-proxy: network_mode: host # Port 4180 image: "quay.io/oauth2-proxy/oauth2-proxy:v7.13.0" diff --git a/tests/system_tests/config-scratch.yaml b/tests/system_tests/config-scratch.yaml new file mode 100644 index 000000000..45950c768 --- /dev/null +++ b/tests/system_tests/config-scratch.yaml @@ -0,0 +1,8 @@ +# Overlay on config.yaml for the containerised server in CI (compose profile "ci"). +# dodal is not in the image, so setup-scratch installs it; DODAL_VERSION is read from uv.lock. +scratch: + root: /tmp/scratch/blueapi + repositories: + - name: dodal + remote_url: https://github.com/DiamondLightSource/dodal.git + target_revision: ${DODAL_VERSION} # unquoted, blueapi only expands env vars in plain scalars diff --git a/tests/system_tests/services/blueapi/start.sh b/tests/system_tests/services/blueapi/start.sh new file mode 100755 index 000000000..77d5f78d3 --- /dev/null +++ b/tests/system_tests/services/blueapi/start.sh @@ -0,0 +1,6 @@ +#!/bin/sh +# dodal is not in the image, setup-scratch clones and installs it from config-scratch.yaml +set -e +mkdir -p /tmp/scratch/blueapi +blueapi -c /blueapi/config.yaml -c /blueapi/config-scratch.yaml setup-scratch +exec blueapi -c /blueapi/config.yaml -c /blueapi/config-scratch.yaml serve diff --git a/tests/system_tests/services/example-services-override.yaml b/tests/system_tests/services/example-services-override.yaml new file mode 100644 index 000000000..fdaf0d548 --- /dev/null +++ b/tests/system_tests/services/example-services-override.yaml @@ -0,0 +1,8 @@ +# Overrides for the example-services submodule. +# EPICS CA (PCAS gateway and libca clients) loops over every possible file descriptor, +# so a huge default nofile limit (e.g. 2^31 on some Docker hosts) pegs the CPU and +# PV connections time out. Cap it. +services: + ca-gateway: + ulimits: + nofile: 1024