Labeling and selection are separate decisions
Adding tags to a task does not instruct Ansible to run only that task. Selection follows execution arguments and effective configuration. In a fictional incident, a team runs --tags deploy to shorten the window, but post-change checking has only the verify tag. The process can finish without error because it executed exactly the requested subset while leaving acceptance undone. Define each execution mode’s contract: required inputs, prerequisites, changes and final checks. Record arguments alongside playbook revision. The same commit with different --tags can represent a different operational change. Do not use tag names instead of describing effects or assume selecting deploy automatically includes every dependency.
Static inheritance and dynamic selection
With tags:deploy on import_tasks, imported tasks inherit the tag and become eligible for --tags deploy. The same tag on include_tasks applies to the include without automatically being copied to children. The lab shows the include running while the deployment file remains absent because its child lacked the requested tag. To apply the tag to children, use apply: tags:deploy on the include; to reach the include in that filtered run, select the include itself too. The trial includes an apply-only variant with no outer tag: the include is skipped and its child never loads. Treat these as separate decisions when reading configuration.
Always and never are not authorization controls
An always-tagged task can run despite normal tag selection, but --skip-tags always can exclude it. In the trial, a synthetic approval assertion blocks writing when approval is absent; the run excluding always proceeds to writing without evaluating that assertion. This demonstrates selection behavior, not an acceptable way to bypass real approval. Control who can choose arguments and perform the operation through appropriate access mechanisms and change processes. Conversely, never prevents default execution, but explicitly selecting never or another tag on the same task can cause it to run. The example tags:[never,maintenance] runs with --tags maintenance. Never does not mean execution is impossible.
Precedence and omitted work
When a task is both selected and excluded by tags, exclusion must be considered. The trial requests --tags never and --skip-tags maintenance for the task carrying both; the marker is not written. Inspect both arguments and relevant defaults, not just positive selection. Implicit validation or fact gathering can also use always; changing selection can remove data or checks needed by later work. An undefined-variable failure after partial execution can result from omitted preparation rather than a template defect. Diagnose by comparing the full run with the problematic selection, observing what actually executed and keeping inputs consistent.
Build an acceptance matrix
A useful matrix records every supported combination of tags, inputs and starting state, plus expected effects and mandatory checks. Include at least a full run, a legitimate operational selection, a combination expected to fail and one expected to leave state unchanged. In the lab, 19 Ansible invocations per run support 40 checks, including expected exit codes, present or absent files and deliberate errors. Two runs produced the same observable outcomes. A zero exit code alone does not prove deployment: selection can skip all useful work. For handover, document only rehearsed modes, local-simulation limits and checks still needed on the target. Tag selection should reduce authorized work without removing the evidence required to accept it.
# Select the include and apply the selection to its children:
- name: Include deployment tasks
ansible.builtin.include_tasks:
file: deploy.yml
apply:
tags: deploy
tags: deploy
# From the project root, with an isolated core 2.16.14 environment:
# python3 content/labs/rhce-reuse-selection/run.py \
# --ansible-bin /path/to/venv/bin/ansible-playbook \
# --output /tmp/rhce-reuse-evidence.json
# Synthetic local files; not a RHEL service or an authorization system.
The pipeline succeeds with --tags deploy, but the included task did not inherit the tag. Its expected artifact is absent and delivery cannot be accepted.
Common pitfalls
Tags as automatic dependencies; apply as include selection; always as impossible to skip; never as an absolute block; zero exit as proof of effect.
Related topics: Imports and includes · Change control and handover
Validate the subset actually executed and the requirements it left unmet.
Reference: Tags and inheritance · EX294 current objectives inspected 2026-09-30; RHCE in Ansible framework effective 2026-05-11; booking product version not publicly pinned