Reword the Molecule scenario comments

They were hard-wrapped at 80 characters, broke mid-parenthesis, and spent lines
restating what the code below them does.

Rewrapped at natural boundaries instead, with the narration dropped and only the
reasons, gotchas and surprises kept. Section dividers stay - they delineate long
plays rather than narrate them.

Comments only; no scenario behaviour changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEH3vxYSQ5SV4N5z61eyGT
This commit is contained in:
Slavi Pantaleev
2026-08-27 18:02:53 +03:00
co-authored by Claude Opus 5
parent e2d3be504e
commit c447e1528b
32 changed files with 458 additions and 641 deletions
@@ -3,11 +3,9 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
---
# The devture base roles carry the variables this role reads
# (`devture_systemd_docker_base_*`, `devture_playbook_help_*`), the same way
# they do when the playbook runs. `matrix-base` is deliberately NOT included:
# it does far more than this role needs, and the variables it would supply come
# from molecule-shared/playbook-context.yml instead.
# The devture base roles carry the variables this role reads, the same way they do when
# the playbook runs. `matrix-base` is deliberately NOT included: it does far more than this
# role needs, and what it would supply comes from molecule-shared/playbook-context.yml.
- name: Include roles for matrix-reminder-bot Molecule tests
hosts: all
become: true
@@ -26,8 +24,8 @@
loop_control:
loop_var: role_name
# The role installs the unit but does not start it - in the playbook that is
# `systemd_service_manager`'s job - so the scenario starts it here.
# The role installs the unit but does not start it; in the playbook that is
# `systemd_service_manager`'s job.
- name: Ensure matrix-reminder-bot is started
hosts: all
become: true
@@ -29,28 +29,25 @@ provisioner:
all:
matrix_bot_matrix_reminder_bot_container_network: matrix-reminder-bot-molecule
# Unlike the bridges, this bot is not an appservice: it logs into the
# homeserver as an ordinary user with a password. The stub prepare.yml
# stands up answers /_matrix/client/v3/login with an access token, which
# is all the bot needs to get past its login and into its sync loop.
# Unlike the bridges, this bot is not an appservice: it logs in as an ordinary user
# with a password. The stub answers /_matrix/client/v3/login with an access token,
# which is all the bot needs to reach its sync loop.
matrix_bot_matrix_reminder_bot_matrix_homeserver_url: http://matrix.molecule.local:8008
# Deliberately different from the role's default localpart
# (`bot.matrix-reminder-bot`), so verify.yml can tell what the role
# Different from the role's default localpart, so verify.yml can tell what the role
# rendered apart from what it would have rendered anyway.
matrix_bot_matrix_reminder_bot_matrix_user_id_localpart: molecule.reminder-bot
matrix_bot_matrix_reminder_bot_matrix_user_password: molecule_bot_password_4f2a91
# The role has no default here and refuses to run without one. Also
# different from the bot's own fallback (`Etc/UTC`), and it reaches the
# container twice - through the config file and through TZ on the unit.
# The role has no default here and refuses to run without one. Also different from the
# bot's own fallback, and it reaches the container twice: the config file and TZ.
matrix_bot_matrix_reminder_bot_reminders_timezone: Europe/Sofia
# The role and the bot both default to `!`.
matrix_bot_matrix_reminder_bot_command_prefix: "%%"
# Both lists default to off with no entries, so turning them on with
# entries of our own exercises the `_auto + _custom` composition.
# Both lists default to off with no entries, so turning them on exercises the
# `_auto + _custom` composition.
matrix_bot_matrix_reminder_bot_allowlist_enabled: true
matrix_bot_matrix_reminder_bot_allowlist_regexes_custom:
- "@molecule-allowed:molecule.local"
@@ -58,22 +55,19 @@ provisioner:
matrix_bot_matrix_reminder_bot_blocklist_regexes_custom:
- ".*:blocked.molecule.local"
# The device name is hardcoded in the role's config template, so
# overriding it is only possible through the extension mechanism. Doing
# it here means the merge of template + extension is tested too.
# The device name is hardcoded in the role's template, so overriding it is only
# possible through the extension mechanism - which tests that merge too.
matrix_bot_matrix_reminder_bot_configuration_extension_yaml: |
matrix:
device_name: Molecule Reminder Bot
# The SQLite database path is moved off the role's default (`bot.db`) so
# that verify.yml can assert the bot opened the path the role gave it,
# with the default name as a negative control.
# Moved off the role's default name so verify.yml can assert the bot opened the path
# the role gave it, with the default name as a negative control.
matrix_bot_matrix_reminder_bot_sqlite_database_path_local: /matrix/matrix-reminder-bot/data/molecule-reminders.db
matrix_bot_matrix_reminder_bot_sqlite_database_path_in_container: /data/molecule-reminders.db
# verify.yml runs as its own play, where the role's defaults are out of
# scope, so the paths it reads are pinned here as literals. They match
# what the role derives from `matrix_base_data_path`.
# verify.yml runs as its own play, where the role's defaults are out of scope,
# so the paths it reads are pinned here to match what the role derives.
matrix_bot_matrix_reminder_bot_base_path: /matrix/matrix-reminder-bot
matrix_bot_matrix_reminder_bot_config_path: /matrix/matrix-reminder-bot/config
matrix_bot_matrix_reminder_bot_data_path: /matrix/matrix-reminder-bot/data
@@ -31,9 +31,8 @@
docker_daemon_options:
storage-driver: fuse-overlayfs
# The role's file tasks set owner/group by name, and Ansible resolves those
# through the passwd database - so they have to exist before it runs. In a
# real deployment `matrix-base` creates them.
# The role's file tasks set owner/group by name, which Ansible resolves through the
# passwd database, so they have to exist first. `matrix-base` creates them for real.
- name: Ensure the matrix group exists
ansible.builtin.group:
name: "{{ matrix_group_name }}"
@@ -57,8 +56,8 @@
group: "{{ matrix_group_name }}"
mode: "0750"
# The role creates this network itself during converge, but the homeserver
# stub has to be on it before the bot starts, so it is created here first.
# The role creates this network itself during converge, but the stub has to be on it
# before the bot starts.
- name: Ensure the container network the role attaches to exists
ansible.builtin.command:
argv:
@@ -72,11 +71,9 @@
- matrix_bot_matrix_reminder_bot_molecule_network.rc != 0
- "'already exists' not in matrix_bot_matrix_reminder_bot_molecule_network.stderr"
# This bot is not an appservice - it logs in with the username and password
# the role rendered into its configuration, and retries every 15 seconds
# until that succeeds. The shared stub answers the login with an access
# token, which is enough to get it into its sync loop. Nothing is asserted
# about the stub itself; see molecule-shared/homeserver-stub.py.
# Not an appservice: it logs in with the username and password the role rendered, retrying
# every 15 seconds until that succeeds. The stub answers with an access token, which is
# enough to reach the sync loop. Nothing is asserted about the stub itself.
- name: Ensure the homeserver stub is running
ansible.builtin.include_tasks:
file: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/tasks/homeserver-stub.yml"
@@ -3,13 +3,12 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
---
# What this proves: matrix-reminder-bot starts on the configuration the role
# rendered, logs into a homeserver as the user the role gave it, opens the
# database at the path the role gave it, and is the version the role pins.
# Proves matrix-reminder-bot starts on the configuration the role rendered, logs in as the
# user the role gave it, opens the database at the path the role gave it, and is the version
# the role pins.
#
# The bot has no HTTP surface of its own to probe, so the evidence is what it
# says about itself in the journal plus what it left on disk. It does NOT set
# real reminders and never will. See docs/molecule-testing.md.
# The bot has no HTTP surface to probe, so the evidence is what it says about itself in the
# journal plus what it left on disk. It does NOT set real reminders. See docs/molecule-testing.md.
- name: Verify matrix-reminder-bot
hosts: all
become: true
@@ -23,10 +22,9 @@
matrix_bot_matrix_reminder_bot_molecule_container_user: "{{ matrix_user_uid }}:{{ matrix_user_gid }}"
tasks:
# The version is read out of the role's own defaults rather than pinned in
# molecule.yml, so that the assertion further down compares the running
# image against what defaults/main.yml actually ships. Pinning it here
# would make that assertion compare the scenario with itself.
# Read from the role's own defaults rather than pinned in molecule.yml, so the version
# assertion compares the running image against what defaults/main.yml ships.
# Pinning it here would make that assertion compare the scenario with itself.
- name: Load the role's defaults under a separate name
ansible.builtin.include_vars:
file: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/defaults/main.yml"
@@ -41,12 +39,10 @@
delay: 5
failed_when: false
# `Restart=always` means a bot crash-looping on a configuration it cannot
# read still reports `active`, so the restart counter is checked too. The
# config file is parsed before the bot's own catch-all retry loop starts, so
# anything wrong in what the role rendered shows up here as restarts.
# Asserted as `is defined` too, because `| int` turns a missing property
# into 0 and would pass vacuously on a systemd that does not expose it.
# `Restart=always` means a bot crash-looping on unreadable config still reports `active`,
# so the restart counter is checked too. The config file is parsed before the bot's own
# catch-all retry loop starts, so anything wrong in what the role rendered shows up here
# as restarts. Asserted `is defined` because `| int` turns a missing property into 0.
- name: Assert the service is active and has not been restarting
ansible.builtin.assert:
that:
@@ -60,14 +56,12 @@
automatic restart(s)
success_msg: "matrix-bot-matrix-reminder-bot.service is active and has not restarted"
# The unit runs `docker start --attach`, so the container's output is in the
# journal despite `--log-driver=none`. That is the only thing this bot
# reports about itself - it serves nothing over HTTP.
# The unit runs `docker start --attach`, so the container's output is in the journal
# despite `--log-driver=none`. It is the only thing this bot reports about itself.
#
# Filtered rather than tailed: the startup lines are the oldest ones in the
# journal, so a `--lines=N` tail would lose them behind anything the bot
# logs later, and reading the journal whole would pull an unbounded amount
# of text into a variable. The filter keeps the failure line too, so the
# Filtered rather than tailed: startup lines are the OLDEST in the journal, so a
# `--lines=N` tail loses them behind anything logged later, and reading it whole pulls
# unbounded text into a variable. The filter keeps the failure line too, so the
# "did not fail to log in" assertion below still has something to see.
- name: Wait for the bot to report that it finished starting up
ansible.builtin.shell:
@@ -83,10 +77,9 @@
delay: 5
failed_when: false
# "Logged in as ..." is only reached after the bot's login call came back as
# something other than a LoginError, so this is the whole chain at once: the
# homeserver URL, the user ID and the password the role rendered were good
# enough for a real login round-trip against the stub.
# "Logged in as ..." is only reached once the login call returned something other than a
# LoginError, so this covers the whole chain at once: homeserver URL, user ID and password
# were all good enough for a real login round-trip.
- name: Assert the bot logged in as the user the role configured
ansible.builtin.assert:
that:
@@ -99,9 +92,8 @@
success_msg: >-
The bot logged in as {{ matrix_bot_matrix_reminder_bot_molecule_user_id }} and finished starting up
# The role picks the storage engine (SQLite here, Postgres otherwise) by
# building the connection string the bot parses, and the bot names the type
# it settled on once the database is open.
# The role picks the storage engine by building the connection string the bot parses,
# and the bot names the type it settled on once the database is open.
- name: Assert the bot opened the database engine the role selected
ansible.builtin.assert:
that:
@@ -114,9 +106,8 @@
src: "{{ matrix_bot_matrix_reminder_bot_config_path }}/config.yaml"
register: matrix_bot_matrix_reminder_bot_config_file
# Every one of these differs from both the role's defaults and the bot's own
# fallbacks, so their presence means the role rendered this file rather than
# the values coinciding with what would have happened anyway.
# Every one differs from both the role's defaults and the bot's own fallbacks, so their
# presence means the role rendered this file rather than coinciding with it.
- name: Assert the rendered configuration carries this scenario's values
ansible.builtin.assert:
that:
@@ -133,9 +124,8 @@
vars:
matrix_bot_matrix_reminder_bot_config_rendered: "{{ matrix_bot_matrix_reminder_bot_config_file.content | b64decode }}"
# `device_name` is hardcoded in the role's config template, so this value can
# only be there if `..._configuration_extension_yaml` was merged over the
# template rather than ignored.
# `device_name` is hardcoded in the role's template, so this value can only be here if
# `..._configuration_extension_yaml` was merged over it rather than ignored.
- name: Assert the configuration extension was merged over the template
ansible.builtin.assert:
that:
@@ -148,9 +138,8 @@
vars:
matrix_bot_matrix_reminder_bot_config_rendered: "{{ matrix_bot_matrix_reminder_bot_config_file.content | b64decode }}"
# The bot has no HTTP surface, so where its database landed is the evidence
# that the storage configuration reached the running process rather than
# merely the file on disk.
# With no HTTP surface, where the database landed is the evidence that the storage
# configuration reached the running process and not merely the file on disk.
- name: Stat the database at the path the scenario configured
ansible.builtin.stat:
path: "{{ matrix_bot_matrix_reminder_bot_sqlite_database_path_local }}"
@@ -168,9 +157,8 @@
success_msg: >-
The database is at the configured path, owned by {{ matrix_user_uid }}:{{ matrix_user_gid }}
# A negative control for the assertion above: the role's own default
# database name must NOT appear, or a file at the configured path would not
# prove the configuration reached the process.
# Negative control for the assertion above: the role's own default database name must NOT
# appear, or a file at the configured path would prove nothing.
- name: Stat the database name the role would have used by default
ansible.builtin.stat:
path: "{{ matrix_bot_matrix_reminder_bot_data_path }}/bot.db"
@@ -186,9 +174,8 @@
configuration reached the bot
success_msg: "Only the configured database path was used"
# matrix-nio writes its encryption store here once a login has succeeded, so
# a populated directory means the bot could use the store path the role
# created for it inside an otherwise read-only container.
# matrix-nio writes its encryption store here once login succeeds, so a populated directory
# means the bot could use the store path the role created inside a read-only container.
- name: List the encryption store the role created
ansible.builtin.find:
paths: "{{ matrix_bot_matrix_reminder_bot_data_store_path }}"
@@ -216,9 +203,8 @@
register: matrix_bot_matrix_reminder_bot_container
changed_when: false
# The timezone reaches the container twice - through the config file checked
# above and through TZ on the unit - and the uid/gid come from the playbook
# context rather than from anything the image would pick on its own.
# The timezone reaches the container twice, through the config file checked above and
# through TZ on the unit. The uid/gid come from the playbook context, not from the image.
- name: Assert the container runs as the role's user with the configured timezone
ansible.builtin.assert:
that: