wex_addon_services_platform
Version: 12.10.6
This addon extends wex with install, setup, and ready lifecycle commands for self-hosted platform services: GitLab, GitLab Runner, Supabase, n8n, Odoo, Ollama, Nextcloud, RabbitMQ, SonarQube, Listmonk, Temporal, and OpenClaw. Each command handles the work its platform requires — writing service configuration into the app config, generating secrets, fetching upstream config files, or verifying that the container is healthy. It targets wex app developers who run one or more of these platforms as Docker services inside a wex-managed app.
Table of Contents
- Installation
- Quickstart
- Tests
- Architecture
- Integration in the Suite
- Dependencies
- Versioning & Compatibility Policy
- License
- About us
- Known Limitations & Roadmap
- Status & Compatibility
- Useful Links
- Migration Notes
Installation
pip install wexample-wex-addon-services-platform
Requires Python >=3.10.
Quickstart
Install the package into the same Python environment as wex:
pip install wexample-wex-addon-services-platform
The package exposes one public symbol:
from wexample_wex_addon_services_platform import ServicesPlatformAddonManager
Pass it to the kernel at startup alongside the other addon managers your wex instance loads:
from wexample_wex_core.common.kernel import Kernel
from wexample_wex_core.addons.core.core_addon_manager import CoreAddonManager
from wexample_wex_addon_services_platform import ServicesPlatformAddonManager
kernel = Kernel(entrypoint_path=wex_dir)
kernel.setup(addons=[CoreAddonManager, ServicesPlatformAddonManager])
Once the kernel is running, add a platform service to a wex app from the app's root directory — ollama for this example:
wex service/install --service ollama
The command writes service.ollama into the app's config.yml, creates the ollama/ host directory, and runs the service-specific install hook (src/wexample_wex_addon_services_platform/services/ollama/commands/service/install.py), which sets service.ollama.host and service.ollama.port. After that wex app/start brings the container up.
To verify the container is healthy after start:
wex @ollama::service/ready
The same service/install --service <name> call works for every platform the addon ships: supabase, n8n, gitlab, gitlab_runner, odoo, nextcloud, rabbitmq, sonarqube, listmonk, temporal, and openclaw. Platforms that require secrets — Supabase generates JWT keys and fetches upstream config files; n8n generates a basic-auth password — do all of that inside their own install hook with no extra input required.
Tests
This project uses pytest for testing and pytest-cov for code coverage analysis.
Installation
First, install the required testing dependencies:
.venv/bin/python -m pip install pytest pytest-cov
Basic Usage
Run all tests with coverage:
.venv/bin/python -m pytest --cov --cov-report=html
Common Commands
# Run tests with coverage for a specific module
.venv/bin/python -m pytest --cov=your_module
# Show which lines are not covered
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
# Generate an HTML coverage report
.venv/bin/python -m pytest --cov=your_module --cov-report=html
# Combine terminal and HTML reports
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
# Run specific test file with coverage
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
Viewing HTML Reports
After generating an HTML report, open htmlcov/index.html in your browser to view detailed line-by-line coverage information.
Coverage Threshold
To enforce a minimum coverage percentage:
.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
This will cause the test suite to fail if coverage drops below 80%.
Architecture
The addon is a Python package that registers a collection of platform-service definitions into the wex kernel. It adds no runtime framework of its own — every piece it ships is either a service descriptor, a Docker Compose file, or a command function that runs when the user invokes a wex CLI verb.
Addon manager
src/wexample_wex_addon_services_platform/services_platform_addon_manager.py is the single entry point the host kernel needs:
from wexample_wex_addon_services_platform import ServicesPlatformAddonManager
kernel.setup(addons=[..., ServicesPlatformAddonManager])
ServicesPlatformAddonManager extends AbstractAddonManager from wexample_wex_core and implements get_package_module(), which returns the wexample_wex_addon_services_platform module object. The framework uses that to walk the package tree and auto-discover every @command-decorated function inside it.
Service modules
Each platform lives under src/wexample_wex_addon_services_platform/services/<name>/. The layout inside that directory is:
| path | what it owns |
|---|---|
service.yml |
name, tags, optional vars block, optional dependencies, pointer to the Compose file |
docker/docker-compose.yml |
canonical container definition used by the wex runtime |
samples/env/{prod,dev}/docker/docker-compose.yml |
override fragments for concrete environments |
app_service.py |
AppService subclass; declares the host directory tree the container requires |
commands/<group>/<verb>.py |
one file per CLI command |
Services that ship today: gitlab, gitlab_runner, supabase, n8n, odoo, ollama, openclaw, nextcloud, temporal, rabbitmq, sonarqube, listmonk, jenkins.
AppService subclass
Services whose containers require specific host directories or permission modes carry an AppService subclass that overrides get_workdir_contribution(). The method returns a nested dict describing the expected directory tree; the framework's filestate layer rectifies it — creating missing entries and enforcing owner/permissions — each time the app starts.
For example, src/wexample_wex_addon_services_platform/services/supabase/app_service.py declares supabase/db/data with owner: 105:106, permissions: 700 (the uid:gid of the supabase/postgres image user), and src/wexample_wex_addon_services_platform/services/n8n/app_service.py declares n8n/ with owner: 1000:1000, permissions: 750 (the node user in the n8n image).
Services that have no special filesystem requirements — or whose container runs as root and manages its own tree — have no AppService subclass.
Commands
Commands follow three lifecycle verbs:
service/install — runs once per service per app. It reads the app's config.yml, writes the service's required keys (host, port, credentials, generated secrets), then calls app_workdir.get_runtime_config(rebuild=True) to flush the cached config. Supabase's install (src/wexample_wex_addon_services_platform/services/supabase/commands/service/install.py) also generates a full JWT key set and fetches official config files from GitHub with curl. n8n's install (src/wexample_wex_addon_services_platform/services/n8n/commands/service/install.py) generates a random basic-auth password.
service/setup — idempotent filesystem preparation. It creates files or directories the container needs on first boot but cannot create itself (e.g., Supabase's pgsodium_root.key, GitLab Runner's config.toml stub). Unlike install it is safe to run repeatedly.
service/ready — health check. Each implementation derives the container name as {app_project_name}_{service_name} from the runtime config, then runs a docker exec against a service-specific health endpoint. Supabase checks kong health inside the supabase_kong container (src/wexample_wex_addon_services_platform/services/supabase/commands/service/ready.py); n8n curls localhost:5678/healthz; ollama curls localhost:11434/api/tags; gitlab calls gitlab-healthcheck.
Supabase also ships two database commands under commands/db/: src/wexample_wex_addon_services_platform/services/supabase/commands/db/migrate.py (applies pending migrations via supabase db push inside the supabase_cli helper container, hooked to run before app::maintenance/disable) and db/reset (drops schemas and replays migrations; tagged DANGEROUS).
GitLab Runner adds a commands/runner/ group with register, unregister, and list verbs that call docker exec … gitlab-runner inside the running container.
Domain tags
src/wexample_wex_addon_services_platform/const/tags.py defines DomainTag — a class of string constants (domain:ai, domain:ci, domain:db, domain:git, domain:platform, etc.) attached to every command via the @command(tags=[...]) decorator. Tags allow the kernel and external tools to filter commands by functional area without inspecting their names.
Call path
When the user runs wex @supabase::service/install:
- The kernel resolves
supabaseto the service registered under that name, andservice/installto the command file at src/wexample_wex_addon_services_platform/services/supabase/commands/service/install.py. - The framework constructs an
ExecutionContext(carrying the IO layer and the kernel) and resolves theservice: AppServiceparameter by looking up the app's activesupabaseservice object. - The command function runs: it reads app config, writes keys, generates secrets, fetches files, and rebuilds the runtime config.
- For
service/ready, the same resolution path leads to a function that runsdocker execand returns aBooleanResponse.
Container names are always {APP_PROJECT_NAME}_{service_name}, where APP_PROJECT_NAME is the value the Docker Compose environment variable ${APP_PROJECT_NAME} expands to at runtime. Commands that need to reach a container resolve this from service.app_workdir.get_runtime_config().search("app.project_name").get_str().
Integration in the Suite
This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
Related Packages
The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
Visit the Wexample Suite documentation for the complete package ecosystem.
Dependencies
- requests:
- wexample-wex-addon-app: >=32.4.0
- wexample-wex-core: >=31.1.0
Versioning & Compatibility Policy
Wexample packages follow Semantic Versioning (SemVer):
- MAJOR: Breaking changes
- MINOR: New features, backward compatible
- PATCH: Bug fixes, backward compatible
We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Free to use in both personal and commercial projects.
About us
Wexample stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.
This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.
Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.
Known Limitations & Roadmap
Current limitations and planned features are tracked in the GitHub issues.
See the project roadmap for upcoming features and improvements.
Status & Compatibility
Maturity: Production-ready
Python Support: >=3.10
OS Support: Linux, macOS, Windows
Status: Actively maintained
Useful Links
- Homepage: https://github.com/wexample/python-wex-addon-services-platform
- Documentation: docs.wexample.com
- Issue Tracker: https://github.com/wexample/python-wex-addon-services-platform/issues
- Discussions: https://github.com/wexample/python-wex-addon-services-platform/discussions
- PyPI: pypi.org/project/wexample-wex-addon-services-platform
Migration Notes
When upgrading between major versions, refer to the migration guides in the documentation.
Breaking changes are clearly documented with upgrade paths and examples.
Metadata
Release files for wexample-wex-addon-services-platform 12.10.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wexample_wex_addon_services_platform-12.10.6.tar.gz | 39.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| wexample_wex_addon_services_platform-12.10.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 126.1 kB
Release files / wexample_wex_addon_services_platform-12.10.6.tar.gz
| Download URL | wexample_wex_addon_services_platform-12.10.6.tar.gz |
|---|---|
| Size | 39.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6c9dd787655a3b88199c94013f635f7ec6a23eb07ca44c3f5f504c2e72146eb9
|
|
BLAKE2b-256 checksum How to use checksums |
94fdd0449c483c1b0e0f69ffc34ca470cf27708eeae92854aab96a4366c3d20d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
pdm/2.25.9 CPython/3.12.3 Linux/6.8.0-139-generic
|
Release files / wexample_wex_addon_services_platform-12.10.6-py3-none-any.whl
| Download URL | wexample_wex_addon_services_platform-12.10.6-py3-none-any.whl |
|---|---|
| Size | 86.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e0554b9bc36658bd5f2aa6bb60e4ec348eb07aea841aac72f51a0179e7da397f
|
|
BLAKE2b-256 checksum How to use checksums |
c8c8a91745b48178112d23a28920ccc7416f485dd294b7f66b1a8333f1312293
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
pdm/2.25.9 CPython/3.12.3 Linux/6.8.0-139-generic
|