Two probes that describe a host were re-running per application. Measured in CI
run wp-swarm-tor2: 42 invocations of the pip probe and 44 of the NFS assert.
sys-pip-install guarded only its dependency include. Everything expensive sat
below that guard in main.yml, unguarded: resolving the interpreter, probing pip
for --break-system-packages, checking for `packaging` and bootstrapping it. All
four ran on every one of the 21 include sites. They move into 00_core.yml, where
the existing `when: run_once_sys_pip_install is not defined` covers them, and
main.yml keeps the guarded include and the pip task itself. The role recap reads
sys-pip-install ---- 87.35s.
The two facts this freezes per host are run constants: ansible_python_interpreter
is pinned once in group_vars/all/00_general.yml and no call site overrides it,
and all 21 sites pass global_install: true. main.yml now defends the probe fact
with `| default(false)` the way 00_core.yml already did, because the probe sits
behind `when: global_install | bool` and a first invocation with false would
otherwise leave it undefined for every later one.
The NFS assert emulated a per-host check with run_once plus delegate_to over
groups['svc-swarm-node'], and the include it lives in happens per application.
It becomes a plain per-host task in sys-svc-compose/00_core.yml, which main.yml
already gates once per host per play: 44 instances and 132 remote commands
become 4 and 4. Dropping run_once also removes a real fragility — at log line
35355 only wrk-01 and wrk-02 reach the include because mgr-01's flag is already
set, so run_once there designates a host that skipped.
It reaches the same hosts as the loop it replaces, measured rather than assumed:
sys-svc-compose/00_core fires only on mgr-01, wrk-01 and wrk-02, the backup play
never runs it, and nfs-server and bkp-01 never execute it. The two conditions
that do not travel are a per-application volume count, meaningless for a
per-host check, and an exemption for manager-placed roles — mgr-01 answered the
assert ok 14 times out of 14, so the exemption was hiding nothing.
The assert is appended to 00_core.yml rather than prepended: utils/once/flag.yml
must stay that file's first task for test_service_core_first_task_run_once.
Worth 128.6s: 84.6s from the pip probe and 44.0s from the assert.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The packaging bootstrap and the main install/upgrade both download from
PyPI and fail hard on a connection reset. Wrap each in the standard
retry-until-succeeded loop (5 tries, 15s apart), matching the apt/dnf/
pacman/docker egress hardening already in place.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add tests/lint/repository/test_task_file_numbering.py: numbered task
files use exactly two leading digits, a numbered *_core.yml must be
00_core.yml, per directory the numbers are unique/consecutive and start
at 01 (00 with a core file), numbered includes appear in ascending
order, and shared helpers live in tasks/utils/ instead of the numbered
chain.
Apply it across every role: rename NN_core.yml to 00_core.yml with a
consecutive down-shift of the siblings, move letter-suffix children into
a subdirectory named after their parent task, relocate helpers included
from more than one place into tasks/utils/, and update every reference
(include_tasks, path_absolute, .ansible-lint-ignore, requirement docs).
Legacy narration comments in the touched files are deleted; the upstream
xwiki.properties reference block opts out via nocheck. The unused
MAILU_IP6_PUBLIC var (only ever named in now-removed comments) is dropped.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add tests/lint/repository/test_name_emoji_and_length.py: every Ansible task
name and GitHub Actions workflow/job/step name must start with an emoji (first
char not 0-9/A-Za-z) and be <= 80 chars.
- emit emoji names at the source: cli/build/include generator now writes
"🔧 setup <app>" / "🚿 flush handlers after <app>" so generated
tasks/groups/*-roles.yml satisfy the convention too
- convert existing task/step/job/workflow names to emoji-prefixed, choosing a
task-fitting icon per action (📦 install, ✅ ensure, 🔍 probe, 🥾 bootstrap,
🚀 deploy, 🧩 service-module load, ⬇️ checkout, 📂 include-routines, ...)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* scripts/lint/autoformat.sh: rename AUTOFORMAT_PARALLEL to PARALLEL,
declare it at file start with default `true`; still env-overridable.
Reword the worker comment so the literal `# shellcheck` token no
longer appears at start-of-line and trips SC1072/SC1073.
* scripts/lint/galaxy.sh: drop the GALAXY_FATAL / GALAXY_NAMESPACE /
GALAXY_PARALLEL env vars (over-engineered for a single repo). Failure
is always fatal. NAMESPACE is an internal constant. Add the same
PARALLEL env var (default `true`, env-overridable); falsy demotes the
xargs fan-out to one worker.
* docs/contributing/environment/variables.md: collapse the four
AUTOFORMAT_*/GALAXY_* rows into one `PARALLEL` row covering both
consumers.
* docs/contributing/tools/make.md: refer to `PARALLEL=0` everywhere;
add the lint-galaxy parallelism note.
Plus working-tree drift across roles/, group_vars/, inventories/, and
tasks/ that accumulated from the make-test setup phase regenerating
generated artefacts during recent test runs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Use 'python -I' (isolated mode) to check for 'packaging' library.
- This ensures the check fails if the library is missing in the strict environment used by Ansible modules, even if present in user site-packages.
- Fixes pip module failures on CentOS.
- add cross-distro dev-python installer script and wire it into role + Dockerfile
- regenerate dockerignore from gitignore on make build and ignore logs/
- harden sys-pip-install break-system-packages support probe
- raise project requires-python to >=3.11
Use ansible_python_interpreter-derived virtualenv for pip installs by default and
only use system pip3 with --break-system-packages when global_install=true. This
ensures Ansible module dependencies (e.g. python-ldap) are available in the
runtime interpreter.
https://chatgpt.com/share/6964335a-29cc-800f-ae65-6a35c7cd2559
- Add global_install flag to sys-pip-install role (default: false)
- Allow optional system-wide installs via pip3 with --break-system-packages
- Install python-ldap via pip in Ansible interpreter for OpenLDAP role
- Refactor svc-db-openldap tasks into 01_core.yml with run-once gating
- Fix environment handling for conditional global pip installs
- Enable global pip installs for CLI tools (gitcon, ldapsm, backup tools, cleanup tools)
https://chatgpt.com/share/6963dd5d-cae0-800f-b8d7-82a3808be634
Use system-wide pip3 for package installation to avoid installing CLI tools
into the Ansible virtualenv. This ensures binaries (e.g. dockreap) are placed
in a global PATH and are usable by systemd services.
https://chatgpt.com/share/69628897-4d98-800f-b4cf-b9a8f5fdaa6b
- replace pkgmgr-install with sys-pip-install for cleanback
- install cleanback as a regular pip package
- align roles with pyproject-based distribution
- keep system-wide, non-interactive installation semantics
https://chatgpt.com/share/69517d20-f850-800f-b6ff-6b983247888f
- Force sys-pip-install to use system python (/usr/bin/python3) instead of active venv
- Add explicit PATH for system-wide pip installs
- Add diagnostics task to verify installation context with system python
- Replace systemctl is-active check with Result/ExecMainStatus to correctly handle oneshot units
- Prevent false failures when oneshot services exit successfully
https://chatgpt.com/share/695123ba-8da4-800f-ae0d-2f09a5efb1e7