fix(dev_env): make concern tags reach included tasks (O8)

Dynamic include_tasks only filter on the include's own tags, not their
(untagged) contents — so `--tags packages` ran none of the neovim/oh-my-posh/
nodejs installs, and `--tags users|config` never entered per_user.yml. Add
`apply: tags:` to all four includes (mirroring base/tasks/main.yml) and tag the
dev_env__home getent+set_fact preflight `always` so a partial run still resolves
the home dir before the dotfile/stow tasks consume it.

Molecule: add a config-only converge play for a fresh user + a verify assertion.
Proven with `molecule converge -- --tags config` (idempotent, home resolved).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
sjat 2026-06-14 19:06:15 +02:00
parent 64f1e821d8
commit 718781053f
4 changed files with 72 additions and 4 deletions

View file

@ -7,9 +7,38 @@
dev_env__users:
- tester
pre_tasks:
# `always` so the test user exists even under a partial `--tags` converge.
- name: Create a test user to receive the environment
ansible.builtin.user:
name: tester
create_home: true
tags: [always]
roles:
- role: dev_env
# Partial-tags regression guard (O8): apply only the `config` concern to a fresh user.
# The dev_env__home preflight is tagged `always`, so a config-only run must still resolve
# the home dir and stow the dotfiles. Run the true partial path with:
# molecule converge -- --tags config
# (a full `molecule test` runs every tag, which still exercises this play idempotently).
- name: Converge — config concern only, fresh user
hosts: all
become: true
gather_facts: true
vars:
dev_env__users:
- tagtester
pre_tasks:
# `always` so the test user exists even under a partial `--tags config` converge.
- name: Create a second test user for the config-only path
ansible.builtin.user:
name: tagtester
create_home: true
tags: [always]
tasks:
- name: Apply dev_env restricted to the config concern
ansible.builtin.include_role:
name: dev_env
apply:
tags: [config]
tags: [config]

View file

@ -71,3 +71,18 @@
- dev_env__dots.results[3].stat.exists
- dev_env__dots.results[4].stat.exists
fail_msg: dotfiles not stowed or omz/tpm not cloned
# Partial-tags regression guard (O8): the config-only converge play provisioned
# `tagtester`. Its stowed .zshrc proves dev_env__home resolved (the `always` preflight)
# and stow (a `config` task) ran without the `users`/`packages` concerns.
- name: Stat the config-only user's stowed .zshrc
ansible.builtin.stat:
path: /home/tagtester/.zshrc
register: dev_env__tagtester_zshrc
- name: Assert the config concern alone resolved home and stowed dotfiles
ansible.builtin.assert:
that:
- dev_env__tagtester_zshrc.stat.exists
- dev_env__tagtester_zshrc.stat.islnk
fail_msg: config-only run did not resolve dev_env__home / stow dotfiles for tagtester

View file

@ -7,21 +7,40 @@
cache_valid_time: 3600
tags: [packages]
# `apply: tags:` propagates the concern tag onto the INCLUDED tasks — without it a tag on
# a dynamic include_tasks only selects the include itself, not its (untagged) contents, so
# `--tags <concern>` would run nothing (Ansible gotcha; mirrors roles/base/tasks/main.yml).
- name: Install Neovim (pinned release)
ansible.builtin.include_tasks: neovim.yml
ansible.builtin.include_tasks:
file: neovim.yml
apply:
tags: [packages]
tags: [packages]
- name: Install oh-my-posh prompt (pinned release)
ansible.builtin.include_tasks: oh_my_posh.yml
ansible.builtin.include_tasks:
file: oh_my_posh.yml
apply:
tags: [packages]
tags: [packages]
- name: Install Node.js (pinned release)
ansible.builtin.include_tasks: nodejs.yml
ansible.builtin.include_tasks:
file: nodejs.yml
apply:
tags: [packages]
tags: [packages]
# per_user.yml resolves dev_env__home (tagged `always`, below) then runs both the `users`
# (login shell) and `config` (dotfiles/stow) concerns; tag + apply both so either
# `--tags users` or `--tags config` reaches in and the home-dir preflight always runs.
- name: Configure each developer user
ansible.builtin.include_tasks: per_user.yml
ansible.builtin.include_tasks:
file: per_user.yml
apply:
tags: [users, config]
loop: "{{ dev_env__users }}"
loop_control:
loop_var: dev_env__user
label: "{{ dev_env__user }}"
tags: [users, config]

View file

@ -1,12 +1,17 @@
---
# `always`: dev_env__home must resolve on every entry into per_user.yml, including a
# partial `--tags users` or `--tags config` run — the dotfile/stow (config) and login-shell
# (users) tasks below all depend on it, so it must never be filtered out (ADR-019).
- name: Look up account for {{ dev_env__user }}
ansible.builtin.getent:
database: passwd
key: "{{ dev_env__user }}"
tags: [always]
- name: Resolve home directory for {{ dev_env__user }}
ansible.builtin.set_fact:
dev_env__home: "{{ getent_passwd[dev_env__user][4] }}"
tags: [always]
- name: Set login shell to zsh for {{ dev_env__user }}
ansible.builtin.user: