Skip to content

Fully align filter and override config formats with APIOps Toolkit#115

Merged
petehauge merged 8 commits into
mainfrom
fix/align-toolkit-config-format
Jun 8, 2026
Merged

Fully align filter and override config formats with APIOps Toolkit#115
petehauge merged 8 commits into
mainfrom
fix/align-toolkit-config-format

Conversation

@petehauge

@petehauge petehauge commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fully aligns the apiops-cli filter and override configuration formats with the APIOps Toolkit so customers can use their existing Toolkit configuration files without any changes.

Closes #114

Changes

Filter Configuration

  • Renamed all filter keys from *Names suffix to bare camelCase plurals matching the Toolkit (apiNamesapis, backendNamesbackends, etc.)
  • Legacy *Names keys accepted as backward-compatible aliases with deprecation warnings
  • Renamed filter config filename from configuration.extract.yamlconfiguration.extractor.yaml across templates, CI/CD workflows, and documentation
  • Added nested API sub-resource filtering — per-API control over operations, diagnostics, schemas, and releases
  • Added workspaces filter support
  • Fixed workspaces: [] (empty array) semantics to correctly exclude all workspaces

Override Configuration

  • Replaced typed override interfaces (NamedValueOverride, BackendOverride, etc.) with a generic OverrideEntry model using properties: Record<string, unknown> — matches the Toolkit's deep-merge behavior and is forward-compatible with any new ARM properties
  • All 14 Toolkit override sections now supported: apis, backends, diagnostics, loggers, namedValues, products, subscriptions, tags, gateways, certificates, groups, policyFragments, schemas, versionSets
  • Nested child overrides (e.g., API → Diagnostics, API → Operations, API → Policy, Product → Policy)
  • 3-level grandchild overrides (API → Operation → Policy)
  • Policy overrides now applied during publish (matching Toolkit behavior)
  • Case-insensitive override name matching
  • Duplicate override name detection with warnings
  • apimServiceName root-level field gracefully handled — logs info that CLI uses --service-name flag instead, and ignores the field

Validation & DX

  • Unknown filter/override keys produce warnings instead of silently ignoring
  • Updated apiops init templates with all sections and nested examples
  • Updated docs (filtering-resources.md, environment-overrides.md) with full format reference

Tests

  • 953 tests passing (18 new tests for nested filter/override functionality)
  • Lint and TypeScript compilation clean

Files Changed (15)

Source (7): config.ts, config-loader.ts, filter-service.ts, override-merger.ts, resource-publisher.ts, transitive-resolver.ts, workspace-extractor.ts
Tests (4): config-loader.test.ts, filter-service.test.ts, override-merger.test.ts, resource-publisher.test.ts
Docs (2): filtering-resources.md, environment-overrides.md
Templates (2): filter-config.ts, override-config.ts

- Rename filter config keys from *Names suffix to bare camelCase plurals
  (e.g., apiNames -> apis, backendNames -> backends, versionSetNames -> versionSets)
  to match the Toolkit's configuration.extractor.yaml schema
- Rename filter config filename from configuration.extract.yaml to
  configuration.extractor.yaml across templates, CI/CD workflows, and docs
- Add graceful handling for apimServiceName in override config (Toolkit
  uses this for target APIM instance; CLI logs info and ignores it)
- Override config format already aligned (same section names and
  properties wrapper structure as Toolkit)
- Update all 13 test files, 7 docs, CI/CD templates, and specs

Closes #114

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@petehauge petehauge changed the title feat: align filter and override config formats with APIOps Toolkit Align filter format with APIOps Toolkit Jun 6, 2026
@petehauge petehauge marked this pull request as draft June 6, 2026 22:02
The config loader now accepts both Toolkit-style keys (e.g., apis,
backends, versionSets) and legacy *Names keys (e.g., apiNames,
backendNames, versionSetNames). Legacy keys emit a deprecation
warning. Using both forms for the same field is an error.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread docs/guides/migration-from-v1.md Outdated
Use "APIOps Toolkit" instead of "v1" and "apiops-cli" instead of "v2"
throughout the migration guide for clarity.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@petehauge petehauge marked this pull request as ready for review June 6, 2026 23:04
Peter Hauge and others added 2 commits June 7, 2026 20:24
- Added orchestration logs for ApiOpsLead architecture review (approval with follow-up)
- Added orchestration log for CodeReviewer standards review (5 required changes)
- Added session log summarizing both reviews
- Merged issue #114 reviews from decisions/inbox to decisions.md
- Removed processed inbox files

