From 184c158306f87f8fa07667a1c9fc27124c7b964a Mon Sep 17 00:00:00 2001 From: Zoheb Shaikh <26975142+ZohebShaikh@users.noreply.github.com> Date: Tue, 20 Oct 2026 15:18:50 +0100 Subject: [PATCH 1/8] check fix --- .github/workflows/_system_test.yml | 7 ++----- tests/system_tests/compose.yaml | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/.github/workflows/_system_test.yml b/.github/workflows/_system_test.yml index 622e26bcb..40640f574 100644 --- a/.github/workflows/_system_test.yml +++ b/.github/workflows/_system_test.yml @@ -25,11 +25,8 @@ jobs: with: compose-file: "tests/system_tests/compose.yaml" - - 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: Wait for Blueapi Server + run: timeout 300 sh -c 'until [ "$(docker inspect -f {{.State.Health.Status}} $(docker compose -f tests/system_tests/compose.yaml ps -q blueapi))" = healthy ]; do sleep 5; done' - name: Run tests run: uv run --locked tox -e system-test diff --git a/tests/system_tests/compose.yaml b/tests/system_tests/compose.yaml index 193a36acc..3e0361674 100644 --- a/tests/system_tests/compose.yaml +++ b/tests/system_tests/compose.yaml @@ -89,6 +89,29 @@ services: security_opt: - label=disable + blueapi: + 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 + volumes: + - ./config.yaml:/config/config.yaml:ro + command: ["-c", "/config/config.yaml", "serve"] + healthcheck: + test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/healthz')"] + interval: 5s + timeout: 5s + retries: 10 + start_period: 30s + 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" From 6163df1684bae5d01b4b6c876a5c36e4ba5912dc Mon Sep 17 00:00:00 2001 From: Zoheb Shaikh <26975142+ZohebShaikh@users.noreply.github.com> Date: Tue, 20 Oct 2026 15:32:51 +0100 Subject: [PATCH 2/8] use better docker compose --- .github/workflows/_container.yml | 10 ++++++++++ .github/workflows/_system_test.yml | 18 +++++++++++++++--- .github/workflows/ci.yml | 1 + tests/system_tests/compose.yaml | 1 + 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/.github/workflows/_container.yml b/.github/workflows/_container.yml index 690576fe1..795ca334b 100644 --- a/.github/workflows/_container.yml +++ b/.github/workflows/_container.yml @@ -55,6 +55,16 @@ jobs: - name: Test cli works in cached runtime image run: docker run --rm tag_for_testing --version + - name: Save image for system tests + run: docker save tag_for_testing -o /tmp/blueapi-image.tar + + - name: Upload image for system tests + uses: actions/upload-artifact@v7 + with: + name: blueapi-image + path: /tmp/blueapi-image.tar + retention-days: 1 + - name: Create tags for publishing image id: meta uses: docker/metadata-action@v6 diff --git a/.github/workflows/_system_test.yml b/.github/workflows/_system_test.yml index 40640f574..c27adad38 100644 --- a/.github/workflows/_system_test.yml +++ b/.github/workflows/_system_test.yml @@ -20,10 +20,22 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v7 - - name: Compose services - uses: hoverkraft-tech/compose-action@b659c744ee9bed25aea2307c017ad849bd104433 # v3.2.0 + - name: Download blueapi image + uses: actions/download-artifact@v8 with: - compose-file: "tests/system_tests/compose.yaml" + name: blueapi-image + path: /tmp + + - name: Load blueapi image + run: | + docker load -i /tmp/blueapi-image.tar + docker tag tag_for_testing blueapi-system-test + + - name: Set up Docker Compose + uses: docker/setup-compose-action@v2 + + - name: Compose services + run: docker compose -f tests/system_tests/compose.yaml up -d - name: Wait for Blueapi Server run: timeout 300 sh -c 'until [ "$(docker inspect -f {{.State.Health.Status}} $(docker compose -f tests/system_tests/compose.yaml ps -q blueapi))" = healthy ]; do sleep 5; done' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54b29171b..89b889962 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,7 @@ jobs: python-version: ${{ matrix.python-version }} system-test: + needs: container uses: ./.github/workflows/_system_test.yml container: diff --git a/tests/system_tests/compose.yaml b/tests/system_tests/compose.yaml index 3e0361674..d8e019b8d 100644 --- a/tests/system_tests/compose.yaml +++ b/tests/system_tests/compose.yaml @@ -90,6 +90,7 @@ services: - label=disable blueapi: + image: blueapi-system-test # CI loads this from the container job; built locally if missing build: context: ../.. target: runtime From 090bf63d963ae63db7b0d066d42798c518bbfa12 Mon Sep 17 00:00:00 2001 From: Zoheb Shaikh <26975142+ZohebShaikh@users.noreply.github.com> Date: Tue, 20 Oct 2026 15:44:48 +0100 Subject: [PATCH 3/8] new check --- .github/workflows/_system_test.yml | 6 +++--- tests/system_tests/Dockerfile | 7 +++++++ tests/system_tests/compose.yaml | 8 +++++--- 3 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 tests/system_tests/Dockerfile diff --git a/.github/workflows/_system_test.yml b/.github/workflows/_system_test.yml index c27adad38..9177aae89 100644 --- a/.github/workflows/_system_test.yml +++ b/.github/workflows/_system_test.yml @@ -27,14 +27,14 @@ jobs: path: /tmp - name: Load blueapi image - run: | - docker load -i /tmp/blueapi-image.tar - docker tag tag_for_testing blueapi-system-test + run: docker load -i /tmp/blueapi-image.tar - name: Set up Docker Compose uses: docker/setup-compose-action@v2 - name: Compose services + env: + BLUEAPI_BASE_IMAGE: tag_for_testing run: docker compose -f tests/system_tests/compose.yaml up -d - name: Wait for Blueapi Server diff --git a/tests/system_tests/Dockerfile b/tests/system_tests/Dockerfile new file mode 100644 index 000000000..ba43f59f3 --- /dev/null +++ b/tests/system_tests/Dockerfile @@ -0,0 +1,7 @@ +# Runtime image plus dodal (demo extra) for system tests, keeps dodal out of the published image +ARG BASE_IMAGE=ghcr.io/diamondlightsource/blueapi:latest +FROM ${BASE_IMAGE} + +# The base image ships the blueapi source and uv.lock, so install the locked demo extra into its venv +WORKDIR /workspaces/blueapi +RUN UV_PROJECT_ENVIRONMENT=/app/.venv uv sync --locked --no-dev --no-editable --inexact --extra demo diff --git a/tests/system_tests/compose.yaml b/tests/system_tests/compose.yaml index d8e019b8d..34e3efa69 100644 --- a/tests/system_tests/compose.yaml +++ b/tests/system_tests/compose.yaml @@ -90,10 +90,12 @@ services: - label=disable blueapi: - image: blueapi-system-test # CI loads this from the container job; built locally if missing + image: blueapi-system-test build: - context: ../.. - target: runtime + context: . + args: + # CI sets this to the image built by the container job + BASE_IMAGE: ${BLUEAPI_BASE_IMAGE:-ghcr.io/diamondlightsource/blueapi:latest} network_mode: host # Port 8000 environment: - EPICS_CA_NAME_SERVERS=127.0.0.1:9064 From 25c422dd1aa49714070a4f24e98dde90a44ac7f9 Mon Sep 17 00:00:00 2001 From: Zoheb Shaikh <26975142+ZohebShaikh@users.noreply.github.com> Date: Tue, 20 Oct 2026 16:10:55 +0100 Subject: [PATCH 4/8] check 3 --- .github/workflows/_container.yml | 10 ---------- .github/workflows/_system_test.yml | 11 ----------- .github/workflows/ci.yml | 1 - tests/system_tests/Dockerfile | 7 ------- tests/system_tests/compose.yaml | 12 +++++------- tests/system_tests/config.yaml | 6 ++++++ 6 files changed, 11 insertions(+), 36 deletions(-) delete mode 100644 tests/system_tests/Dockerfile diff --git a/.github/workflows/_container.yml b/.github/workflows/_container.yml index 795ca334b..690576fe1 100644 --- a/.github/workflows/_container.yml +++ b/.github/workflows/_container.yml @@ -55,16 +55,6 @@ jobs: - name: Test cli works in cached runtime image run: docker run --rm tag_for_testing --version - - name: Save image for system tests - run: docker save tag_for_testing -o /tmp/blueapi-image.tar - - - name: Upload image for system tests - uses: actions/upload-artifact@v7 - with: - name: blueapi-image - path: /tmp/blueapi-image.tar - retention-days: 1 - - name: Create tags for publishing image id: meta uses: docker/metadata-action@v6 diff --git a/.github/workflows/_system_test.yml b/.github/workflows/_system_test.yml index 9177aae89..d298278f5 100644 --- a/.github/workflows/_system_test.yml +++ b/.github/workflows/_system_test.yml @@ -20,21 +20,10 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v7 - - name: Download blueapi image - uses: actions/download-artifact@v8 - with: - name: blueapi-image - path: /tmp - - - name: Load blueapi image - run: docker load -i /tmp/blueapi-image.tar - - name: Set up Docker Compose uses: docker/setup-compose-action@v2 - name: Compose services - env: - BLUEAPI_BASE_IMAGE: tag_for_testing run: docker compose -f tests/system_tests/compose.yaml up -d - name: Wait for Blueapi Server diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89b889962..54b29171b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,6 @@ jobs: python-version: ${{ matrix.python-version }} system-test: - needs: container uses: ./.github/workflows/_system_test.yml container: diff --git a/tests/system_tests/Dockerfile b/tests/system_tests/Dockerfile deleted file mode 100644 index ba43f59f3..000000000 --- a/tests/system_tests/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -# Runtime image plus dodal (demo extra) for system tests, keeps dodal out of the published image -ARG BASE_IMAGE=ghcr.io/diamondlightsource/blueapi:latest -FROM ${BASE_IMAGE} - -# The base image ships the blueapi source and uv.lock, so install the locked demo extra into its venv -WORKDIR /workspaces/blueapi -RUN UV_PROJECT_ENVIRONMENT=/app/.venv uv sync --locked --no-dev --no-editable --inexact --extra demo diff --git a/tests/system_tests/compose.yaml b/tests/system_tests/compose.yaml index 34e3efa69..a08e02676 100644 --- a/tests/system_tests/compose.yaml +++ b/tests/system_tests/compose.yaml @@ -90,25 +90,23 @@ services: - label=disable blueapi: - image: blueapi-system-test build: - context: . - args: - # CI sets this to the image built by the container job - BASE_IMAGE: ${BLUEAPI_BASE_IMAGE:-ghcr.io/diamondlightsource/blueapi:latest} + 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 volumes: - ./config.yaml:/config/config.yaml:ro - command: ["-c", "/config/config.yaml", "serve"] + # dodal is not in the image, setup-scratch clones and installs it from the config + entrypoint: ["sh", "-c", "mkdir -p /tmp/scratch/blueapi && blueapi -c /config/config.yaml setup-scratch && exec blueapi -c /config/config.yaml serve"] healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/healthz')"] interval: 5s timeout: 5s retries: 10 - start_period: 30s + start_period: 120s depends_on: configure-services: condition: service_completed_successfully diff --git a/tests/system_tests/config.yaml b/tests/system_tests/config.yaml index 89f94e533..95c3fa853 100644 --- a/tests/system_tests/config.yaml +++ b/tests/system_tests/config.yaml @@ -27,3 +27,9 @@ oidc: client_audience: "ixx-blueapi" opa: root: "http://localhost:8181/v1/data/diamond/policy/" +scratch: + root: /tmp/scratch/blueapi + repositories: + - name: dodal + remote_url: https://github.com/DiamondLightSource/dodal.git + target_revision: "3.0.3" # matches uv.lock From 3a2bb00433c8bad7998bae587f770dca5c3038fd Mon Sep 17 00:00:00 2001 From: Zoheb Shaikh <26975142+ZohebShaikh@users.noreply.github.com> Date: Tue, 20 Oct 2026 16:26:47 +0100 Subject: [PATCH 5/8] update the test --- .github/workflows/_system_test.yml | 12 ++++++++---- tests/system_tests/compose.yaml | 11 ++++++++--- tests/system_tests/config-scratch.yaml | 8 ++++++++ tests/system_tests/config.yaml | 6 ------ 4 files changed, 24 insertions(+), 13 deletions(-) create mode 100644 tests/system_tests/config-scratch.yaml diff --git a/.github/workflows/_system_test.yml b/.github/workflows/_system_test.yml index d298278f5..7886e77ab 100644 --- a/.github/workflows/_system_test.yml +++ b/.github/workflows/_system_test.yml @@ -23,11 +23,15 @@ jobs: - name: Set up Docker Compose uses: docker/setup-compose-action@v2 - - name: Compose services - run: docker compose -f tests/system_tests/compose.yaml up -d + - 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: Wait for Blueapi Server - run: timeout 300 sh -c 'until [ "$(docker inspect -f {{.State.Health.Status}} $(docker compose -f tests/system_tests/compose.yaml ps -q blueapi))" = healthy ]; do sleep 5; done' + - name: Compose services + run: docker compose -f tests/system_tests/compose.yaml --profile ci up -d --wait --wait-timeout 600 - 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 --profile ci logs diff --git a/tests/system_tests/compose.yaml b/tests/system_tests/compose.yaml index a08e02676..d6638d944 100644 --- a/tests/system_tests/compose.yaml +++ b/tests/system_tests/compose.yaml @@ -89,7 +89,9 @@ services: security_opt: - label=disable + # CI only, locally run the server with `just serve` (uv) instead blueapi: + profiles: [ci] build: context: ../.. target: runtime @@ -97,16 +99,19 @@ services: environment: - EPICS_CA_NAME_SERVERS=127.0.0.1:9064 - EPICS_PVA_NAME_SERVERS=127.0.0.1:9075 + - DODAL_VERSION volumes: - ./config.yaml:/config/config.yaml:ro - # dodal is not in the image, setup-scratch clones and installs it from the config - entrypoint: ["sh", "-c", "mkdir -p /tmp/scratch/blueapi && blueapi -c /config/config.yaml setup-scratch && exec blueapi -c /config/config.yaml serve"] + - ./config-scratch.yaml:/config/config-scratch.yaml:ro + # dodal is not in the image, setup-scratch clones and installs it from config-scratch.yaml + entrypoint: ["sh", "-c", "mkdir -p /tmp/scratch/blueapi && blueapi -c /config/config.yaml -c /config/config-scratch.yaml setup-scratch && exec blueapi -c /config/config.yaml -c /config/config-scratch.yaml serve"] healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/healthz')"] interval: 5s timeout: 5s retries: 10 - start_period: 120s + # setup-scratch plus device connection can take several minutes + start_period: 300s depends_on: configure-services: condition: service_completed_successfully 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/config.yaml b/tests/system_tests/config.yaml index 95c3fa853..89f94e533 100644 --- a/tests/system_tests/config.yaml +++ b/tests/system_tests/config.yaml @@ -27,9 +27,3 @@ oidc: client_audience: "ixx-blueapi" opa: root: "http://localhost:8181/v1/data/diamond/policy/" -scratch: - root: /tmp/scratch/blueapi - repositories: - - name: dodal - remote_url: https://github.com/DiamondLightSource/dodal.git - target_revision: "3.0.3" # matches uv.lock From 99e890d315d441a61c9ecc7a6533c4fc8eb9522a Mon Sep 17 00:00:00 2001 From: Zoheb Shaikh <26975142+ZohebShaikh@users.noreply.github.com> Date: Tue, 20 Oct 2026 16:31:52 +0100 Subject: [PATCH 6/8] wait for blueapi --- .github/workflows/_system_test.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/_system_test.yml b/.github/workflows/_system_test.yml index 7886e77ab..db003965a 100644 --- a/.github/workflows/_system_test.yml +++ b/.github/workflows/_system_test.yml @@ -27,7 +27,10 @@ jobs: run: echo "DODAL_VERSION=$(grep -A1 '^name = "dls-dodal"$' uv.lock | sed -n 's/^version = "\(.*\)"$/\1/p')" >> "$GITHUB_ENV" - name: Compose services - run: docker compose -f tests/system_tests/compose.yaml --profile ci up -d --wait --wait-timeout 600 + # Wait on blueapi only: --wait on everything fails on the one-shot init container exiting + run: | + docker compose -f tests/system_tests/compose.yaml --profile ci up -d + docker compose -f tests/system_tests/compose.yaml --profile ci up -d --wait --wait-timeout 600 blueapi - name: Run tests run: uv run --locked tox -e system-test From b23864e418cf8dc4a358ba8f3628fbb3d18b0922 Mon Sep 17 00:00:00 2001 From: Zoheb Shaikh <26975142+ZohebShaikh@users.noreply.github.com> Date: Tue, 20 Oct 2026 16:57:55 +0100 Subject: [PATCH 7/8] fix(tests): connect system test devices and move blueapi config to its own folder - Set COMPOSE_PROFILES=test,ci in CI: --profile ci replaced the test profile from .env, so the sim IOCs and ca-gateway never started - Cap nofile at 1024 for blueapi and ca-gateway (via an include override of example-services); a huge default limit makes EPICS CA spin and time out - Move blueapi server config into services/blueapi with a start.sh entrypoint and mount the folder Co-Authored-By: Claude Opus 5.5 --- .github/workflows/_system_test.yml | 9 ++++++--- docs/how-to/1.2 authn-authz.md | 2 +- docs/how-to/1.6 configure-tiled.md | 2 +- .../how-to/just-run-blueapi-and-services-locally.md | 4 ++-- justfile | 6 +++--- tests/system_tests/compose.yaml | 13 ++++++++----- .../{ => services/blueapi}/config-scratch.yaml | 0 .../system_tests/{ => services/blueapi}/config.yaml | 0 tests/system_tests/services/blueapi/start.sh | 6 ++++++ .../services/example-services-override.yaml | 8 ++++++++ tests/system_tests/test_blueapi_system.py | 2 +- 11 files changed, 36 insertions(+), 16 deletions(-) rename tests/system_tests/{ => services/blueapi}/config-scratch.yaml (100%) rename tests/system_tests/{ => services/blueapi}/config.yaml (100%) create mode 100755 tests/system_tests/services/blueapi/start.sh create mode 100644 tests/system_tests/services/example-services-override.yaml diff --git a/.github/workflows/_system_test.yml b/.github/workflows/_system_test.yml index db003965a..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: @@ -29,12 +32,12 @@ jobs: - 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 --profile ci up -d - docker compose -f tests/system_tests/compose.yaml --profile ci up -d --wait --wait-timeout 600 blueapi + 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 --profile ci logs + run: docker compose -f tests/system_tests/compose.yaml logs diff --git a/docs/how-to/1.2 authn-authz.md b/docs/how-to/1.2 authn-authz.md index 5671d14ec..c902fa2bd 100644 --- a/docs/how-to/1.2 authn-authz.md +++ b/docs/how-to/1.2 authn-authz.md @@ -68,7 +68,7 @@ The authorization provider is opa.diamond.ac.uk An example configuration to to customise authorization is shown in this `config.yaml` file. -```{literalinclude} ../../tests/system_tests/config.yaml +```{literalinclude} ../../tests/system_tests/services/blueapi/config.yaml :language: yaml ``` Else, the default values in `OpaConfig` class defined in `config.py` will be used. diff --git a/docs/how-to/1.6 configure-tiled.md b/docs/how-to/1.6 configure-tiled.md index 866ccfd87..326370c44 100644 --- a/docs/how-to/1.6 configure-tiled.md +++ b/docs/how-to/1.6 configure-tiled.md @@ -6,7 +6,7 @@ Tiled is a server and data management system used to store and organise experime An example configuration to enable tiled is shown in this `config.yaml` file. -```{literalinclude} ../../tests/system_tests/config.yaml +```{literalinclude} ../../tests/system_tests/services/blueapi/config.yaml :language: yaml ``` diff --git a/docs/how-to/just-run-blueapi-and-services-locally.md b/docs/how-to/just-run-blueapi-and-services-locally.md index 5a8303b42..a3c735d86 100644 --- a/docs/how-to/just-run-blueapi-and-services-locally.md +++ b/docs/how-to/just-run-blueapi-and-services-locally.md @@ -10,7 +10,7 @@ Before starting, ensure you have followed the [Installation instructions](../tut - A. initialise the example-services repo - B. launch an instance of NumTracker, RabbitMQ, Keycloak, Tiled, OPA and a number of IOCs in detached mode - C. set required EPICS environmental variables - - D. start the BlueAPI server using the the config in `tests/system_tests/config.yaml` + - D. start the BlueAPI server using the the config in `tests/system_tests/services/blueapi/config.yaml` 3. To run the above separately use the following commands: - 2A and 2B: `just compose` @@ -29,7 +29,7 @@ Channel Access To log in through the BlueAPI CLI: -1. Run `blueapi login` (if you want to run a plan with stomp config, add the `-c tests/system_tests/config.yaml` parameter) +1. Run `blueapi login` (if you want to run a plan with stomp config, add the `-c tests/system_tests/services/blueapi/config.yaml` parameter) 2. Follow the login prompted to Keycloak, then log in with the username `admin` and password `admin` 3. When prompted by Keycloak, grant BlueAPI access to the listed privileges 4. Run `blueapi controller plans` to check that the log in has succeeded diff --git a/justfile b/justfile index e0b40df56..d40fa4fab 100644 --- a/justfile +++ b/justfile @@ -26,11 +26,11 @@ compose +ARGS="up -d --no-recreate": init-example-services _check-runner serve *OPTS: #!/usr/bin/env bash source tests/system_tests/.env - uv run blueapi -c tests/system_tests/config.yaml {{ OPTS }} serve + uv run blueapi -c tests/system_tests/services/blueapi/config.yaml {{ OPTS }} serve [doc('Run a plan using the blueapi CLI')] run PLAN PARAMS: - uv run blueapi -c tests/system_tests/config.yaml controller run -i {{ SESSION }} {{ PLAN }} '{{ PARAMS }}' + uv run blueapi -c tests/system_tests/services/blueapi/config.yaml controller run -i {{ SESSION }} {{ PLAN }} '{{ PARAMS }}' [doc('Regenerate schemas, run pre-commit checks and type checking')] lint: @@ -58,7 +58,7 @@ repl: uv run --with ptpython ptpython -i <(cat << EOF from blueapi.client import BlueapiClient from blueapi.client.rest import ServiceUnavailableError - bc = BlueapiClient.from_config_file("tests/system_tests/config.yaml").with_instrument_session("cm12345-1") + bc = BlueapiClient.from_config_file("tests/system_tests/services/blueapi/config.yaml").with_instrument_session("cm12345-1") try: bc.login() except KeyboardInterrupt: diff --git a/tests/system_tests/compose.yaml b/tests/system_tests/compose.yaml index d6638d944..b32550045 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: @@ -100,11 +102,12 @@ services: - 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:/config/config.yaml:ro - - ./config-scratch.yaml:/config/config-scratch.yaml:ro - # dodal is not in the image, setup-scratch clones and installs it from config-scratch.yaml - entrypoint: ["sh", "-c", "mkdir -p /tmp/scratch/blueapi && blueapi -c /config/config.yaml -c /config/config-scratch.yaml setup-scratch && exec blueapi -c /config/config.yaml -c /config/config-scratch.yaml serve"] + - ./services/blueapi:/blueapi:ro + entrypoint: ["sh", "/blueapi/start.sh"] healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/healthz')"] interval: 5s diff --git a/tests/system_tests/config-scratch.yaml b/tests/system_tests/services/blueapi/config-scratch.yaml similarity index 100% rename from tests/system_tests/config-scratch.yaml rename to tests/system_tests/services/blueapi/config-scratch.yaml diff --git a/tests/system_tests/config.yaml b/tests/system_tests/services/blueapi/config.yaml similarity index 100% rename from tests/system_tests/config.yaml rename to tests/system_tests/services/blueapi/config.yaml 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 diff --git a/tests/system_tests/test_blueapi_system.py b/tests/system_tests/test_blueapi_system.py index 138ee85c9..bfc36ec49 100644 --- a/tests/system_tests/test_blueapi_system.py +++ b/tests/system_tests/test_blueapi_system.py @@ -249,7 +249,7 @@ def clean_existing_tasks(rest_client: BlueapiRestClient): @pytest.fixture(autouse=True, scope="module") def reset_numtracker(): - server_config = load_config(Path(_DATA_PATH, "config.yaml")) + server_config = load_config(_DATA_PATH / "services" / "blueapi" / "config.yaml") nt_url = server_config.numtracker.url # type: ignore - if numtracker is None we should fail response = requests.post( str(nt_url), From 8326808280f2f6deaed45dcae622f0b9f48a2617 Mon Sep 17 00:00:00 2001 From: Zoheb Shaikh <26975142+ZohebShaikh@users.noreply.github.com> Date: Wed, 21 Oct 2026 08:53:07 +0100 Subject: [PATCH 8/8] use old place for config files --- docs/how-to/1.2 authn-authz.md | 2 +- docs/how-to/1.6 configure-tiled.md | 2 +- docs/how-to/just-run-blueapi-and-services-locally.md | 4 ++-- justfile | 6 +++--- tests/system_tests/compose.yaml | 4 +++- .../system_tests/{services/blueapi => }/config-scratch.yaml | 0 tests/system_tests/{services/blueapi => }/config.yaml | 0 tests/system_tests/test_blueapi_system.py | 2 +- 8 files changed, 11 insertions(+), 9 deletions(-) rename tests/system_tests/{services/blueapi => }/config-scratch.yaml (100%) rename tests/system_tests/{services/blueapi => }/config.yaml (100%) diff --git a/docs/how-to/1.2 authn-authz.md b/docs/how-to/1.2 authn-authz.md index c902fa2bd..5671d14ec 100644 --- a/docs/how-to/1.2 authn-authz.md +++ b/docs/how-to/1.2 authn-authz.md @@ -68,7 +68,7 @@ The authorization provider is opa.diamond.ac.uk An example configuration to to customise authorization is shown in this `config.yaml` file. -```{literalinclude} ../../tests/system_tests/services/blueapi/config.yaml +```{literalinclude} ../../tests/system_tests/config.yaml :language: yaml ``` Else, the default values in `OpaConfig` class defined in `config.py` will be used. diff --git a/docs/how-to/1.6 configure-tiled.md b/docs/how-to/1.6 configure-tiled.md index 326370c44..866ccfd87 100644 --- a/docs/how-to/1.6 configure-tiled.md +++ b/docs/how-to/1.6 configure-tiled.md @@ -6,7 +6,7 @@ Tiled is a server and data management system used to store and organise experime An example configuration to enable tiled is shown in this `config.yaml` file. -```{literalinclude} ../../tests/system_tests/services/blueapi/config.yaml +```{literalinclude} ../../tests/system_tests/config.yaml :language: yaml ``` diff --git a/docs/how-to/just-run-blueapi-and-services-locally.md b/docs/how-to/just-run-blueapi-and-services-locally.md index a3c735d86..5a8303b42 100644 --- a/docs/how-to/just-run-blueapi-and-services-locally.md +++ b/docs/how-to/just-run-blueapi-and-services-locally.md @@ -10,7 +10,7 @@ Before starting, ensure you have followed the [Installation instructions](../tut - A. initialise the example-services repo - B. launch an instance of NumTracker, RabbitMQ, Keycloak, Tiled, OPA and a number of IOCs in detached mode - C. set required EPICS environmental variables - - D. start the BlueAPI server using the the config in `tests/system_tests/services/blueapi/config.yaml` + - D. start the BlueAPI server using the the config in `tests/system_tests/config.yaml` 3. To run the above separately use the following commands: - 2A and 2B: `just compose` @@ -29,7 +29,7 @@ Channel Access To log in through the BlueAPI CLI: -1. Run `blueapi login` (if you want to run a plan with stomp config, add the `-c tests/system_tests/services/blueapi/config.yaml` parameter) +1. Run `blueapi login` (if you want to run a plan with stomp config, add the `-c tests/system_tests/config.yaml` parameter) 2. Follow the login prompted to Keycloak, then log in with the username `admin` and password `admin` 3. When prompted by Keycloak, grant BlueAPI access to the listed privileges 4. Run `blueapi controller plans` to check that the log in has succeeded diff --git a/justfile b/justfile index d40fa4fab..e0b40df56 100644 --- a/justfile +++ b/justfile @@ -26,11 +26,11 @@ compose +ARGS="up -d --no-recreate": init-example-services _check-runner serve *OPTS: #!/usr/bin/env bash source tests/system_tests/.env - uv run blueapi -c tests/system_tests/services/blueapi/config.yaml {{ OPTS }} serve + uv run blueapi -c tests/system_tests/config.yaml {{ OPTS }} serve [doc('Run a plan using the blueapi CLI')] run PLAN PARAMS: - uv run blueapi -c tests/system_tests/services/blueapi/config.yaml controller run -i {{ SESSION }} {{ PLAN }} '{{ PARAMS }}' + uv run blueapi -c tests/system_tests/config.yaml controller run -i {{ SESSION }} {{ PLAN }} '{{ PARAMS }}' [doc('Regenerate schemas, run pre-commit checks and type checking')] lint: @@ -58,7 +58,7 @@ repl: uv run --with ptpython ptpython -i <(cat << EOF from blueapi.client import BlueapiClient from blueapi.client.rest import ServiceUnavailableError - bc = BlueapiClient.from_config_file("tests/system_tests/services/blueapi/config.yaml").with_instrument_session("cm12345-1") + bc = BlueapiClient.from_config_file("tests/system_tests/config.yaml").with_instrument_session("cm12345-1") try: bc.login() except KeyboardInterrupt: diff --git a/tests/system_tests/compose.yaml b/tests/system_tests/compose.yaml index b32550045..25570146b 100644 --- a/tests/system_tests/compose.yaml +++ b/tests/system_tests/compose.yaml @@ -106,7 +106,9 @@ services: ulimits: nofile: 1024 volumes: - - ./services/blueapi:/blueapi:ro + - ./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')"] diff --git a/tests/system_tests/services/blueapi/config-scratch.yaml b/tests/system_tests/config-scratch.yaml similarity index 100% rename from tests/system_tests/services/blueapi/config-scratch.yaml rename to tests/system_tests/config-scratch.yaml diff --git a/tests/system_tests/services/blueapi/config.yaml b/tests/system_tests/config.yaml similarity index 100% rename from tests/system_tests/services/blueapi/config.yaml rename to tests/system_tests/config.yaml diff --git a/tests/system_tests/test_blueapi_system.py b/tests/system_tests/test_blueapi_system.py index bfc36ec49..138ee85c9 100644 --- a/tests/system_tests/test_blueapi_system.py +++ b/tests/system_tests/test_blueapi_system.py @@ -249,7 +249,7 @@ def clean_existing_tasks(rest_client: BlueapiRestClient): @pytest.fixture(autouse=True, scope="module") def reset_numtracker(): - server_config = load_config(_DATA_PATH / "services" / "blueapi" / "config.yaml") + server_config = load_config(Path(_DATA_PATH, "config.yaml")) nt_url = server_config.numtracker.url # type: ignore - if numtracker is None we should fail response = requests.post( str(nt_url),