Skip to content

feat: improve scenario selection and filtering for large collection trees#4613

Merged
cidrblock merged 6 commits intomainfrom
exclude_wild
Feb 24, 2026
Merged

feat: improve scenario selection and filtering for large collection trees#4613
cidrblock merged 6 commits intomainfrom
exclude_wild

Conversation

@cidrblock
Copy link
Contributor

@cidrblock cidrblock commented Feb 23, 2026

Problem

Collections with hundreds of nested scenarios expose several pain points in Molecule's scenario selection and filtering:

  1. Discovery requires manual configMOLECULE_COLLECTION_GLOB defaults to */molecule.yml (flat), so nested scenarios aren't discovered unless users manually set MOLECULE_GLOB to a recursive pattern.
  2. -s wildcards don't recurse-s "camera_*" with a recursive MOLECULE_GLOB produces camera_*/molecule.yml instead of camera_*/**/molecule.yml, missing scenarios nested under matching directories.
  3. -e only matches exact names — there's no way to exclude a group of scenarios by pattern (e.g., -e "appliance_vlans/*"), forcing users to list every scenario name individually.

All three issues stem from the same root cause: Molecule's scenario selection was designed for flat directory layouts and doesn't scale to deeply nested collection trees.

Solution

Three targeted changes, all in src/molecule/command/base.py and src/molecule/constants.py:

1. Recursive default collection glob

Change MOLECULE_COLLECTION_GLOB from extensions/molecule/*/molecule.yml to extensions/molecule/**/molecule.yml. This is a strict superset — ** matches everything * matches plus nested directories — so existing flat layouts are unaffected.

2. Recursive wildcard targeting with -s

When -s receives a wildcard pattern (e.g., camera_*) and the base glob uses **, append **/molecule.yml instead of just molecule.yml so scenarios at any nesting depth are discovered.

3. Glob-aware -e/--exclude filtering

Replace plain not in checks with fnmatch pattern matching via a new _is_excluded() helper, so -e "appliance_vlans/*" or -e "*/merged" exclude entire groups of scenarios.

Changes

  • src/molecule/constants.py: MOLECULE_COLLECTION_GLOB uses ** instead of *
  • src/molecule/command/base.py:
    • New _is_excluded() helper using fnmatch.fnmatch
    • Both exclude filter paths updated to use _is_excluded
    • _resolve_scenario_glob appends **/molecule.yml for wildcard + recursive glob combinations
  • tests/unit/command/test_base.py: 9 parameterized test cases for _is_excluded
  • tests/unit/test_nested_scenarios.py: Updated assertions for new default glob; 2 new recursive wildcard test cases

Test plan

  • pytest tests/unit/test_nested_scenarios.py — 31 passed
  • pytest tests/unit/command/test_base.py::test_is_excluded — 9 passed
  • tox -e lint — clean

cidrblock and others added 2 commits February 23, 2026 15:17
Replace plain string equality checks with fnmatch pattern matching so
that -e can accept glob patterns like 'appliance_vlans/*' or '*/merged'
in addition to exact scenario names.

Co-authored-by: Cursor <cursoragent@cursor.com>
When -s receives a wildcard pattern like "camera_*" and the base
MOLECULE_GLOB uses ** (recursive), append **/molecule.yml instead of
just molecule.yml so scenarios at any nesting depth are discovered.

Co-authored-by: Cursor <cursoragent@cursor.com>
Change MOLECULE_COLLECTION_GLOB from */molecule.yml to **/molecule.yml
so nested scenarios are discovered automatically without requiring users
to manually set MOLECULE_GLOB.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions github-actions bot added feat and removed feat labels Feb 23, 2026
@cidrblock cidrblock changed the title feat: support glob wildcards in -e/--exclude and recursive wildcard targeting with -s feat: improve scenario selection and filtering for large collection trees Feb 23, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>

This comment was marked as outdated.

…tection

