Fully align filter and override config formats with APIOps Toolkit#115
Conversation
- 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>
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>
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>
- 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>
There was a problem hiding this comment.
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
*Namesaliases + 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.yamlacross 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). |
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>
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() ?? ''; |
There was a problem hiding this comment.
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>> = { |
There was a problem hiding this comment.
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. |
| * nameParts layout for ApiOperationPolicy: [apiName, operationName] | ||
| * The grandchild name is always the fixed singleton name (e.g., "policy"). | ||
| */ | ||
| function applyGrandchildOverride( |
There was a problem hiding this comment.
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 |
| [ResourceType.PolicyFragment]: 'policyFragmentNames', | ||
| [ResourceType.VersionSet]: 'versionSetNames', | ||
| type StringArrayField = 'namedValues' | 'backends' | 'policyFragments' | 'versionSets'; | ||
| const fieldMap: Partial<Record<ResourceType, StringArrayField>> = { |
| # - name: applicationinsights | ||
| # properties: | ||
| # loggerId: "appinsights-logger-${environment}" | ||
| # verbosity: Error |
There was a problem hiding this comment.
What's this? I only see verbosity mentioned in a markdown file and here in the example overrides.
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
*Namessuffix to bare camelCase plurals matching the Toolkit (apiNames→apis,backendNames→backends, etc.)*Nameskeys accepted as backward-compatible aliases with deprecation warningsconfiguration.extract.yaml→configuration.extractor.yamlacross templates, CI/CD workflows, and documentationworkspacesfilter supportworkspaces: [](empty array) semantics to correctly exclude all workspacesOverride Configuration
NamedValueOverride,BackendOverride, etc.) with a genericOverrideEntrymodel usingproperties: Record<string, unknown>— matches the Toolkit's deep-merge behavior and is forward-compatible with any new ARM propertiesapis,backends,diagnostics,loggers,namedValues,products,subscriptions,tags,gateways,certificates,groups,policyFragments,schemas,versionSetsapimServiceNameroot-level field gracefully handled — logs info that CLI uses--service-nameflag instead, and ignores the fieldValidation & DX
apiops inittemplates with all sections and nested examplesTests
Files Changed (15)
Source (7):
config.ts,config-loader.ts,filter-service.ts,override-merger.ts,resource-publisher.ts,transitive-resolver.ts,workspace-extractor.tsTests (4):
config-loader.test.ts,filter-service.test.ts,override-merger.test.ts,resource-publisher.test.tsDocs (2):
filtering-resources.md,environment-overrides.mdTemplates (2):
filter-config.ts,override-config.ts