feat: support nested scenario directories in collection mode#4611
Merged
feat: support nested scenario directories in collection mode#4611
Conversation
Allow scenario names to contain `/` path separators when running in collection mode (extensions/molecule/), enabling hierarchical grouping of scenarios (e.g. `appliance_vlans/merged`). - Add `_resolve_scenario_glob()` helper in command/base.py for slash-aware scenario targeting - Add `Config._derive_scenario_name()` to derive hierarchical names from molecule.yml paths relative to the collection root - Gate all changes behind collection-mode detection so role-mode testing is unaffected - Add comprehensive unit and integration tests - Document the feature in configuration.md, getting-started-collections.md, and usage.md Co-authored-by: Cursor <cursoragent@cursor.com>
Remove the slash guard from _resolve_scenario_glob so collection mode always uses os.path.join instead of str.replace. This avoids corrupting multi-star globs like '**' and simplifies the logic since both flat and nested names produce identical results with the path-based approach. Co-authored-by: Cursor <cursoragent@cursor.com>
for more information, see https://pre-commit.ci
Allow 'molecule test -s "appliance_vlans/*"' to expand and run all scenarios under a nested group. Replaces scenario_names with the actual discovered names after glob expansion so Scenarios._verify and _filter_for_scenario work correctly. Adds 3 new tests covering wildcard glob resolution, multi-scenario discovery, and Scenarios verification with expanded names. Updates docs to show wildcard usage. Co-authored-by: Cursor <cursoragent@cursor.com>
- Replace os.path.join with Path / operator (PTH118) - Use ternary for scenario_name assignment (SIM108) - Move Path import into TYPE_CHECKING block (TC003) - Add full Google-style docstrings with Args/Returns (pydoclint) - Rename fixture to fixture_ prefix pattern (pylint W0621) - Replace os.path.join in test expectations with string literals Co-authored-by: Cursor <cursoragent@cursor.com>
- Fix ephemeral directory creation with nested names: replace '/' with '--' in scenario name when constructing filesystem paths to avoid creating unintended nested directories (scenario.py) - Add path traversal validation: reject scenario names containing '..' or starting with '/' to prevent directory escape - Add glob pattern assumptions comment in _resolve_scenario_glob - Document _derive_scenario_name edge case for molecule.yml directly under collection root - Add 7 new tests: path traversal rejection (4 cases), nonexistent scenario handling (2 cases), and ephemeral directory name safety Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add standard MIT license header to test_nested_scenarios.py - Replace unit-level ephemeral name test with integration test that creates a real Scenario object and verifies the ephemeral_directory property produces a flat path (no nested dirs from '/' in name) Co-authored-by: Cursor <cursoragent@cursor.com>
shatakshiiii
approved these changes
Feb 19, 2026
rija
added a commit
to rmenage/ansible-role-hardened-docker
that referenced
this pull request
Mar 3, 2026
This MR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [molecule](https://github.com/ansible-community/molecule) ([changelog](https://github.com/ansible-community/molecule/releases)) | `>=25.0.0,<26.0.0` → `>=26.2.0,<26.3.0` |  |  | --- ### Release Notes <details> <summary>ansible-community/molecule (molecule)</summary> ### [`v26.2.0`](https://github.com/ansible/molecule/releases/tag/v26.2.0) [Compare Source](ansible/molecule@v25.12.0...v26.2.0) #### Features - feat: improve scenario selection and filtering for large collection trees ([#​4613](ansible/molecule#4613)) [@​cidrblock](https://github.com/cidrblock) - feat: support nested scenario directories in collection mode ([#​4611](ansible/molecule#4611)) [@​cidrblock](https://github.com/cidrblock) #### Fixes - fix: remove use of click-help-colors ([#​4569](ansible/molecule#4569)) [@​ssbarnea](https://github.com/ssbarnea) - fix: validate .git directories in find\_vcs\_root() ([#​4610](ansible/molecule#4610)) [@​skeetmtp](https://github.com/skeetmtp) - fix: handle missing molecule\_yml\_date\_modified key in state ([#​4606](ansible/molecule#4606)) [@​dmzoneill](https://github.com/dmzoneill) - Add execution flow documentation ([#​4589](ansible/molecule#4589)) [@​Qalthos](https://github.com/Qalthos) - Modify contact links in issue template config ([#​4586](ansible/molecule#4586)) [@​alisonlhart](https://github.com/alisonlhart) #### Maintenance - chore(deps): update all dependencies ([#​4612](ansible/molecule#4612)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore: replace pre-commit with prek ([#​4614](ansible/molecule#4614)) [@​ssbarnea](https://github.com/ssbarnea) - chore: use tox>=4.46.0 during testing ([#​4615](ansible/molecule#4615)) [@​ssbarnea](https://github.com/ssbarnea) - chore(deps): update pep621 ([#​4609](ansible/molecule#4609)) @​[renovate\[bot\]](https://github.com/apps/renovate) - Bump cryptography from 46.0.4 to 46.0.5 ([#​4604](ansible/molecule#4604)) @​[dependabot\[bot\]](https://github.com/apps/dependabot) - Bump pillow from 12.1.0 to 12.1.1 ([#​4605](ansible/molecule#4605)) @​[dependabot\[bot\]](https://github.com/apps/dependabot) - chore(deps): update all dependencies ([#​4608](ansible/molecule#4608)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore(deps): update all dependencies ([#​4603](ansible/molecule#4603)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore(deps): update all dependencies ([#​4599](ansible/molecule#4599)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore(deps): update dependencies \[security] ([#​4601](ansible/molecule#4601)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore(deps): update all dependencies ([#​4598](ansible/molecule#4598)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore(deps): update all dependencies ([#​4595](ansible/molecule#4595)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore(deps): update all dependencies ([#​4594](ansible/molecule#4594)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore(deps): update all dependencies ([#​4593](ansible/molecule#4593)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore(deps): update all dependencies ([#​4592](ansible/molecule#4592)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore(deps): update all dependencies ([#​4591](ansible/molecule#4591)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore(deps): update all dependencies ([#​4590](ansible/molecule#4590)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore(deps): update all dependencies ([#​4587](ansible/molecule#4587)) @​[renovate\[bot\]](https://github.com/apps/renovate) - chore: adopt pytest>=9.0.0 config ([#​4583](ansible/molecule#4583)) [@​Qalthos](https://github.com/Qalthos) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi45OS4wIiwidXBkYXRlZEluVmVyIjoiNDIuOTkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Refs: rmenage/ansible-role-hardened-docker!23 See-also:
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.
Summary
/separators (e.g.,molecule test -s appliance_vlans/merged) to targetmolecule.ymlfiles in subdirectories underextensions/molecule/._resolve_scenario_glob()incommand/base.pyfor path-based glob resolution andConfig._derive_scenario_name()inconfig.pyfor hierarchical name derivation from file paths.extensions/molecule/) — role-mode testing is completely unaffected.docs/configuration.md,docs/getting-started-collections.md, anddocs/usage.md.Details
Large Ansible collections (e.g., 48 resource modules × 4 states = ~200 scenarios) benefit from grouping related scenarios under parent directories rather than using a flat layout. This PR enables:
Test plan
tests/unit/test_nested_scenarios.pypasstox)Made with Cursor