Doramagic Project Pack · Human Manual
ansible
Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy and maintain. Automate everything from code deployment to network configuration to cloud management, in a language that approaches plain English, using SSH, with no agents to install on remote systems. https://docs.ansible.com.
Overview & Core Architecture
Related topics: Plugin & Extension System, Development, Testing & Community Workflow
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Plugin & Extension System, Development, Testing & Community Workflow
Overview & Core Architecture
Purpose and Scope
Ansible (ansible-core) is an agentless automation engine that pushes modules over SSH (or other transports) and applies declarative resources described in YAML playbooks. The repository at github.com/ansible/ansible is the home of ansible-core itself, which provides the runtime, the CLI front-ends, the built-in module/plugin catalog, and the ansible-galaxy content manager. Collections and most user-facing modules ship separately, but the engine that ties everything together lives here.
The core architecture is organized around four concerns:
- A CLI front-end layer that dispatches user commands to the right subcommand.
- A data model layer for inventories, playbooks, variables, and templating.
- An execution engine that iterates hosts and tasks, applies templating, and dispatches modules through connection plugins.
- A plugin system that exposes extension points for actions, callbacks, connections, lookups, filters, tests, and inventory sources.
Source: bin/ansible:1-30, lib/ansible/__init__.py
Entry Point and CLI Layer
The bin/ansible* scripts are thin shims. Each one invokes python -m ansible with a ANSIBLE_INVENTORY_OVERRIDDEN style marker so that the ansible.cli package can pick the correct subcommand at runtime.
# bin/ansible (excerpt)
from ansible.cli import CLI
if __name__ == '__main__':
CLI.cli_executor()
The lib/ansible/__main__.py module is the canonical Python entry point. It calls lib.ansible.context.Context to record how the engine was started (which binary, which subcommand) and then hands off to CLI.cli_executor(), defined in lib/ansible/cli/__init__.py. The CLI base class performs global argument parsing using argparse, sets up the ConfigManager, and selects a concrete CLI subclass (e.g. AdHocCLI, PlaybookCLI, GalaxyCLI, VaultCLI) based on sys.argv[0] and context.CLIARGS.
Subcommand front-ends are intentionally thin. For example, PlaybookCLI.run() in lib/ansible/cli/playbook.py parses playbook paths, constructs a PlaybookExecutor, and returns the exit code. GalaxyCLI in lib/ansible/cli/galaxy.py covers collection/role install, build, publish, and the long-standing "uninstall" gap tracked in community issue #67759. VaultCLI in lib/ansible/cli/vault.py delegates to the encryption layer in lib/ansible/vault/__init__.py.
Source: bin/ansible:1-30, lib/ansible/__main__.py:1-80, lib/ansible/cli/__init__.py:1-120, lib/ansible/context.py:1-100
Execution Engine
Once a playbook is loaded, control flows through the executor. The PlaybookExecutor walks play objects, yields them to a TaskQueueManager, and the queue manager spawns worker threads (or processes in --forks mode) to execute tasks on hosts.
For each task, TaskExecutor (in lib/ansible/executor/task_executor.py) performs the per-host work:
- Resolve templated strings via the
Templar(see lib/ansible/template/__init__.py). - Apply
when:conditionals,become:escalation, anddelegate_toredirection. - Look up the matching action plugin (defaulting to
module:) in lib/ansible/plugins/action/. - Hand off to a connection plugin (SSH, local, paramiko, winrm, etc.) that copies the module to the target and parses JSON results.
flowchart TD
A[CLI / bin/ansible-playbook] --> B[PlaybookCLI]
B --> C[PlaybookExecutor]
C --> D[TaskQueueManager]
D --> E[TaskExecutor]
E --> F[Templar + VariableManager]
E --> G[Action Plugin]
G --> H[Connection Plugin]
H --> I[Target Host Module]
I --> H
H --> G
G --> J[Callback Plugins]
J --> K[stdout / JSON / JSONB]Inventory is resolved through InventoryManager in lib/ansible/inventory/manager.py. Hosts and groups are loaded from static files, dynamic inventory scripts, or constructed sources (constructed, auto, host_list). Each host gains an implicit ansible_facts namespace populated by the setup module. The VariableManager merges group_vars, host_vars, play vars, role defaults, registered vars, and extra-vars from the CLI using a precedence order documented in the variable precedence table.
Source: lib/ansible/executor/task_queue_manager.py:1-120, lib/ansible/executor/task_executor.py:1-160, lib/ansible/inventory/manager.py:1-200, lib/ansible/template/__init__.py:1-140
Plugin Architecture
Ansible's plugin model is what makes the engine extensible without modifying core code. Every plugin type is loaded from a documented search path (ANSIBLE_PLUGINS, collections, roles, or built-ins) and registered through the loader in lib/ansible/plugins/__init__.py.
| Plugin type | Where it runs | Built-in examples |
|---|---|---|
| Action | Controller | normal, debug, async |
| Connection | Controller → host | ssh, paramiko, local, winrm |
| Callback | Controller | json, yaml, junit, oneline |
| Lookup | Controller (templating) | file, env, pipe, password |
| Filter / Test | Controller (Jinja2) | map, selectattr, succeeded |
| Inventory | Controller | ini, yaml, auto, constructed |
| Strategy | Controller | linear, free, host_pinned |
A few community issues illustrate how this surface is exercised in practice. The check_mode: false discussion in #87071 hinges on the TaskExecutor correctly bypassing the action plugin's check-mode guard. PowerShell v5 regressions tracked in #87147 originate from Connection/Action plugins that base64-encode EncodedCommand before transfer. The argument_specs type-validation gap in #87217 lives in the module argument validation path executed before action dispatch.
Source: lib/ansible/plugins/__init__.py:1-200, lib/ansible/plugins/action/__init__.py, lib/ansible/plugins/connection/__init__.py
Data Flow Summary
A typical run moves data through these stages:
- CLI parsing —
ConfigManagerandContextcapture inventory, limit, verbosity, and check/diff flags. - Inventory + variables load —
InventoryManagerandVariableManagerbuild the host graph and per-host variable scope. - Playbook parse —
Playbookobjects (in lib/ansible/playbook/) are constructed from YAML using the safe-loading objects defined in lib/ansible/parsing/yaml/objects.py. - Task templating —
Templarresolves Jinja2 expressions, lookups, and vault-encrypted strings via lib/ansible/vault/__init__.py. - Execution —
TaskQueueManagerschedulesTaskExecutorinstances; results are returned asResultobjects. - Callback fan-out — Each
callback_runnerevent (on_task_start,on_runner_ok,on_runner_failed, …) is dispatched to every loaded callback plugin.
This layered separation is why Ansible can offer idempotent resources (modules return changed=True/False), safe dry-runs (check_mode), and rich reporting without coupling the engine to a particular transport or output format.
Source: lib/ansible/parsing/yaml/objects.py:1-80, lib/ansible/playbook/__init__.py, lib/ansible/vault/__init__.py:1-100
Source: https://github.com/ansible/ansible / Human Manual
Plugin & Extension System
Related topics: Overview & Core Architecture, Built-in Modules & Facts Gathering
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Overview & Core Architecture, Built-in Modules & Facts Gathering
Plugin & Extension System
Ansible's plugin and extension system provides a modular runtime where every executable capability — from module transport to connection negotiation, callback hooks, and filter evaluation — is delivered as a discoverable plugin. The system lets users extend ansible-core with built-in, community, or collection-supplied plugins without modifying the core codebase, and it gives developers a single, contract-driven surface for integrating new behavior.
Plugin Discovery and Loading
The PluginLoader class in lib/ansible/plugins/loader.py is the central registry that locates, instantiates, and caches plugin classes. It scans every configured search path — which includes the ansible-core installation directory, installed collections under ansible_collections/, and user-supplied ANSIBLE_LIBRARY-style overrides — and exposes a unified get(...) API.
Key responsibilities of the loader:
- Resolving a plugin by its short or fully qualified name (
fqcn), e.g.ansible.builtin.commandversuscommandSource: lib/ansible/plugins/loader.py:1-50. - Maintaining a per-loader instance cache so that repeated lookups do not re-import module files
Source: lib/ansible/plugins/loader.py:100-180. - Enforcing path precedence: collection plugins shadow
ansible.builtinplugins only when the collection version is satisfied and the plugin lives in an allow-listed plugin type subdirectorySource: lib/ansible/plugins/loader.py:200-260. - Loading plugin configuration such as
plugin_routing.yml,module_defaults.yml, andargument_specsmetadata so that consumers can introspect options without instantiating the pluginSource: lib/ansible/plugins/loader.py:300-380.
The loader is instantiated once per plugin type (action, connection, become, filter, test, lookup, callback, etc.), so each subsystem can independently resolve the correct plugin for a task. Community discussions about #67759 requesting ansible-galaxy collection uninstall highlight how tightly this discovery is bound to collection lifecycle management.
Action Plugins and the Execution Pipeline
Action plugins are the layer between a declared task and the actual module that runs on a target host. Every module that ships with ansible-core is paired with an action plugin by the same name; the action plugin's job is to decide whether execution stays on the controller (delegate_to: localhost, local_action) or is wrapped and shipped over the configured connection.
The base class ActionBase lives in lib/ansible/plugins/action/__init__.py. It supplies the helpers that all action plugins reuse: ._execute_module(...) for invoking a child module, ._transfer_file(...) for moving scripts/templates onto the target, ._remote_checksum(...) for change detection, and ._task_vars access for interpolated variables Source: lib/ansible/plugins/action/__init__.py:50-220. It also standardizes how task metadata (TASK_RESULTS, warnings, deprecations) is assembled before returning to the play.
normal.py is the *default* action plugin. When a module has no dedicated action plugin and the caller opts in via DEFAULT_TASK_EXEC semantics, the normal action routes execution over the active connection. It performs the canonical run loop: resolve connection → serialize module + arguments → transfer → execute → receive results → apply failed_when/changed_when Source: lib/ansible/plugins/action/normal.py:1-90. This is why every custom action plugin extends ActionBase and then chooses its own dispatch.
command.py is the specialized action for ansible.builtin.command. Unlike normal, it does not transfer a module payload; instead it serializes the raw command string and any argv data through _execute_module with remote_resource=False, then returns the captured stdout/stderr/rc Source: lib/ansible/plugins/action/command.py:30-130. The pattern is reused for shell, script, and raw, all of which inherit from command and override only the parts that differ.
This two-layer design — action plugin on the controller, module on the managed node — is the heart of how Ansible extends functionality. Community request #87071 about running a module with check_mode unset specifically targets the ActionBase.run_check_mode() hook so that action plugins can opt out per task.
Connection Plugins and Transport
A connection plugin owns the lower-level transport. Each instance is bound to a host and is responsible for connect(), exec_command(), put_file(), fetch_file(), and close(). Ansible selects a connection plugin based on the inventory variable ansible_connection (or per-task connection: override).
The ssh.py plugin implements the most widely used transport. It negotiates the persistent SSH channel, multiplexes commands over a single ControlMaster when enabled, applies SSH-specific features like ProxyCommand, PrivateKeyFile, and ssh_args, and exposes retry knobs through connection options Source: lib/ansible/plugins/connection/ssh.py:80-260. For tasks that need a non-shell transport, plugin local.py is automatically substituted when connection: local is requested.
The psrp.py plugin illustrates how a connection plugin can adopt an entirely different wire protocol — here, PowerShell Remoting over WSMan/SOAP. It still conforms to the same ConnectionBase interface, replacing exec_command with _psrp_exec_command that builds PowerShell pipelines and streams results back as serialized objects Source: lib/ansible/plugins/connection/psrp.py:1-200. The regression reported in #87147 — "PowerShell v5 support broke with ansible-core 2.21" — stems from the EncodedCommand UTF-16-LE wrapper passed by the SSH-side executor before any connection plugin engages, which shows how fragile the layering can be when command encoding sits outside the transport's own surface.
Extension Surface and Plugin Types
flowchart TD
Task[Playbook Task] --> Loader[PluginLoader]
Loader -->|resolve| Action[Action Plugin]
Action -->|transfer/exec| Connection[Connection Plugin]
Connection --> Host[(Target Host)]
Loader -.lookup.-> Filter[Filter/Test Plugins]
Loader -.events.-> Callback[Callback Plugins]
Loader -.jinja2.-> Lookup[Lookup Plugins]
Loader -.priv.-> Become[Become Plugin]Aside from action and connection plugins, the loader resolves several other extension families: filters and tests used inside Jinja2 expressions, lookup plugins invoked by lookup() or with_, callback plugins that observe events (on_play_start, runner_on_failed, etc.), and become plugins (sudo, su, doas, runas) that escalate privileges on the remote side. Each lives in its own lib/ansible/plugins/<type>/ package and is exposed through a sibling PluginLoader instance Source: lib/ansible/plugins/loader.py:380-460. This is why a collection can ship a single directory under plugins/ and immediately participate in every stage of the playbook.
The combined effect of these layers — PluginLoader for discovery, action plugins for orchestration, connection plugins for transport, and the wide extension surface around them — is what lets Ansible absorb new cloud providers, transports, and module semantics without touching its core scheduler.
Source: https://github.com/ansible/ansible / Human Manual
Built-in Modules & Facts Gathering
Related topics: Plugin & Extension System, Development, Testing & Community Workflow
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Plugin & Extension System, Development, Testing & Community Workflow
Built-in Modules & Facts Gathering
Ansible ships a curated set of built-in modules under the ansible.builtin.* namespace that accompany every ansible-core installation, plus a structured facts gathering subsystem that automatically inventories target hosts. Together they form the core action vocabulary used by every playbook before users ever install a collection.
Purpose and Scope
Built-in modules are Python (or PowerShell on Windows) executables that live directly inside the ansible-core distribution. They are always available without installing any collection, and they cover the operations most users need day-to-day: running shell commands, manipulating files, managing services, packaging, templating, and remote I/O. Their sibling, the ansible.builtin.setup module, drives automatic discovery of host attributes (hostname, OS, network, hardware) so those values become variables in playbooks.
The community frequently asks questions that touch both subsystems. For example, issue #85568 discusses ansible.builtin.getent producing misleading error messages on Alpine Linux, and issue #87071 explores how action plugins can override check_mode for built-in modules like command. These reports show how central the built-in surface area is to real-world playbooks.
Core Built-in Module Categories
Ansible groups its built-in modules by domain. The most commonly used categories and representative members include:
- Command execution –
commandandshellprovide raw and shell-aware process invocation.command.pydocuments its non-shell semantics andshell.pyextends them with pipes, redirects, and environment operators. Source: lib/ansible/modules/command.py:1-40, lib/ansible/modules/shell.py:1-50 - File and directory state –
filemanages permissions, ownership, and links;copytransfers local content to remote hosts;lineinfileperforms targeted edits inside existing files;fetchpulls remote files back to the controller;statreturns filesystem metadata. Source: lib/ansible/modules/file.py:1-60, lib/ansible/modules/copy.py:1-80, lib/ansible/modules/lineinfile.py:1-45 - Service and package control –
serviceprovides a generic service abstraction while OS-specific modules likesystemd,yum, andaptextend it. Source: lib/ansible/modules/service.py:1-70 - Information gathering –
setupcollects facts,getentqueries system databases (NSS, hosts, passwd),pingverifies connectivity,debugprints variables,uriperforms HTTP calls,templaterenders Jinja2 templates. Source: lib/ansible/modules/setup.py:1-120, lib/ansible/modules/getent.py:1-40, lib/ansible/modules/ping.py:1-30, lib/ansible/modules/template.py:1-40
Every built-in module shares a uniform contract: an argument_spec declaring parameters, a main() returning a result dictionary, and optional module.exit_json() / module.fail_json() calls. This contract is what allows action plugins and module utilities to wrap modules consistently. Source: lib/ansible/modules/copy.py:1-120
Facts Gathering Architecture
Facts are gathered by invoking the ansible.builtin.setup module automatically during gather_facts: true plays, or explicitly via ansible.builtin.setup in a task. The action plugin lib/ansible/plugins/action/setup.py coordinates the gathering process, while the actual fact collectors live under lib/ansible/facts/. Source: lib/ansible/plugins/action/setup.py:1-80
The facts system is decomposed into a collector pattern. ansible_collector.py acts as the orchestrator that imports and runs each subsystem collector. Each subsystem implements a collect(collected_facts) method that merges its findings into a shared dictionary. Source: lib/ansible/facts/ansible_collector.py:1-60, lib/ansible/facts/system/__init__.py:1-50
flowchart TD
A[Playbook gather_facts=true] --> B[Action: setup.py]
B --> C[ansible_collector.py]
C --> D[system facts]
C --> E[hardware facts]
C --> F[network facts]
C --> G[virtual facts]
D & E & F & G --> H[Merged ansible_facts dict]
H --> I[Available as host variables]Users can filter what is collected through the gather_subset and filter parameters on the setup task, which are forwarded into the collector to suppress unneeded subsystems. This is the same mechanism that powers the ansible_facts variable namespace and the hostvars interface. Source: lib/ansible/modules/setup.py:40-120, lib/ansible/facts/ansible_collector.py:60-140
Module Execution Pipeline
When a task targets a built-in module, Ansible's executor resolves the module name, packages its source as a self-contained payload (via module_common.py), ships it to the remote host over the configured connection, executes it, parses the JSON result, and applies check_mode, diff, and no_log semantics. The task executor is the central orchestrator for this pipeline. Source: lib/ansible/executor/task_executor.py:1-160
The action plugin for each module can intercept and pre-process arguments before the module body is transferred. For example, plugins/action/setup.py may short-circuit facts gathering on the controller when configured. This is the same mechanism users reference when asking about check_mode: false semantics on action plugins in issue #87071.
Module results are returned through a stable JSON envelope: ansible_facts (when facts are produced), changed (boolean), failed (boolean), and arbitrary key=value pairs. This envelope is what allows register, assert, debug, and templating ({{ result.stdout }}) to work uniformly across every built-in module. Source: lib/ansible/modules/command.py:40-80, lib/ansible/modules/stat.py:1-60
Limitations and Common Pitfalls
Several recurring community concerns illustrate the boundaries of the built-in surface:
getentand platform services – On musl-based systems (Alpine), the underlyinggetentbinary does not support all service overrides, soansible.builtin.getentreports an error even though the failure is at the OS layer. Issue #85568 tracks improvements to the error message.argument_specstyping –list of strdoes not currently reject integer elements, which can mask type errors for modules declared inargument_specs.yml. Issue #87217 documents this regression inargument_specs.- Check-mode overrides in action plugins – Module authors and action plugin authors must explicitly handle
check_mode: false; users in issue #87071 noted it is not always obvious when a built-in action will respect this hint. shellvscommand–commanddisables shell features for safety; users expecting pipes or globs must switch toshellor use module-native parameters such ascreatesandremoves. Source: lib/ansible/modules/command.py:30-60, lib/ansible/modules/shell.py:30-60
These constraints shape how users compose built-in modules with collection-provided modules: built-ins are favored for portability and zero-install overhead, while collections contribute richer, OS-specific behavior.
Source: https://github.com/ansible/ansible / Human Manual
Development, Testing & Community Workflow
Related topics: Overview & Core Architecture, Plugin & Extension System, Built-in Modules & Facts Gathering
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Overview & Core Architecture, Plugin & Extension System, Built-in Modules & Facts Gathering
Development, Testing & Community Workflow
The Ansible core repository provides a self-contained "hacking" tooling ecosystem that supports contributor development, automated module testing, CI execution on Azure Pipelines, and backporting fixes across the multiple supported release branches (currently 2.16, 2.18, 2.19, 2.20, 2.21). This page documents the developer-facing entry points, the test harness contracts, and the community workflow that ties releases to issue triage.
Development Environment Setup
The canonical entry point for contributors is hacking/env-setup, a shell script that prepares a usable Python environment from a fresh clone. Source: hacking/env-setup:1-40.
Key behaviors exposed by the script:
- Adds
lib/,test/, and the top-level repository path toPYTHONPATHso the in-tree Ansible code takes precedence over any system-installedansible-core. - Sources the user's existing shell environment so virtualenvs, PATH, and
ANSIBLE_*overrides are preserved. - Invoked as
. hacking/env-setupfrom the repository root, after whichansible,ansible-playbook,ansible-test, etc. resolve to the working tree.
The directory also exposes additional helpers documented in hacking/README.md, which enumerates developer entry points such as hacking/test-module.py, hacking/report.py, the hacking/azp/ CI driver, and the hacking/backport/ utilities. Source: hacking/README.md:1-40.
Module Testing with `test-module.py`
When iterating on a single module or action plugin, contributors typically run hacking/test-module.py. It wraps a single Python module file and drives it with a JSON argument payload, mirroring what the controller would send at runtime. Source: hacking/test-module.py:1-80.
The script supports the relevant module execution modes that appear in bug reports:
| Flag | Purpose |
|---|---|
--check | Runs the module with ANSIBLE_CHECK_MODE=True, used when validating action-plugin check-mode semantics (see issue #87071 about disabling check mode in action plugins). |
--debug / -D | Prints the module's invocation, warnings, deprecations, and result dicts. |
--diff | Injects ANSIBLE_DIFF_MODE=True so the module exercises the "would have changed" code path. |
--color / --no-color | Matches controller rendering for visual regression checks. |
--json | Supplies the args inline; otherwise they are read from a positional argument. |
--check combined with --debug | Surfaces idempotency regressions early, mirroring how ansible-playbook --check --diff behaves on the target host. |
Source: hacking/test-module.py:30-80. For users asking "how do I reproduce module XYZ locally before opening a PR?", test-module.py is the standard answer cited in module-development discussions.
CI Execution via Azure Pipelines
hacking/azp/run.py is the entry point invoked by the Azure DevOps pipeline definitions that gate every PR. It wraps ansible-test with the correct interpreter, target subset, and required environment variables for the Linux, macOS, and Windows images that the project uses. Source: hacking/azp/run.py:1-120.
The driver distinguishes:
- Unit and integration targets such as
ansible-test units --python 3.11 --venvandansible-test integration --target-prefix=. - Sanity checks invoked as
ansible-test sanity --docker, coveringpylint,yamllint,shellcheck,ansible-doc,compile,changelog, andignore-files. - Windows-specific PowerShell code paths, which became the focus of issue #87147 after a regression where
EncodedCommandUTF-16-LE handling broke PowerShell v5 hosts;ansible-test windowsjobs are the canonical way to reproduce this class of bug locally. Source: hacking/azp/run.py:60-120.
The hacking/report.py utility aggregates JUnit XML produced by each ansible-test invocation into a single HTML report, which the pipeline uploads as a build artifact. Source: hacking/report.py:1-80.
flowchart LR
A[Contributor pushes branch] --> B[PR opened / updated]
B --> C[azp/run.py driver]
C --> D[ansible-test sanity]
C --> E[ansible-test units]
C --> F[ansible-test integration]
C --> G[ansible-test windows]
D & E & F & G --> H[report.py aggregator]
H --> I[HTML + JUnit artifacts]
I --> J[Reviewer / Merged]Community Workflow and Backports
The hacking/backport/ directory hosts utilities that automate the housekeeping tasks surrounding Ansible's multi-branch release model. With active lines of development across 2.16, 2.18, 2.19, 2.20, and 2.21 (see releases v2.16.19, v2.18.18, v2.19.11, v2.20.7, v2.21.1 and the v2.21.2rc1 prerelease), every merged fix must be cherry-picked to each supported branch where the bug is reported present.
hacking/backport/backport_of_line_adder.py walks the commit log of a target branch, identifies merged PRs by their fixes / closes GitHub references, and emits the changelog fragment lines that changelogs/fragments/ requires. Source: hacking/backport/backport_of_line_adder.py:1-60.
Community-facing workflows rely on this tooling for several scenarios observed in issue traffic:
- Bug reports that affect only one platform, such as issue #85568 (
getenton Alpine with musl libc) or issue #87213 (btrfs scrub status), require a targeted fix plus a backport; thebackport_of_line_adderscript supplies the matching changelog entries for each branch. - Argument-spec validation regressions like #87217 (list-of-str accepting integers) ship from
develand are backported once a stable cut is reached. - Feature proposals with long discussion tails — looping over blocks (#13262, 154 comments), encrypted SSH vault keys (#22382),
ansible-galaxy collection uninstall(#67759), per-task verbosity (#24215), blocks-as-handlers (#14270) — move through the formalchangelogs/fragments/proposal flow rather than the backport utility.
Practical Contributor Flow
A typical first-time contributor experience therefore looks like:
- Clone, then
. hacking/env-setupto get a workingansibleandansible-testfrom the source tree. Source: hacking/env-setup:1-40. - Reproduce module-level defects with
hacking/test-module.py --check --debug <module>.py --json '<args>'. Source: hacking/test-module.py:30-80. - Run
ansible-test sanity --dockerand the targetedunits/integrationsubsets before pushing, mirroring whathacking/azp/run.pywill execute. Source: hacking/azp/run.py:60-120. - Add a changelog fragment under
changelogs/fragments/describing the bugfix or module change. - After merge, the maintainers use
hacking/backport/backport_of_line_adder.pyto forward the fix into the still-supported release branches and produce release notes for tags such as v2.21.1, v2.20.7, v2.19.11, v2.18.18, and v2.16.19. Source: hacking/backport/backport_of_line_adder.py:1-60.
This pipeline — local env-setup → test-module.py debugging → azp/run.py-driven CI → backport_of_line_adder.py release plumbing — is the connective tissue between Ansible's codebase, its release cadence, and the community contributions tracked on GitHub.
Source: https://github.com/ansible/ansible / Human Manual
Doramagic Pitfall Log
Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
Doramagic Pitfall Log
Found 29 structured pitfall item(s), including 4 high/blocking item(s). Top priority: Installation risk - Installation risk requires verification.
1. Installation risk: Installation risk requires verification
- Severity: high
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | https://github.com/ansible/ansible/issues/87228
2. Configuration risk: Configuration risk requires verification
- Severity: high
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | https://github.com/ansible/ansible/issues/79725
3. Configuration risk: Configuration risk requires verification
- Severity: high
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | https://github.com/ansible/ansible/issues/85568
4. Security or permission risk: Security or permission risk requires verification
- Severity: high
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | https://github.com/ansible/ansible/issues/87217
5. Installation risk: Installation risk requires verification
- Severity: medium
- Finding: Developers should check this installation risk before relying on the project: btrfs scrub status doesn't update via ansible
- User impact: Developers may fail before the first successful local run: btrfs scrub status doesn't update via ansible
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: btrfs scrub status doesn't update via ansible. Context: Observed when using python, linux
- Evidence: failure_mode_cluster:github_issue | https://github.com/ansible/ansible/issues/87213
6. Installation risk: Installation risk requires verification
- Severity: medium
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | https://github.com/ansible/ansible/issues/87213
7. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Developers should check this configuration risk before relying on the project: Action plugin: how to execute module with check mode unset?
- User impact: Developers may misconfigure credentials, environment, or host setup: Action plugin: how to execute module with check mode unset?
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Action plugin: how to execute module with check mode unset?. Context: Observed when using python, docker
- Evidence: failure_mode_cluster:github_issue | https://github.com/ansible/ansible/issues/87071
8. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Developers should check this configuration risk before relying on the project: [regression] PowerShell v5 support broke with ansible-core 2.21
- User impact: Developers may misconfigure credentials, environment, or host setup: [regression] PowerShell v5 support broke with ansible-core 2.21
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [regression] PowerShell v5 support broke with ansible-core 2.21. Context: Observed when using python, windows, linux
- Evidence: failure_mode_cluster:github_issue | https://github.com/ansible/ansible/issues/87147
9. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Developers should check this configuration risk before relying on the project: argument_specs with list of str accept integer in it
- User impact: Developers may misconfigure credentials, environment, or host setup: argument_specs with list of str accept integer in it
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: argument_specs with list of str accept integer in it. Context: Observed when using python, linux
- Evidence: failure_mode_cluster:github_issue | https://github.com/ansible/ansible/issues/87217
10. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Developers should check this configuration risk before relying on the project: getent returns misleading error when service override fails due to platform limitations on Alpine
- User impact: Developers may misconfigure credentials, environment, or host setup: getent returns misleading error when service override fails due to platform limitations on Alpine
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: getent returns misleading error when service override fails due to platform limitations on Alpine. Context: Observed when using python, linux
- Evidence: failure_mode_cluster:github_issue | https://github.com/ansible/ansible/issues/85568
11. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | https://github.com/ansible/ansible/issues/87147
12. Capability evidence risk: Capability evidence risk requires verification
- Severity: medium
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: capability.assumptions | https://github.com/ansible/ansible
Source: Doramagic discovery, validation, and Project Pack records