Fix first-run collection discovery by gating plugin loader initialization#516
Merged
cidrblock merged 5 commits intoansible:mainfrom Aug 13, 2025
Merged
Conversation
…th capture Fixes first-run collection discovery issue where ansible-lint fails to find plugins from collections installed during prepare_environment(). The problem occurs because Ansible's plugin loader was initialized too early with incomplete collection paths, before prepare_environment() installs dependencies from requirements.yml and galaxy.yml files. This particularly affects Templar usage since it relies on the collection loader for template rendering and plugin discovery. Changes: - Add Runtime.plugin_loader_enabled class variable to gate access - Add enable_plugin_loader() method for explicit initialization - Modify Plugins.__getattribute__ to raise RuntimeError if accessed early - Enhance clean() to reset flags and unload ansible modules for test isolation - Move plugin loader init from _ensure_module_available() to enable_plugin_loader() This ensures plugin loader initialization happens after collections are installed, eliminating the 'works on second run' behavior.
cidrblock
added a commit
to cidrblock/ansible-lint
that referenced
this pull request
Aug 13, 2025
Fixes first-run collection discovery issue by calling enable_plugin_loader() after prepare_environment() has installed collections from requirements.yml and galaxy.yml files. This ensures that Ansible's plugin loader is initialized with complete collection paths, allowing Templar and other components to properly discover plugins from newly installed collections on the first run. Related to: ansible/ansible-compat#516
alisonlhart
approved these changes
Aug 13, 2025
e61c090 to
ec878ef
Compare
cidrblock
added a commit
to cidrblock/ansible-lint
that referenced
this pull request
Aug 13, 2025
Fixes first-run collection discovery issue by calling enable_plugin_loader() after prepare_environment() has installed collections from requirements.yml and galaxy.yml files. This ensures that Ansible's plugin loader is initialized with complete collection paths, allowing Templar and other components to properly discover plugins from newly installed collections on the first run. Related to: ansible/ansible-compat#516
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When
ansible-lintruns on collections for the first time, it fails to discover plugins from collections installed byansible-compatduringprepare_environment(). The issue occurs because Ansible's plugin loader is initialized too early with incomplete collection paths, beforeprepare_environment()has a chance to install dependencies.Root Cause
The plugin loader was being initialized during
Runtime.__init__()or early module imports, capturing collection paths before:requirements.ymlandgalaxy.ymldependencies/.ansible/collections) is populatedANSIBLE_COLLECTIONS_PATHincludes the newly installed collectionsThe problem was particularly acute because
ansible-lint'sTemplarclass internally uses Ansible's collection loader for template rendering and plugin discovery. When the plugin loader was initialized early with incomplete paths,Templarwould fail to find collections that were installed duringprepare_environment(), leading to template rendering failures and missing plugin errors.Solution
Introduced a plugin loader gate mechanism to delay initialization until the environment is fully prepared:
1. Gated Plugin Loader Access
Runtime.plugin_loader_enabledclass variable (defaults toFalse)Plugins.__getattribute__to raiseRuntimeErrorif plugin loader is accessed before being enabled2. Explicit Plugin Loader Enablement
Runtime.enable_plugin_loader()method to explicitly initialize the plugin loader_ensure_module_available()to this dedicated methodansible-lintnow callsenable_plugin_loader()afterprepare_environment()completes3. Enhanced State Management
Runtime.clean()to reset bothinitializedandplugin_loader_enabledflagsansible.plugins.*,ansible.utils.collection_loader, andansible.collections.*to ensure fresh state between test runsChanges Made
Impact
ansible-compatAPIThis change ensures that
ansible-lintcan successfully discover and use collection plugins on the first run, eliminating the "works on second run" behavior that users were experiencing.