Support !-prefix exclusions in filter entries#222
Merged
Conversation
Entries in filter allowlists whose first character is `!` are now treated as exclusions. A resource is included iff at least one inclusion matches and no exclusion matches. Pure-exclusion lists behave as "include-all, then subtract" (implicit `*` include). - Localized to `matchesFilter` in filter-service.ts; no schema changes. - Works uniformly for top-level fields (apiNames, backendNames, ...) and for `apiSubFilters` / `workspaceSubFilters` string lists. - Respects existing semantics: case-insensitive, API revision-suffix stripping, parent-to-child cascading. - New unit tests cover pure-exclusion, mixed inclusion + exclusion, wildcard exclusion, revision matching, parent cascade, non-leading `!` as literal, and sub-filter exclusions. - Docs: filtering-resources.md gains a negation section with examples. Closes #216 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR extends the existing filter matching logic to support !-prefixed entries as exclusions, enabling “include-all-minus” and mixed include/exclude allowlists across top-level filter lists and nested sub-filter lists (e.g., apiSubFilters operations).
Changes:
- Updated
matchesFilterto split allowlists into inclusion vs. exclusion entries and apply(implicit/explicit include) AND (no exclude match)semantics. - Added a dedicated unit-test suite covering exclusion behavior (pure exclusion, wildcard exclusion, case-insensitivity, API revision-root matching, parent→child cascade, and
apiSubFilters). - Documented
!exclusions in the filtering guide with semantics and examples.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/services/filter-service.ts | Implements !-prefixed exclusions in allowlist matching via include/exclude evaluation. |
| tests/unit/services/filter-service.test.ts | Adds unit tests validating exclusion semantics across key scenarios. |
| docs/guides/filtering-resources.md | Documents the new exclusion operator with examples and semantics. |
EMaher
previously approved these changes
Jul 2, 2026
!-prefix exclusions in filter entries!-prefix exclusions in filter entries
Address Copilot review feedback on #216 / PR #222: an unquoted leading `!` in a YAML sequence is parsed as a YAML tag and produces a confusing load error before the filter code ever sees the value. Add an explicit "always quote `!` entries" note wherever we show filter syntax, so users copying examples don't hit that. Places updated: - docs/guides/filtering-resources.md (main filter guide) - docs/commands/extract.md (mentions `!` exclusion + quoting alongside the existing wildcard docs) - src/templates/configs/filter-config.yaml (the init-scaffolded filter template; adds an exclusion example with the quoting note) - src/templates/copilot/configure-filter-prompt.md (teaches the configure-filter Copilot prompt about `!` exclusions + quoting) Refs #216, PR #222. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
EMaher
approved these changes
Jul 2, 2026
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
Adds a negation operator to filter allowlists. Any filter entry whose first character is
!is treated as an exclusion rather than an inclusion, letting users concisely say "include everything matching this pattern, except these specific ones."Semantics
!must be the first character of an entry to be interpreted as negation;foo!baris a literal name. (APIM resource names cannot contain!, so this is unambiguous.)*.apis,backends,products,namedValues, …) and to nested lists insideapiSubFiltersandworkspaceSubFilters—workspaceSubFiltersreuseFilterConfigunder the hood, so no separate wiring is needed.Changes
src/services/filter-service.ts—matchesFilternow partitions each allowlist intoincludes/excludesby leading-!prefix and evaluates(no includes OR any include matches) AND no exclude matches. A smallentryMatcheshelper deduplicates wildcard vs. exact matching logic.tests/unit/services/filter-service.test.ts— newnegationsuite (9 tests) covering pure-exclusion, mixed inclusion + exclusion, wildcard exclusion, case-insensitivity, revision-suffix matching, parent → child cascade, non-leading!treated as a literal character, and exclusions insideapiSubFilters.docs/guides/filtering-resources.md— new "Excluding resources with!" section with worked examples for top-level and sub-filter usage.No schema changes —
!-prefixed strings are already valid string entries, soconfig-loaderdoesn't need to know about the operator.Related Issue(s)
Closes #216
Verification
npm test— 1075 tests pass (49 test files).npm run lint— clean.