Skip to content

feat(filter-diff): support glob patterns in exclude-paths#224

Draft
jedp-docker wants to merge 1 commit into
docker:mainfrom
jedp-docker:feat/filter-diff-glob-patterns
Draft

feat(filter-diff): support glob patterns in exclude-paths#224
jedp-docker wants to merge 1 commit into
docker:mainfrom
jedp-docker:feat/filter-diff-glob-patterns

Conversation

@jedp-docker
Copy link
Copy Markdown

@jedp-docker jedp-docker commented May 30, 2026

Summary

  • exclude-paths now accepts glob patterns in addition to plain path prefixes
  • A single **/package-lock.json entry covers lock files at any depth, instead of listing every path explicitly
  • Plain prefix patterns are unchanged — fully backward compatible

Implementation

Uses path.matchesGlob (added in Node v22.5.0/v20.17.0, available in the node24 runtime — no new dependencies). Patterns containing * are matched as globs; all others continue to use startsWith.

Type augmentation

path.matchesGlob is not typed in @types/node@22.0.0 (the version pinned in pnpm-lock.yaml). Normally this would be fixed by bumping @types/node, but that requires regenerating the lockfile — which currently fails due to a pre-existing issue:

@actions/artifact@6.2.1 declares "@protobuf-ts/plugin": "^2.2.3-alpha.1" as a dependency. Under pnpm's blockExoticSubdeps: true + resolutionMode: time-based (both required by docker-security/safe-defaults), any fresh pnpm install fails with ERR_PNPM_EXOTIC_SUBDEP. The frozen lockfile used in CI works fine because --frozen-lockfile skips resolution entirely and the check never fires.

The fix (@protobuf-ts/plugin dropped from deps) is already merged in the actions/toolkit source as @actions/artifact@6.2.2, but that version has not been published to npm yet. Once it is, a normal pnpm install will work and we can bump @types/node cleanly.

In the meantime, matchesGlob is declared via a module augmentation in filter-diff.ts with a comment explaining the blocker.

Motivation

Without glob support, callers had to enumerate every lock file path explicitly. In docker/internal-agents there are 7 package-lock.json files — with this change that list collapses to one line:

exclude-paths: |
  **/package-lock.json

Test plan

  • 5 new unit tests covering **/name glob matching at root depth, nested depth, non-matching files, mixed diffs, and coexistence with plain prefix patterns
  • Full suite: 376/376 passing

🤖 Generated with Claude Code

Copy link
Copy Markdown
Contributor

@docker-agent docker-agent left a comment

Choose a reason for hiding this comment

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

Assessment: 🟡 NEEDS ATTENTION

One medium-severity finding in the newly added glob-matching heuristic.

const isExcluded = (filePath: string): boolean =>
prefixes.some((prefix) => filePath.startsWith(prefix));
prefixes.some((pattern) =>
pattern.includes('*') ? matchesGlob(filePath, pattern) : filePath.startsWith(pattern),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[MEDIUM] Glob heuristic pattern.includes('*') misses ? and [...] metacharacters

The new heuristic on line 72 routes patterns to matchesGlob only when they contain *. However, path.matchesGlob also supports ? (match any single character) and [...] (character classes), which would silently fall through to startsWith instead.

For example:

  • file?.ts — passed to startsWith, treated as a literal prefix string instead of a glob
  • src/[generated]/ — same silent failure

The result is wrong exclusion behaviour with no error thrown — files that should be excluded won't be (or vice versa).

Suggested fix: Broaden the heuristic to detect any glob metacharacter:

const isGlob = (p: string) => /[*?[]/.test(p);
// then:
isGlob(pattern) ? matchesGlob(filePath, pattern) : filePath.startsWith(pattern)

Note: the PR description and docs explicitly limit the feature to *-style globs ("Entries containing * are matched…"), so this may be an intentional scope limitation — but if so, it's worth documenting that ?/[...] patterns are unsupported rather than silently mishandled.

@jedp-docker jedp-docker force-pushed the feat/filter-diff-glob-patterns branch from 175d5bb to e180664 Compare May 30, 2026 03:35
Plain prefix matching required listing every package-lock.json path
explicitly. With glob support, a single `**/package-lock.json` entry
covers all lock files at any depth.

Uses `path.matchesGlob` (added in Node v22.5.0/v20.17.0, available in
the node24 runtime — no new dependencies). Patterns containing `*` are
matched as globs; plain strings continue to use `startsWith` for
backward compatibility.

Adds a `declare module` augmentation for `matchesGlob` since the
@types/node version pinned in pnpm-lock.yaml predates its type
definition. The lockfile cannot be updated until a pre-existing exotic
subdep in @actions/artifact@6.2.1 is resolved upstream.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@jedp-docker jedp-docker force-pushed the feat/filter-diff-glob-patterns branch from e180664 to 7a63f7e Compare May 30, 2026 04:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants