Skip to content

fix(toolkit-lib): user-supplied glob include patterns silently ignored#1652

Open
iliapolo wants to merge 4 commits into
mainfrom
fix/watch-glob-include-patterns
Open

fix(toolkit-lib): user-supplied glob include patterns silently ignored#1652
iliapolo wants to merge 4 commits into
mainfrom
fix/watch-glob-include-patterns

Conversation

@iliapolo

@iliapolo iliapolo commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Fixes #1647

Summary

User-specified glob patterns in cdk.json's watch.include (e.g. src/**/*.ts) were silently ignored: cdk watch started, observed nothing, and never triggered on file changes. Only literal directory paths worked, and no error was shown — so watch appeared to be running but was effectively dead.

Root cause

This is remaining fallout from the chokidar v3→v4 migration (#1146 fixed only the default include: ['**'] case). In chokidar v4 the ignored callback also controls directory traversal: if a directory is ignored, its entire subtree is pruned and no nested file is ever discovered.

The matcher ignored any path that didn't match an include pattern. But a directory like src never matches a file glob like src/**/*.ts, so src was pruned before any .ts file inside it could be found — leaving watch observing nothing.

Fix

The matcher now uses the Stats chokidar provides to distinguish files from directories:

  • Excludes always take precedence and prune both files and directories.
  • A directory is kept if it could be an ancestor of an included file (derived from the progressive /-delimited prefixes of each include pattern, e.g. src/**/*.tssrc, src/**, src/**/*.ts), so we descend and discover the nested files we actually want. It is never pruned merely for failing the file-level include filter.
  • A file must match an include pattern to be watched.
  • When stats are absent (chokidar invokes the callback both with and without stats during traversal), the path is kept if it matches a file include pattern or is a potential ancestor directory of one.

This restores chokidar v3 glob semantics: globs like src/**/*.ts watch exactly the matching files, while excludes still prune entire subtrees (e.g. node_modules/**) efficiently. Literal directory paths and the default ['**'] config continue to work unchanged.

Testing

  • New unit tests in glob-matcher.test.ts covering directory traversal: ancestor directories of a file glob are descended into, directories that cannot contain a match are pruned, directories are only pruned by excludes, multiple globs across separate trees, and the no-stats traversal path.
  • New regression test in watch.test.ts asserting the ignored callback descends into ancestor directories of a user-supplied file glob (src/**/*.ts).
  • Existing tests updated to invoke the ignored callback the way chokidar v4 actually does — with file system Stats.
  • New integ test

Q. Why did every test need to be updated to pass a stats argument?

The fix changes the matcher's contract. It used to be a pure path filter — one string in, ignore/keep out — so tests called shouldIgnore('some/path') and asserted the result directly. Now the correct answer depends on whether the path is a file or a directory: src must be kept (so chokidar descends and finds src/a.ts) even though it doesn't match a file glob like src/**/*.ts, while src/a.js under that same glob must be ignored. Since 'src' looks just like a file path, the only way to tell them apart is the Stats argument chokidar v4 actually passes. The old single-argument calls now hit the stats-absent fallback — which is intentionally permissive and defers real filtering to the later with-stats call — so they no longer reflect how chokidar invokes the callback. Passing FILE/DIR stats updates the tests to exercise it the way production does.

Checklist

  • This change contains a major version upgrade for a dependency and I confirm all breaking changes are addressed
    • Release notes for the new version:

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@aws-cdk-automation aws-cdk-automation requested a review from a team June 19, 2026 18:52
@codecov-commenter

codecov-commenter commented Jun 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.80%. Comparing base (ab0f8e3) to head (bfe6fd7).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1652   +/-   ##
=======================================
  Coverage   88.80%   88.80%           
=======================================
  Files          77       77           
  Lines       11354    11354           
  Branches     1584     1584           
=======================================
  Hits        10083    10083           
  Misses       1241     1241           
  Partials       30       30           
Flag Coverage Δ
suite.unit 88.80% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Regression test for #1647. The existing glob watch integ tests use a
'**/*.ts' include with a file at the watch-dir root - the one glob shape that
cannot reproduce the bug, since a '**'-leading pattern prunes nothing and a
root-level file needs no directory descent.

This test uses a directory-scoped glob ('src/**/*.ts') with the watched file
nested inside 'src', exercising the path that actually regressed: chokidar v4's
ignored callback gates directory traversal, and the bug pruned the 'src'
directory before any nested file could be discovered.

Verified the test fails (poll timeout waiting for 'Detected change to') when the
matcher fix is reverted, and passes with it in place.
@iliapolo iliapolo marked this pull request as ready for review June 19, 2026 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(watch) cdk watch: user-supplied glob include patterns silently ignored on 2.1128.0 (no change detection)

2 participants