SUT topology template
Use this optional template when your UI test environment depends on several services and a single sut_preset block in test_execution.yml becomes too cramped.
The idea is simple:
- keep
.ogoron/configs/test_execution.ymlfocused on execution profiles and thin SUT hooks - describe multi-service topology in a separate manifest
- let a small orchestration layer read that manifest and implement
up,healthcheck, anddown
In practice, this template is most useful for the Ogoron UI track, where ogoron prepare ui-workspace, ogoron run smoke, and ogoron run ui-tests need a consistent view of the environment.
When to use it
This template becomes useful when your environment includes combinations such as:
- several backends and several frontends
- different runtime styles across services (
shell,compose,external) - heavy local services that are sometimes reused from a shared environment
- different service wiring in
localandci
Suggested file location
Recommended location:
.ogoron/configs/sut_topology.yml
This file is optional and separate from test_execution.yml.
File shape
The template uses four main ideas:
defaults- common timeout values
profiles- named runtime situations such as
local,ci, orshared-env
- named runtime situations such as
services- named services with dependencies
modes- different ways to operate the same service (
shell,compose,external, ...)
- different ways to operate the same service (
Each service mode may define:
startstophealthcheckreadinessbase_urlenvenv_files
Design notes
Important decisions in this template:
- no
groupsin the first version externalis a first-class modehealthcheck.type: noneis allowed only when declared explicitly with a reasondepends_onlives on services, not on profiles- the goal is not to recreate Docker Compose; the goal is to define a Docker-agnostic orchestration contract
Template
Copy this template into .ogoron/configs/sut_topology.yml and adapt the service names, commands, URLs, and environment values for your project:
version: 1
# Optional multi-service SUT topology template for Ogoron-owned UI testing.
#
# Use this file when a repository needs to describe:
# - multiple services
# - multiple runtime profiles (`local`, `ci`, `shared-env`, ...)
# - different execution modes per service (`shell`, `compose`, `external`, ...)
#
# Keep `test_execution.yml` thin.
# Let `test_execution.yml` call an orchestration layer that reads this topology.
defaults:
startup_timeout_seconds: 90
shutdown_timeout_seconds: 30
healthcheck_timeout_seconds: 5
profiles:
local:
description: Developer workstation profile.
service_modes:
backend-a: shell
backend-b: shell
frontend-main: shell
frontend-docs: shell
frontend-public: shell
ci:
description: CI-oriented profile.
service_modes:
backend-a: compose
backend-b: shell
frontend-main: compose
frontend-docs: compose
frontend-public: compose
shared-env:
description: Reuse services that are already running elsewhere.
service_modes:
backend-a: external
backend-b: external
frontend-main: external
frontend-docs: external
frontend-public: external
services:
backend-a:
role: backend
cwd: systems/backend-a
depends_on: []
modes:
shell:
start:
cmd: ["./run-backend-a.sh"]
stop:
strategy: process_group
healthcheck:
type: http
url: http://127.0.0.1:33141/health
base_url: http://127.0.0.1:33141
env_files:
- ./.env.local
compose:
start:
cmd: ["docker", "compose", "up", "-d", "backend-a"]
stop:
cmd: ["docker", "compose", "down"]
healthcheck:
type: http
url: http://127.0.0.1:33141/health
base_url: http://127.0.0.1:33141
external:
start:
skip: true
stop:
skip: true
healthcheck:
type: http
url: ${BACKEND_A_BASE_URL}/health
base_url: ${BACKEND_A_BASE_URL}
backend-b:
role: backend
cwd: systems/backend-b
depends_on: [backend-a]
modes:
shell:
start:
cmd: ["python", "-m", "uvicorn", "src.main:app", "--host", "127.0.0.1", "--port", "33142"]
stop:
strategy: process_group
healthcheck:
type: http
url: http://127.0.0.1:33142/healthz
readiness:
type: http
url: http://127.0.0.1:33142/readyz
base_url: http://127.0.0.1:33142
env:
FEATURE_FLAG_EXAMPLE: "1"
external:
start:
skip: true
stop:
skip: true
healthcheck:
type: http
url: ${BACKEND_B_BASE_URL}/healthz
readiness:
type: http
url: ${BACKEND_B_BASE_URL}/readyz
base_url: ${BACKEND_B_BASE_URL}
frontend-main:
role: frontend
cwd: systems/frontend-main
depends_on: [backend-a, backend-b]
modes:
shell:
start:
cmd: ["npm", "run", "dev", "--", "--host", "127.0.0.1", "--port", "33143"]
stop:
strategy: process_group
healthcheck:
type: http
url: http://127.0.0.1:33143
base_url: http://127.0.0.1:33143
env:
VITE_BACKEND_A_BASE_URL: http://127.0.0.1:33141
VITE_BACKEND_B_BASE_URL: http://127.0.0.1:33142
compose:
start:
cmd: ["docker", "compose", "up", "-d", "frontend-main"]
stop:
cmd: ["docker", "compose", "down"]
healthcheck:
type: http
url: http://127.0.0.1:33143
base_url: http://127.0.0.1:33143
external:
start:
skip: true
stop:
skip: true
healthcheck:
type: http
url: ${FRONTEND_MAIN_BASE_URL}
base_url: ${FRONTEND_MAIN_BASE_URL}
frontend-docs:
role: frontend
cwd: systems/frontend-docs
depends_on: []
modes:
shell:
start:
cmd: ["npm", "run", "start", "--", "--port", "33144"]
stop:
strategy: process_group
healthcheck:
type: http
url: http://127.0.0.1:33144
base_url: http://127.0.0.1:33144
compose:
start:
cmd: ["docker", "compose", "up", "-d", "frontend-docs"]
stop:
cmd: ["docker", "compose", "down"]
healthcheck:
type: http
url: http://127.0.0.1:33144
base_url: http://127.0.0.1:33144
external:
start:
skip: true
stop:
skip: true
healthcheck:
type: http
url: ${FRONTEND_DOCS_BASE_URL}
base_url: ${FRONTEND_DOCS_BASE_URL}
frontend-public:
role: frontend
cwd: systems/frontend-public
depends_on: []
modes:
shell:
start:
cmd: ["npm", "run", "dev", "--", "--host", "127.0.0.1", "--port", "33145"]
stop:
strategy: process_group
healthcheck:
type: http
url: http://127.0.0.1:33145
base_url: http://127.0.0.1:33145
compose:
start:
cmd: ["docker", "compose", "up", "-d", "frontend-public"]
stop:
cmd: ["docker", "compose", "down"]
healthcheck:
type: http
url: http://127.0.0.1:33145
base_url: http://127.0.0.1:33145
external:
start:
skip: true
stop:
skip: true
healthcheck:
type: http
url: ${FRONTEND_PUBLIC_BASE_URL}
base_url: ${FRONTEND_PUBLIC_BASE_URL}
shared-cdn:
role: external_dependency
cwd: .
depends_on: []
modes:
external:
start:
skip: true
stop:
skip: true
healthcheck:
type: none
reason: No dedicated readiness signal; availability is verified indirectly by consumer tests.
base_url: ${SHARED_CDN_BASE_URL}
If you prefer to download the same file directly, it is also available as:
How to adapt it
Replace the neutral service names with your own:
backend-abackend-bfrontend-mainfrontend-docsfrontend-public
Then adjust:
cwddepends_oncmdbase_url- health and readiness endpoints
- environment variables
Relationship to test_execution.yml
Keep test_execution.yml small.
For example, a future SUT preset might call a dedicated orchestration entrypoint:
sut:
default_preset: qa
presets:
qa:
up:
- name: sut-up
cmd: ["./scripts/sut", "up", "--profile", "local"]
healthcheck:
- name: sut-healthcheck
cmd: ["./scripts/sut", "healthcheck", "--profile", "local"]
down:
- name: sut-down
cmd: ["./scripts/sut", "down", "--profile", "local"]