Closes #114
- Generic OverrideEntry model with recursive children (max 3 levels)
- All 14 Toolkit override sections supported (apis, backends, diagnostics, etc.)
- Nested API sub-resource filtering (operations, diagnostics, schemas, releases)
- Nested override children (ApiDiagnostic, ApiOperation, ApiPolicy, etc.)
- 3-level grandchild overrides (ApiOperationPolicy)
- Policy override support in publish path
- Workspace filter empty-array semantics fix
- Duplicate override name warnings
- Case-insensitive override matching
- Updated docs, templates, and 18 new tests (953 total)

Closes #114

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@petehauge petehauge changed the title Align filter format with APIOps Toolkit feat: Fully align filter and override config formats with APIOps Toolkit Jun 8, 2026
@petehauge petehauge changed the title feat: Fully align filter and override config formats with APIOps Toolkit Fully align filter and override config formats with APIOps Toolkit Jun 8, 2026
@petehauge petehauge requested review from EMaher and Copilot June 8, 2026 13:29

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.

Pull request overview

This PR updates apiops-cli to accept APIOps Toolkit-aligned YAML configuration formats for extraction filters and publish overrides, and propagates the new defaults across templates, docs, and tests.

Changes:

  • Renames filter keys to Toolkit-style plurals (with legacy *Names aliases + warnings) and introduces nested API sub-resource filtering.
  • Expands override normalization/merging toward a generic properties + nested-children model, and applies policy overrides during publish.
  • Renames the default filter filename to configuration.extractor.yaml across init/templates/docs.

Reviewed changes

Copilot reviewed 37 out of 37 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/lib/config-loader.ts Parses Toolkit-style filter keys (with legacy aliases), nested API/workspace filter entries, and normalizes overrides.
src/models/config.ts Updates FilterConfig key names and introduces generic OverrideEntry/OverrideSection.
src/services/filter-service.ts Applies Toolkit-style filter keys and API sub-resource filtering semantics.
src/services/override-merger.ts Applies override deep-merge with support for nested override lookups.
src/services/resource-publisher.ts Applies overrides to policy payloads before PUT.
src/services/workspace-extractor.ts Updates workspace filtering semantics and empty-array handling.
src/services/transitive-resolver.ts Updates transitive dependency expansion to new filter keys.
src/services/init-service.ts Generates configuration.extractor.yaml and updates conflict detection/output listing.
src/templates/configs/filter-config.ts Updates filter template keys + adds nested API/workspace examples.
src/templates/configs/override-config.ts Expands override template examples and notes Toolkit section support.
src/templates/github-actions/extract-workflow.ts Switches workflow option/command to configuration.extractor.yaml.
src/templates/azure-devops/extract-pipeline.ts Switches pipeline option/command to configuration.extractor.yaml.
docs/guides/filtering-resources.md Documents new filter keys and nested filtering.
docs/guides/environment-overrides.md Documents expanded override sections and nested override examples.
docs/reference/configuration.md Updates default filter filename + sample keys.
docs/commands/init.md Updates generated-files docs for new filter filename.
docs/commands/extract.md Updates examples to new filter filename + keys.
docs/ci-cd/github-actions.md Updates config choice option to new filename.
docs/ci-cd/azure-devops.md Updates config choice option and flowchart to new filename.
docs/guides/migration-from-v1.md Rewords Toolkit references and updates filter key examples.
specs/contracts/cli-commands.md Updates init outputs to new filter filename.
.squad/decisions/decisions.md Adds decision log entries related to issue #114.
tests/unit/lib/config-loader.test.ts Updates tests for new filter keys, legacy alias support, nested filter parsing, and override normalization.
tests/unit/services/filter-service.test.ts Updates tests for new filter keys + API sub-filter behavior + workspace filtering.
tests/unit/services/override-merger.test.ts Updates tests for override shape and adds nested override scenarios.
tests/unit/services/resource-publisher.test.ts Updates overrides shape usage in publish tests.
tests/unit/services/extract-service.test.ts Updates filter key usage in extract tests.
tests/unit/services/resource-extractor.test.ts Updates named values filter key usage.
tests/unit/services/workspace-extractor.test.ts Updates workspace filter key usage.
tests/unit/services/transitive-resolver.test.ts Updates transitive resolver tests to new filter keys.
tests/unit/services/init-service.test.ts Updates expected generated filename and conflict mocks.
tests/unit/templates/configs/config-templates.test.ts Updates template assertions for new keys/filename.
tests/unit/templates/github-actions/extract-workflow.test.ts Updates workflow template assertions for new filename.
tests/unit/templates/azure-devops/extract-pipeline.test.ts Updates pipeline template assertions for new filename.
tests/unit/services/delete-unmatched-service.test.ts Renames local variables in assertions (no functional change).
tests/unit/services/api-product-extractor.test.ts Updates API filter key usage in revision filtering test.
tests/unit/clients/artifact-store.test.ts Renames local variables in assertions (no functional change).

