Skip to content

feat: allow wildcard API and workspace sub-filters, and filtering API tag descriptions - #338

Open
Chris Dayne (cdayne) wants to merge 2 commits into
Azure:mainfrom
cdayne:feat/wildcard-sub-filters
Open

Chris Dayne (cdayne) wants to merge 2 commits into
Azure:mainfrom
cdayne:feat/wildcard-sub-filters

Conversation

@cdayne

@cdayne Chris Dayne (cdayne) commented Nov 6, 2026 •

Copy link
Copy Markdown

Summary

Lets a nested API or workspace filter entry be keyed by a wildcard pattern, so one sub-filter applies to every matching API or workspace, and adds a tagDescriptions API sub-filter.

Changes

  • Wildcard API sub-filters (Allow excluding schemas and operations from all APIs during extraction #316): the key of a nested apis entry can be a pattern (- '*': { operations: [], schemas: [] }). It selects the matching APIs, like a plain pattern, and its sub-filter applies to each of them. An entry keyed by an API's name takes precedence over a pattern, even an empty one (- orders: {} or - orders:), which includes everything; otherwise the first matching pattern applies. One lookup (findApiSubFilter) is used by filtering, the specification operation filter and API publishing.
  • Workspace sub-filters keyed by a pattern: on main, a workspaces entry keyed by a pattern selected the matching workspaces, but its sub-filter was looked up by exact name only, so it never applied and those workspaces were extracted and published unfiltered. They now use the same lookup. The check that decides what --remove-stale manages uses it too.
  • tagDescriptions API sub-filter (API tagDescriptions are extracted with hardcoded source APIM resource IDs. #307): chooses an API's tag descriptions by name, as stored under apis/<api>/tagDescriptions/. The rest of API tagDescriptions are extracted with hardcoded source APIM resource IDs. #307 is already handled on main: publish drops the source instance's tag ID from tag descriptions (fix: strip source-service tagId from ApiTagDescription PUT payloads #313).
  • Sub-filters on an exclusion key (- '!name': {...}) are ignored with a warning, for APIs and workspaces, instead of being kept where they could never apply.
  • Docs: the filtering guide and the extract command reference describe wildcard keys, tagDescriptions and the exclusion warning; the extractor config schema describes pattern keys and tagDescriptions.

Behaviour changes users may notice

  • Workspace sub-filters keyed by a pattern now apply: a filter that relied on them being ignored extracts and publishes less.
  • A sub-filter keyed by an exclusion now logs a warning.

Validation

  • npm test: all pass except the 2 environment-related package-build integration tests that also fail on main. npm run lint and npm run build are clean.
  • Integration runs on 2026-11-06 against StandardV2 source and target instances (the filtering fixture), on the branch this change came from:
    • apis: [{'*': {operations: [], schemas: [], tagDescriptions: []}}]: every API extracted with no operation, schema or tag description folders, and no operations left in the specifications.
    • apis: [{orders: {operations: ['*']}}, {'*': {operations: []}}]: orders keeps its operations; billing has none.
    • workspaces: [{'team-*': {apis: [ws-orders], tags: []}}]: the sub-filter applies to team-a and team-b.
    • workspaces: ['*', {'!team-b': {apis: []}}]: "Sub-filter for exclusion '!team-b' … has no effect"; team-b not extracted.
    • Tag descriptions publish to another instance without error.

Related Issue(s)

Closes #316
Closes #307

… tag descriptions

A nested API filter entry applied only to the API it named, so excluding
operations or schemas from every API meant one entry per API. The key of
a nested entry can now be a wildcard pattern: it selects the matching
APIs, like a plain pattern, and its sub-filter applies to each of them:

  apis:
    - '*':
        operations: []
        schemas: []

An entry keyed by the API's name takes precedence over a pattern. One
lookup (findApiSubFilter) is now used by filtering, the specification
operation filter and API publishing.

A nested workspaces entry keyed by a pattern selected the matching
workspaces, but its sub-filter was looked up by exact name only, so it
never applied: those workspaces were extracted and published with no
filter at all. Workspace sub-filters now use the same lookup. The check
that decides what --remove-stale manages uses it too, so it follows a
pattern-keyed sub-filter. A sub-filter attached to an exclusion ('!name')
is ignored with a warning, for APIs and workspaces, instead of being kept
where it could never apply.

API sub-filters also accept tagDescriptions, to choose an API's tag
descriptions by name (as stored under apis/<api>/tagDescriptions/). The
rest of Azure#307 is already handled: tag description artifacts keep the
source instance's tag ID, but publish drops that read-only property, so
they publish to another instance (confirmed by the filtering integration
tests).

The filtering guide and the extract command reference describe wildcard
keys, tagDescriptions and the exclusion warning.

Closes Azure#316
Closes Azure#307
Copilot AI balanced review requested due to automatic review settings November 6, 2026 06:36

Copilot AI left a comment

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.

🟡 Changes recommended

Empty exact-name overrides are discarded during loading, allowing wildcard exclusions to incorrectly prevail for APIs and workspaces; preserve these entries and add loader-backed regression tests.

1 open issue
What changed in this PR

This PR extends resource filtering with wildcard API and workspace sub-filters and adds API tag-description filtering, addressing #316 and the remaining filtering work in #307.

Changes:

  • Shares sub-filter lookup across filtering, extraction, publishing, and stale-resource reconciliation, with exact-name precedence.
  • Adds tagDescriptions filtering and warnings for sub-filters attached to exclusions.
  • Updates schema descriptions, documentation, and unit tests.
File Description
tests/​unit/​services/​workspace-extractor.test.ts Tests wildcard workspace lookup and name precedence.
tests/​unit/​services/​filter-service.test.ts Tests wildcard filtering, reconciliation, and tag descriptions.
tests/​unit/​lib/​config-loader.test.ts Tests loading wildcard filters and exclusion warnings.
src/​services/​filter-service.ts Centralizes wildcard lookup and filters tag descriptions.
src/​services/​api-publisher.ts Uses shared API sub-filter lookup when planning publication.
src/​services/​api-extractor.ts Applies wildcard operation filters to exported specifications.
src/​models/​config.ts Adds tagDescriptions to API sub-filters.
src/​lib/​config-loader.ts Loads tag-description filters and warns on exclusion sub-filters.
scripts/​generate-schemas.mjs Updates generated descriptions for wildcard keys.
schemas/​v1/​extractor-config.schema.json Adds tag-description support and wildcard descriptions.
docs/​guides/​filtering-resources.md Explains wildcard precedence, tag descriptions, and exclusions.
docs/​commands/​extract.md Documents wildcard keys and tag-description filtering.

Review effort: Balanced

Comment thread src/services/filter-service.ts Resolved
…attern

The loader dropped a nested entry with no sub-resource lists (`- orders:
{}` or `- orders:`), so with `- '*': {operations: []}` beside it the
wildcard's sub-filter still applied to orders, against the rule that an
entry keyed by the name takes precedence. The same held for workspaces.

Such an entry is now kept as an empty sub-filter, which includes
everything.
Copilot AI balanced review requested due to automatic review settings November 6, 2026 07:04

Copilot AI left a comment

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.

🟢 Approval recommended

No active review issues block approval of the wildcard sub-filter and tag-description filtering changes.

1 open issue

Review effort: Balanced

This branch has not been deployed

No deployments
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.

Allow excluding schemas and operations from all APIs during extraction API tagDescriptions are extracted with hardcoded source APIM resource IDs.

2 participants