Add a Molecule scenario for mautrix-whatsapp, and a shared playbook context

The second scenario, chosen to be a bridge rather than another HTTP
component: bridges are roughly 40 of the 70 roles here, and validating the
shape on role two is cheaper than discovering it on role forty. It found
two things the first role could not.

Bridges read a whole family of variables from outside themselves -
matrix_bridges_relay_enabled, _encryption_enabled, _encryption_default,
_msc4190_enabled, _self_sign_enabled, plus matrix_admin - all defined in
matrix-base. Since every bridge reads them, they belong in shared context
rather than in each bridge's scenario: molecule-shared/playbook-context.yml
now carries them along with the identity and path variables the first
scenario had inline. Note it is loaded through vars_files, which outranks
inventory group_vars, so it is authoritative; a scenario that wants to prove
one of these reaches the rendered configuration should say so explicitly.

Appservices call /whoami while starting and refuse to run if the id returned
is not the bot user they were configured as - mautrix-whatsapp exits 17 with
"Unexpected user ID in whoami call". The shared stub now takes the id it
should claim to be. Expect every bridge and bot to need this.

What the scenario proves: the bridge starts and stays up, opens its
appservice port, its rendered config and appservice registration carry the
scenario's tokens and bot user, it created its sqlite database under the
role's data path as the role's uid, and it runs the version the role pins.
It does not bridge anything and never will.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Slavi Pantaleev
2026-08-27 18:02:53 +03:00
co-authored by Claude Opus 5
parent 81a0ee3d53
commit f320bfc93b
12 changed files with 443 additions and 12 deletions
+56
View File
@@ -0,0 +1,56 @@
# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
#
# SPDX-License-Identifier: AGPL-3.0-or-later
---
# The variables a role here reads from its surroundings rather than from its own
# defaults. In a real run `matrix-base` and `group_vars/matrix_servers` provide
# them; in a scenario they have to come from somewhere, and including
# `matrix-base` itself does far more than a role scenario needs.
#
# Include from a scenario's prepare.yml, converge.yml and verify.yml:
#
# vars_files:
# - "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/playbook-context.yml"
#
# A scenario can override any of these in its own group_vars - that is the point
# of testing a role with values it would not have chosen for itself.
#
# Keep this to variables that come from OUTSIDE the role under test. Anything the
# role defines belongs in the scenario, not here.
# --- Identity and paths (matrix-base) --------------------------------------
matrix_base_data_path: /matrix
matrix_domain: molecule.local
matrix_user_name: matrix
matrix_group_name: matrix
# Deliberately not 1000: the base images already have a user there, so a distinct
# id is what proves a role used the one it was given rather than coinciding with
# the image's own.
matrix_user_uid: 1234
matrix_user_gid: 1234
# Empty in the playbook's own defaults too. Components that would invite an
# administrator into a room skip doing so when it is empty, which is what a
# scenario wants.
matrix_admin: ''
# --- Bridge-wide switches (matrix-base) ------------------------------------
#
# Every bridge role reads these, so they live here rather than in each bridge's
# scenario. The values match the playbook's own defaults: encryption off, no
# relay, no MSC4190. A bridge scenario that wants to prove one of these reaches
# the rendered configuration should override it in its own group_vars.
matrix_bridges_encryption_enabled: false
matrix_bridges_encryption_default: false
matrix_bridges_msc4190_enabled: false
matrix_bridges_self_sign_enabled: false
matrix_bridges_relay_enabled: false
matrix_bridges_exposure_enabled: true
matrix_bridges_exposure_hostname: molecule.local
matrix_bridges_exposure_path_prefix: /bridges
@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: 2026 Slavi Pantaleev
SPDX-License-Identifier: AGPL-3.0-or-later
@@ -50,6 +50,10 @@
- --network-alias={{ molecule_shared_stub_hostname | default('matrix.molecule.local') }}
- --env=STUB_SERVER_NAME={{ molecule_shared_stub_server_name | default('molecule.local') }}
- --env=STUB_JOINED_ROOMS={{ (molecule_shared_stub_joined_rooms | default([])) | join(',') }}
# Appservices call /whoami on startup and refuse to run if the id
# returned is not the bot user they were configured as, so a scenario
# bridging anything has to tell the stub who it should claim to be.
- --env=STUB_USER_ID={{ molecule_shared_stub_user_id | default('@stub:' + (molecule_shared_stub_server_name | default('molecule.local'))) }}
- --volume=/root/molecule-homeserver-stub.py:/stub.py:ro
- "{{ molecule_shared_image_python }}"
- python3