Comment thread src/services/override-merger.ts Outdated
Comment thread src/services/override-merger.ts Outdated
Comment thread src/services/override-merger.ts Outdated
Comment thread src/lib/config-loader.ts
Comment thread docs/commands/init.md
Comment thread docs/guides/filtering-resources.md
Comment thread tests/unit/services/override-merger.test.ts
Comment thread tests/unit/services/override-merger.test.ts
Comment thread src/services/override-merger.ts
Bug fixes:
- ServicePolicy override no longer throws RangeError (nameParts: [])
- ApiPolicy/ProductPolicy singleton child overrides now use fixed name "policy"
- ApiOperationPolicy grandchild override uses correct 2-part nameParts
- Recursive override parser passes bare section kind for child lookup
- Tests updated to use verified descriptor nameParts from buildDescriptor

Parity additions:
- Added policies filter key for ServicePolicy (Toolkit parity)
- Strip apiRevision/isCurrent from API overrides (matches Toolkit)
- Workspace sub-filter docs marked as not yet implemented (#119)

957 tests pass, lint and TypeScript clean.

Closes #114

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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.

Pull request overview

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

Comment thread src/lib/config-loader.ts
Comment thread docs/commands/init.md
Peter Hauge and others added 2 commits June 8, 2026 07:38
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
*/
function getSingletonFilterName(type: ResourceType): string {
const meta = RESOURCE_TYPE_METADATA[type];
return meta.armPathSuffix.split('/').pop() ?? '';

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.

There are several helper functions in resource-paths.ts library for getting parts of paths. Randome split/regex calls always make me a little nervous in terms of maintainabilty

/**
* Map resource types to their top-level override config section key.
*/
const OVERRIDE_SECTION_MAP: Partial<Record<ResourceType, keyof OverrideConfig>> = {

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.

Adding const arrays in each other libraries makes it harder in the future to add a new resource type. Unless there is a good reason, adding a property like supportsOverrideSection or similar to the RESOURCE_TYPE_METADATA would make it easier to add a type in the future.

let overrideProperties = entry.properties;

// Deep-merge the override into the resource JSON
// Strip apiRevision and isCurrent from API overrides — matches Toolkit behavior.

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.

Maybe add this to the spec?

* nameParts layout for ApiOperationPolicy: [apiName, operationName]
* The grandchild name is always the fixed singleton name (e.g., "policy").
*/
function applyGrandchildOverride(

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.

Having the section -> child -> grand child relation ship hard coded in make me nervous for future maintenance. What if another level is added in the future. Workspaces is a good example of another layer of resources being added. I had actually ripped out the parent-> child -> grandchild stuff when I was working on the publish service.

const grandchildSection = childEntry.children[mapping.grandchildKey];
if (!grandchildSection) return { ...json };

// Grandchild is always a singleton (e.g., "policy") — name is NOT in nameParts

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.

Really?

[ResourceType.PolicyFragment]: 'policyFragmentNames',
[ResourceType.VersionSet]: 'versionSetNames',
type StringArrayField = 'namedValues' | 'backends' | 'policyFragments' | 'versionSets';
const fieldMap: Partial<Record<ResourceType, StringArrayField>> = {

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.

Same comment as above.

# - name: applicationinsights
# properties:
# loggerId: "appinsights-logger-${environment}"
# verbosity: Error

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.

What's this? I only see verbosity mentioned in a markdown file and here in the example overrides.

@petehauge petehauge merged commit a495dd7 into main Jun 8, 2026
5 checks passed
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.

Fully align filter and override configuration formats with APIOps Toolkit

3 participants