- Use exact-match short-circuit before fnmatchcase to protect scenario
  names containing literal glob characters
- Use wcmatch glob.is_magic with BRACE flag for wildcard detection so
  brace expansion patterns like {camera,router}_* are recognized

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@cidrblock cidrblock merged commit 36a628c into main Feb 24, 2026
27 checks passed
@cidrblock cidrblock deleted the exclude_wild branch February 24, 2026 14:55
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` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/molecule/26.2.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/molecule/25.12.0/26.2.0?slim=true) |

---

### 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 ([#&#8203;4613](ansible/molecule#4613)) [@&#8203;cidrblock](https://github.com/cidrblock)
- feat: support nested scenario directories in collection mode ([#&#8203;4611](ansible/molecule#4611)) [@&#8203;cidrblock](https://github.com/cidrblock)

#### Fixes

- fix: remove use of click-help-colors ([#&#8203;4569](ansible/molecule#4569)) [@&#8203;ssbarnea](https://github.com/ssbarnea)
- fix: validate .git directories in find\_vcs\_root() ([#&#8203;4610](ansible/molecule#4610)) [@&#8203;skeetmtp](https://github.com/skeetmtp)
- fix: handle missing molecule\_yml\_date\_modified key in state ([#&#8203;4606](ansible/molecule#4606)) [@&#8203;dmzoneill](https://github.com/dmzoneill)
- Add execution flow documentation ([#&#8203;4589](ansible/molecule#4589)) [@&#8203;Qalthos](https://github.com/Qalthos)
- Modify contact links in issue template config ([#&#8203;4586](ansible/molecule#4586)) [@&#8203;alisonlhart](https://github.com/alisonlhart)

#### Maintenance

- chore(deps): update all dependencies ([#&#8203;4612](ansible/molecule#4612)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore: replace pre-commit with prek ([#&#8203;4614](ansible/molecule#4614)) [@&#8203;ssbarnea](https://github.com/ssbarnea)
- chore: use tox>=4.46.0 during testing ([#&#8203;4615](ansible/molecule#4615)) [@&#8203;ssbarnea](https://github.com/ssbarnea)
- chore(deps): update pep621 ([#&#8203;4609](ansible/molecule#4609)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- Bump cryptography from 46.0.4 to 46.0.5 ([#&#8203;4604](ansible/molecule#4604)) @&#8203;[dependabot\[bot\]](https://github.com/apps/dependabot)
- Bump pillow from 12.1.0 to 12.1.1 ([#&#8203;4605](ansible/molecule#4605)) @&#8203;[dependabot\[bot\]](https://github.com/apps/dependabot)
- chore(deps): update all dependencies ([#&#8203;4608](ansible/molecule#4608)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore(deps): update all dependencies ([#&#8203;4603](ansible/molecule#4603)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore(deps): update all dependencies ([#&#8203;4599](ansible/molecule#4599)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore(deps): update dependencies \[security] ([#&#8203;4601](ansible/molecule#4601)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore(deps): update all dependencies ([#&#8203;4598](ansible/molecule#4598)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore(deps): update all dependencies ([#&#8203;4595](ansible/molecule#4595)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore(deps): update all dependencies ([#&#8203;4594](ansible/molecule#4594)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore(deps): update all dependencies ([#&#8203;4593](ansible/molecule#4593)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore(deps): update all dependencies ([#&#8203;4592](ansible/molecule#4592)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore(deps): update all dependencies ([#&#8203;4591](ansible/molecule#4591)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore(deps): update all dependencies ([#&#8203;4590](ansible/molecule#4590)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore(deps): update all dependencies ([#&#8203;4587](ansible/molecule#4587)) @&#8203;[renovate\[bot\]](https://github.com/apps/renovate)
- chore: adopt pytest>=9.0.0 config ([#&#8203;4583](ansible/molecule#4583)) [@&#8203;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:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants