From 2ae5ef3157b2d9e6b41eec8f24dffca3e8e31303 Mon Sep 17 00:00:00 2001 From: Zoheb Shaikh <26975142+ZohebShaikh@users.noreply.github.com> Date: Mon, 24 Aug 2026 11:43:09 +0100 Subject: [PATCH 1/2] ci: Configure numtracker as part of compose --- justfile | 8 ---- tests/system_tests/compose.yaml | 1 + tests/system_tests/services/startup.py | 51 +++++++++++++++++++++-- tests/system_tests/test_blueapi_system.py | 7 +++- 4 files changed, 53 insertions(+), 14 deletions(-) diff --git a/justfile b/justfile index 71613f4bc..3433acd7f 100644 --- a/justfile +++ b/justfile @@ -4,14 +4,6 @@ RUNNER := "docker" compose +ARGS="up -d": {{ RUNNER }} compose -f tests/system_tests/compose.yaml {{ARGS}} -configure-adsim: (compose "exec" "numtracker" "/app/numtracker" "client" "configure" "adsim" - "--directory" '/tmp/' - "--scan" '{instrument}-{scan_number}' - "--detector" '{instrument}-{scan_number}-{detector}' - "--number" "43") - -services: compose configure-adsim - serve *OPTS: #!/usr/bin/env bash source tests/system_tests/.env diff --git a/tests/system_tests/compose.yaml b/tests/system_tests/compose.yaml index 3b116938f..c5be60e48 100644 --- a/tests/system_tests/compose.yaml +++ b/tests/system_tests/compose.yaml @@ -56,6 +56,7 @@ services: - KC_BOOTSTRAP_ADMIN_PASSWORD=admin - KC_BOOTSTRAP_ADMIN_USERNAME=admin - KEYCLOAK_REALM=master + - NT_URL=http://localhost:8406/graphql command: ["uv", "run", "/startup.py"] depends_on: keycloak: diff --git a/tests/system_tests/services/startup.py b/tests/system_tests/services/startup.py index 2a27cef68..5919d1447 100644 --- a/tests/system_tests/services/startup.py +++ b/tests/system_tests/services/startup.py @@ -2,6 +2,7 @@ # requires-python = ">=3.11" # dependencies = [ # "mantelo==2.2.1", +# "requests" # ] # /// """Configure the local Keycloak instance used by the system tests.""" @@ -11,12 +12,13 @@ from functools import wraps from typing import Any +import requests from mantelo import KeycloakAdmin -SERVER = os.environ.get("KEYCLOAK_SERVER") -REALM = os.environ.get("KEYCLOAK_REALM") -ADMIN_USERNAME = os.environ.get("KC_BOOTSTRAP_ADMIN_USERNAME") -ADMIN_PASSWORD = os.environ.get("KC_BOOTSTRAP_ADMIN_PASSWORD") +SERVER = os.environ.get("KEYCLOAK_SERVER", "http://localhost:8081") +REALM = os.environ.get("KEYCLOAK_REALM", "master") +ADMIN_USERNAME = os.environ.get("KC_BOOTSTRAP_ADMIN_USERNAME", "admin") +ADMIN_PASSWORD = os.environ.get("KC_BOOTSTRAP_ADMIN_PASSWORD", "admin") USERS = {"alice": "alice", "bob": "bob"} @@ -138,6 +140,9 @@ def cleanup_components() -> None: def create_users() -> None: for username, password in USERS.items(): + if admin.users.get(username=username): + print(f">> Skipping {username} (exists)") + continue response, _ = admin.users.as_raw().post({"username": username, "enabled": True}) user_id = response.headers["Location"].rsplit("/", 1)[-1] admin.users(user_id).reset_password.put( @@ -229,6 +234,7 @@ def create_user_service_account_client( def create_clients() -> None: create_cli_client(client_id="ixx-cli-blueapi", aud="ixx-blueapi") create_cli_client(client_id="tiled-cli", aud="tiled") + create_cli_client(client_id="numtracker", aud="numtracker") create_web_client( client_id="ixx-blueapi", aud="ixx-blueapi", @@ -254,7 +260,44 @@ def create_clients() -> None: ) +def configure_numtracker(): + def _(): + token_url = SERVER + "/realms/master/protocol/openid-connect/token" + response = requests.post( + token_url, + data={ + "client_id": "system-test-blueapi-admin", + "client_secret": "secret", + "grant_type": "client_credentials", + }, + ) + response.raise_for_status() + return response.json().get("access_token") + + nt_url = os.environ.get("NT_URL", "http://localhost:8406/graphql") + response = requests.post( + str(nt_url), + json={ + "query": """mutation { + configure(instrument: "adsim", + config: {directory: "/tmp/", + scan: "{instrument}-{scan_number}", + detector: "{instrument}-{scan_number}-{detector}", + scanNumber: 43}) { + scanTemplate + } + }""" + }, + headers={"authorization": "Bearer " + _()}, + ) + response.raise_for_status() + if response.json().get("errors") is not None: + raise Exception(response.json()) + print(">> Configurated numtracker") + + if __name__ == "__main__": cleanup_components() create_users() create_clients() + configure_numtracker() diff --git a/tests/system_tests/test_blueapi_system.py b/tests/system_tests/test_blueapi_system.py index 89a490834..452b2c5c9 100644 --- a/tests/system_tests/test_blueapi_system.py +++ b/tests/system_tests/test_blueapi_system.py @@ -271,7 +271,7 @@ def clean_existing_tasks(rest_client: BlueapiRestClient): def reset_numtracker(): server_config = load_config(Path(_DATA_PATH, "config.yaml")) nt_url = server_config.numtracker.url # type: ignore - if numtracker is None we should fail - requests.post( + response = requests.post( str(nt_url), json={ "query": f"""mutation {{ @@ -285,7 +285,10 @@ def reset_numtracker(): }}""" }, headers={"authorization": "Bearer " + get_access_token(User.admin)}, - ).raise_for_status() + ) + response.raise_for_status() + if response.json().get("errors") is not None: + raise Exception(response.json()) yield From 507f1c50abb1121af2961fca524ae050a69d6dfd Mon Sep 17 00:00:00 2001 From: Zoheb Shaikh <26975142+ZohebShaikh@users.noreply.github.com> Date: Tue, 25 Aug 2026 08:09:15 +0000 Subject: [PATCH 2/2] code review changes --- tests/system_tests/services/startup.py | 35 +++++++++++++------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/tests/system_tests/services/startup.py b/tests/system_tests/services/startup.py index 5919d1447..2bfa722fc 100644 --- a/tests/system_tests/services/startup.py +++ b/tests/system_tests/services/startup.py @@ -19,6 +19,7 @@ REALM = os.environ.get("KEYCLOAK_REALM", "master") ADMIN_USERNAME = os.environ.get("KC_BOOTSTRAP_ADMIN_USERNAME", "admin") ADMIN_PASSWORD = os.environ.get("KC_BOOTSTRAP_ADMIN_PASSWORD", "admin") +NT_URL = os.environ.get("NT_URL", "http://localhost:8406/graphql") USERS = {"alice": "alice", "bob": "bob"} @@ -261,34 +262,32 @@ def create_clients() -> None: def configure_numtracker(): - def _(): - token_url = SERVER + "/realms/master/protocol/openid-connect/token" - response = requests.post( - token_url, - data={ - "client_id": "system-test-blueapi-admin", - "client_secret": "secret", - "grant_type": "client_credentials", - }, - ) - response.raise_for_status() - return response.json().get("access_token") + token_url = SERVER + "/realms/master/protocol/openid-connect/token" + response = requests.post( + token_url, + data={ + "client_id": "system-test-blueapi-admin", + "client_secret": "secret", + "grant_type": "client_credentials", + }, + ) + response.raise_for_status() + access_token = response.json().get("access_token") - nt_url = os.environ.get("NT_URL", "http://localhost:8406/graphql") response = requests.post( - str(nt_url), + NT_URL, json={ "query": """mutation { configure(instrument: "adsim", config: {directory: "/tmp/", - scan: "{instrument}-{scan_number}", - detector: "{instrument}-{scan_number}-{detector}", - scanNumber: 43}) { + scan: "{instrument}-{scan_number}", + detector: "{instrument}-{scan_number}-{detector}", + scanNumber: 43}) { scanTemplate } }""" }, - headers={"authorization": "Bearer " + _()}, + headers={"authorization": "Bearer " + access_token}, ) response.raise_for_status() if response.json().get("errors") is not None: